use of android.text.TextPaint in project Jota-Text-Editor-old by jiro-aqua.
the class StaticLayout method generate.
/* package */
void generate(CharSequence source, int bufstart, int bufend, TextPaint paint, int outerwidth, Alignment align, float spacingmult, float spacingadd, boolean includepad, boolean trackpad, boolean breakOnlyAtSpaces, float ellipsizedWidth, TextUtils.TruncateAt where, boolean showTab) {
// Jota Text Editor
mLineCount = 0;
int v = 0;
boolean needMultiply = (spacingmult != 1 || spacingadd != 0);
Paint.FontMetricsInt fm = mFontMetricsInt;
int[] choosehtv = null;
int end = TextUtils.indexOf(source, '\n', bufstart, bufend);
int bufsiz = end >= 0 ? end - bufstart : bufend - bufstart;
boolean first = true;
if (mChdirs == null) {
mChdirs = new byte[ArrayUtils.idealByteArraySize(bufsiz + 1)];
mChs = new char[ArrayUtils.idealCharArraySize(bufsiz + 1)];
mWidths = new float[ArrayUtils.idealIntArraySize((bufsiz + 1) * 2)];
}
byte[] chdirs = mChdirs;
char[] chs = mChs;
float[] widths = mWidths;
AlteredCharSequence alter = null;
// Jota Text Editor
// Spanned spanned = null;
// if (source instanceof Spanned)
// spanned = (Spanned) source;
// XXX
int DEFAULT_DIR = DIR_LEFT_TO_RIGHT;
for (int start = bufstart; start <= bufend; start = end) {
if (first)
first = false;
else
end = TextUtils.indexOf(source, '\n', start, bufend);
if (end < 0)
end = bufend;
else
end++;
int firstWidthLineCount = 1;
int firstwidth = outerwidth;
int restwidth = outerwidth;
LineHeightSpan[] chooseht = null;
if (end - start > chdirs.length) {
chdirs = new byte[ArrayUtils.idealByteArraySize(end - start)];
mChdirs = chdirs;
}
if (end - start > chs.length) {
chs = new char[ArrayUtils.idealCharArraySize(end - start)];
mChs = chs;
}
if ((end - start) * 2 > widths.length) {
widths = new float[ArrayUtils.idealIntArraySize((end - start) * 2)];
mWidths = widths;
}
TextUtils.getChars(source, start, end, chs, 0);
final int n = end - start;
boolean easy = true;
boolean altered = false;
// XXX
int dir = DEFAULT_DIR;
for (int i = 0; i < n; i++) {
if (chs[i] >= FIRST_RIGHT_TO_LEFT) {
easy = false;
break;
}
}
if (!easy) {
// XXX put override flags, etc. into chdirs
dir = bidi(dir, chs, chdirs, n, false);
for (int i = 0; i < n; i++) {
if (chdirs[i] == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
int j;
for (j = i; j < n; j++) {
if (chdirs[j] != Character.DIRECTIONALITY_RIGHT_TO_LEFT)
break;
}
if (AndroidCharacter.mirror(chs, i, j - i))
altered = true;
i = j - 1;
}
}
}
CharSequence sub;
if (altered) {
if (alter == null)
alter = AlteredCharSequence.make(source, chs, start, end);
else
alter.update(chs, start, end);
sub = alter;
} else {
sub = source;
}
int width = firstwidth;
float w = 0;
int here = start;
int ok = start;
float okwidth = w;
int okascent = 0, okdescent = 0, oktop = 0, okbottom = 0;
int fit = start;
float fitwidth = w;
int fitascent = 0, fitdescent = 0, fittop = 0, fitbottom = 0;
boolean tab = false;
int next;
for (int i = start; i < end; i = next) {
// Jota Text Editor
// if (spanned == null)
next = end;
// else
// next = spanned.nextSpanTransition(i, end,
// MetricAffectingSpan.
// class);
// if (spanned == null) {
paint.getTextWidths(sub, i, next, widths);
System.arraycopy(widths, 0, widths, end - start + (i - start), next - i);
paint.getFontMetricsInt(fm);
// Jota Text Editor
// } else {
// mWorkPaint.baselineShift = 0;
//
// Styled.getTextWidths(paint, mWorkPaint,
// spanned, i, next,
// widths, fm);
// System.arraycopy(widths, 0, widths,
// end - start + (i - start), next - i);
//
// if (mWorkPaint.baselineShift < 0) {
// fm.ascent += mWorkPaint.baselineShift;
// fm.top += mWorkPaint.baselineShift;
// } else {
// fm.descent += mWorkPaint.baselineShift;
// fm.bottom += mWorkPaint.baselineShift;
// }
// }
int fmtop = fm.top;
int fmbottom = fm.bottom;
int fmascent = fm.ascent;
int fmdescent = fm.descent;
for (int j = i; j < next; j++) {
char c = chs[j - start];
if (c == '\n') {
// Jota Text Editor
if (!tab)
tab = showTab;
} else if (c == '\t') {
w = Layout.nextTab(sub, start, end, w, null);
tab = true;
} else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < next) {
int emoji = Character.codePointAt(chs, j - start);
if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) {
Bitmap bm = EMOJI_FACTORY.getBitmapFromAndroidPua(emoji);
if (bm != null) {
Paint whichPaint;
// Jota Text Editor
// if (spanned == null) {
whichPaint = paint;
// } else {
// whichPaint = mWorkPaint;
// }
float wid = (float) bm.getWidth() * -whichPaint.ascent() / bm.getHeight();
w += wid;
tab = true;
j++;
} else {
w += widths[j - start + (end - start)];
}
} else {
w += widths[j - start + (end - start)];
}
} else {
// Jota Text Editor
if (c == 0x3000) {
// ideographic space ( for Japanese )
if (!tab)
tab = showTab;
}
w += widths[j - start + (end - start)];
}
if (w <= width) {
fitwidth = w;
fit = j + 1;
if (fmtop < fittop)
fittop = fmtop;
if (fmascent < fitascent)
fitascent = fmascent;
if (fmdescent > fitdescent)
fitdescent = fmdescent;
if (fmbottom > fitbottom)
fitbottom = fmbottom;
if (c == ' ' || c == '\t' || ((c == '.' || c == ',' || c == ':' || c == ';') && (j - 1 < here || !Character.isDigit(chs[j - 1 - start])) && (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || ((c == '/' || c == '-') && (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || (c >= FIRST_CJK && isIdeographic(c, true) && j + 1 < next && isIdeographic(chs[j + 1 - start], false))) {
okwidth = w;
ok = j + 1;
if (fittop < oktop)
oktop = fittop;
if (fitascent < okascent)
okascent = fitascent;
if (fitdescent > okdescent)
okdescent = fitdescent;
if (fitbottom > okbottom)
okbottom = fitbottom;
}
} else if (breakOnlyAtSpaces) {
if (ok != here) {
while (ok < next && chs[ok - start] == ' ') {
ok++;
}
v = out(source, here, ok, okascent, okdescent, oktop, okbottom, v, spacingmult, spacingadd, chooseht, choosehtv, fm, tab, needMultiply, start, chdirs, dir, easy, ok == bufend, includepad, trackpad, widths, start, end - start, where, ellipsizedWidth, okwidth, paint);
here = ok;
} else {
// Act like it fit even though it didn't.
fitwidth = w;
fit = j + 1;
if (fmtop < fittop)
fittop = fmtop;
if (fmascent < fitascent)
fitascent = fmascent;
if (fmdescent > fitdescent)
fitdescent = fmdescent;
if (fmbottom > fitbottom)
fitbottom = fmbottom;
}
} else {
if (ok != here) {
while (ok < next && chs[ok - start] == ' ') {
ok++;
}
v = out(source, here, ok, okascent, okdescent, oktop, okbottom, v, spacingmult, spacingadd, chooseht, choosehtv, fm, tab, needMultiply, start, chdirs, dir, easy, ok == bufend, includepad, trackpad, widths, start, end - start, where, ellipsizedWidth, okwidth, paint);
here = ok;
} else if (fit != here) {
// Log.e("text", "output fit " + here + " to " +fit);
v = out(source, here, fit, fitascent, fitdescent, fittop, fitbottom, v, spacingmult, spacingadd, chooseht, choosehtv, fm, tab, needMultiply, start, chdirs, dir, easy, fit == bufend, includepad, trackpad, widths, start, end - start, where, ellipsizedWidth, fitwidth, paint);
here = fit;
} else {
// Log.e("text", "output one " + here + " to " +(here + 1));
measureText(paint, mWorkPaint, source, here, here + 1, fm, tab, null);
v = out(source, here, here + 1, fm.ascent, fm.descent, fm.top, fm.bottom, v, spacingmult, spacingadd, chooseht, choosehtv, fm, tab, needMultiply, start, chdirs, dir, easy, here + 1 == bufend, includepad, trackpad, widths, start, end - start, where, ellipsizedWidth, widths[here - start], paint);
here = here + 1;
}
if (here < i) {
// must remeasure
j = next = here;
} else {
// continue looping
j = here - 1;
}
ok = fit = here;
w = 0;
fitascent = fitdescent = fittop = fitbottom = 0;
okascent = okdescent = oktop = okbottom = 0;
if (--firstWidthLineCount <= 0) {
width = restwidth;
}
}
}
}
if (end != here) {
if ((fittop | fitbottom | fitdescent | fitascent) == 0) {
paint.getFontMetricsInt(fm);
fittop = fm.top;
fitbottom = fm.bottom;
fitascent = fm.ascent;
fitdescent = fm.descent;
}
// Log.e("text", "output rest " + here + " to " + end);
v = out(source, here, end, fitascent, fitdescent, fittop, fitbottom, v, spacingmult, spacingadd, chooseht, choosehtv, fm, tab, needMultiply, start, chdirs, dir, easy, end == bufend, includepad, trackpad, widths, start, end - start, where, ellipsizedWidth, w, paint);
}
start = end;
if (end == bufend)
break;
}
if (bufend == bufstart || source.charAt(bufend - 1) == '\n') {
// Log.e("text", "output last " + bufend);
paint.getFontMetricsInt(fm);
v = out(source, bufend, bufend, fm.ascent, fm.descent, fm.top, fm.bottom, v, spacingmult, spacingadd, null, null, fm, false, needMultiply, bufend, chdirs, DEFAULT_DIR, true, true, includepad, trackpad, widths, bufstart, 0, where, ellipsizedWidth, 0, paint);
}
}
use of android.text.TextPaint in project Jota-Text-Editor-old by jiro-aqua.
the class StaticLayout method getLineForVertical.
// Jota Text Editor
// private void calculateEllipsis(int linestart, int lineend,
// float[] widths, int widstart, int widoff,
// float avail, TextUtils.TruncateAt where,
// int line, float textwidth, TextPaint paint) {
// int len = lineend - linestart;
//
// if (textwidth <= avail) {
// // Everything fits!
// mLines[mColumns * line + ELLIPSIS_START] = 0;
// mLines[mColumns * line + ELLIPSIS_COUNT] = 0;
// return;
// }
//
// float ellipsiswid = paint.measureText("…");
// int ellipsisStart, ellipsisCount;
//
// if (where == TextUtils.TruncateAt.START) {
// float sum = 0;
// int i;
//
// for (i = len; i >= 0; i--) {
// float w = widths[i - 1 + linestart - widstart + widoff];
//
// if (w + sum + ellipsiswid > avail) {
// break;
// }
//
// sum += w;
// }
//
// ellipsisStart = 0;
// ellipsisCount = i;
// } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
// float sum = 0;
// int i;
//
// for (i = 0; i < len; i++) {
// float w = widths[i + linestart - widstart + widoff];
//
// if (w + sum + ellipsiswid > avail) {
// break;
// }
//
// sum += w;
// }
//
// ellipsisStart = i;
// ellipsisCount = len - i;
// } else /* where = TextUtils.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 = widths[right - 1 + linestart - widstart + widoff];
//
// if (w + rsum > ravail) {
// break;
// }
//
// rsum += w;
// }
//
// float lavail = avail - ellipsiswid - rsum;
// for (left = 0; left < right; left++) {
// float w = widths[left + linestart - widstart + widoff];
//
// if (w + lsum > lavail) {
// break;
// }
//
// lsum += w;
// }
//
// ellipsisStart = left;
// ellipsisCount = right - left;
// }
//
// mLines[mColumns * line + ELLIPSIS_START] = ellipsisStart;
// mLines[mColumns * line + ELLIPSIS_COUNT] = ellipsisCount;
// }
// Override the baseclass so we can directly access our members,
// rather than relying on member functions.
// The logic mirrors that of Layout.getLineForVertical
// FIXME: It may be faster to do a linear search for layouts without many lines.
public int getLineForVertical(int vertical) {
int high = mLineCount;
int low = -1;
int guess;
// int[] lines = mLines;
while (high - low > 1) {
guess = (high + low) >> 1;
if (guess * mHeight > vertical) {
// Jota Text Editor
high = guess;
} else {
low = guess;
}
}
if (low < 0) {
return 0;
} else {
return low;
}
}
use of android.text.TextPaint in project Jota-Text-Editor-old by jiro-aqua.
the class StaticLayout method out.
/*
private static void dump(byte[] data, int count, String label) {
if (false) {
System.out.print(label);
for (int i = 0; i < count; i++)
System.out.print(" " + data[i]);
System.out.println();
}
}
*/
// Jota Text Editor
// private static int getFit(TextPaint paint,
// TextPaint workPaint,
// CharSequence text, int start, int end,
// float wid) {
// int high = end + 1, low = start - 1, guess;
//
// while (high - low > 1) {
// guess = (high + low) / 2;
//
// if (measureText(paint, workPaint,
// text, start, guess, null, true, null) > wid)
// high = guess;
// else
// low = guess;
// }
//
// if (low < start)
// return start;
// else
// return low;
// }
private int out(CharSequence text, int start, int end, int above, int below, int top, int bottom, int v, float spacingmult, float spacingadd, LineHeightSpan[] chooseht, int[] choosehtv, Paint.FontMetricsInt fm, boolean tab, boolean needMultiply, int pstart, byte[] chdirs, int dir, boolean easy, boolean last, boolean includepad, boolean trackpad, float[] widths, int widstart, int widoff, TextUtils.TruncateAt ellipsize, float ellipsiswidth, float textwidth, TextPaint paint) {
int j = mLineCount;
// Jota Text Editor
int off = j * 1;
int want = off + 1 + TOP;
// Jota Text Editor
// int want2 = j + TOP;
int[] lines = mLines;
if (want >= lines.length) {
int nlen = ArrayUtils.idealIntArraySize(want + 1);
int[] grow = new int[nlen];
System.arraycopy(lines, 0, grow, 0, lines.length);
mLines = grow;
lines = grow;
}
if (chooseht != null) {
fm.ascent = above;
fm.descent = below;
fm.top = top;
fm.bottom = bottom;
for (int i = 0; i < chooseht.length; i++) {
if (chooseht[i] instanceof LineHeightSpan.WithDensity) {
((LineHeightSpan.WithDensity) chooseht[i]).chooseHeight(text, start, end, choosehtv[i], v, fm, paint);
} else {
chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
}
}
above = fm.ascent;
below = fm.descent;
top = fm.top;
bottom = fm.bottom;
}
if (j == 0) {
if (trackpad) {
mTopPadding = top - above;
}
if (includepad) {
above = top;
}
}
if (last) {
if (trackpad) {
mBottomPadding = bottom - below;
}
if (includepad) {
below = bottom;
}
}
int extra;
if (needMultiply) {
double ex = (below - above) * (spacingmult - 1) + spacingadd;
if (ex >= 0) {
extra = (int) (ex + 0.5);
} else {
extra = -(int) (-ex + 0.5);
}
} else {
extra = 0;
}
lines[off + START] = start;
// Jota Text Editor
// lines[off + TOP] = v;
// lines[off + DESCENT] = below + extra;
// v += (below - above) + extra;
// lines[off + mColumns + START] = end;
// lines[off + mColumns + TOP] = v;
mHeight = (below - above) + extra;
mDescent = below + extra;
if (tab)
lines[off + TAB] |= TAB_MASK;
{
lines[off + DIR] |= dir << DIR_SHIFT;
int cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
int count = 0;
if (!easy) {
for (int k = start; k < end; k++) {
if (chdirs[k - pstart] != cur) {
count++;
cur = chdirs[k - pstart];
}
}
}
// Jota Text Editor
// Directions linedirs;
//
// if (count == 0) {
// linedirs = DIRS_ALL_LEFT_TO_RIGHT;
// } else {
// short[] ld = new short[count + 1];
//
// cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
// count = 0;
// int here = start;
//
// for (int k = start; k < end; k++) {
// if (chdirs[k - pstart] != cur) {
// // XXX check to make sure we don't
// // overflow short
// ld[count++] = (short) (k - here);
// cur = chdirs[k - pstart];
// here = k;
// }
// }
//
// ld[count] = (short) (end - here);
//
// if (count == 1 && ld[0] == 0) {
// linedirs = DIRS_ALL_RIGHT_TO_LEFT;
// } else {
// linedirs = new Directions(ld);
// }
// }
// mLineDirections[j] = linedirs;
// If ellipsize is in marquee mode, do not apply ellipsis on the first line
// Jota Text Editor
// if (ellipsize != null && (ellipsize != TextUtils.TruncateAt.MARQUEE || j != 0)) {
// calculateEllipsis(start, end, widths, widstart, widoff,
// ellipsiswidth, ellipsize, j,
// textwidth, paint);
// }
}
mLineCount++;
return v;
}
use of android.text.TextPaint in project Jota-Text-Editor-old by jiro-aqua.
the class Styled method drawUniformRun.
/**
* Draws and/or measures a uniform run of text on a single line. No span of
* interest should start or end in the middle of this run (if not
* drawing, character spans that don't affect metrics can be ignored).
* Neither should the run direction change in the middle of the run.
*
* <p>The x position is the leading edge of the text. In a right-to-left
* paragraph, this will be to the right of the text to be drawn. Paint
* should not have an Align value other than LEFT or positioning will get
* confused.
*
* <p>On return, workPaint will reflect the original paint plus any
* modifications made by character styles on the run.
*
* <p>The returned width is signed and will be < 0 if the paragraph
* direction is right-to-left.
*/
private static float drawUniformRun(Canvas canvas, Spanned text, int start, int end, int dir, boolean runIsRtl, float x, int top, int y, int bottom, Paint.FontMetricsInt fmi, TextPaint paint, TextPaint workPaint, boolean needWidth) {
boolean haveWidth = false;
float ret = 0;
CharacterStyle[] spans = text.getSpans(start, end, CharacterStyle.class);
ReplacementSpan replacement = null;
// XXX: This shouldn't be modifying paint, only workPaint.
// However, the members belonging to TextPaint should have default
// values anyway. Better to ensure this in the Layout constructor.
paint.bgColor = 0;
paint.baselineShift = 0;
workPaint.set(paint);
if (spans.length > 0) {
for (int i = 0; i < spans.length; i++) {
CharacterStyle span = spans[i];
if (span instanceof ReplacementSpan) {
replacement = (ReplacementSpan) span;
} else {
span.updateDrawState(workPaint);
}
}
}
if (replacement == null) {
CharSequence tmp;
int tmpstart, tmpend;
if (runIsRtl) {
tmp = TextUtils.getReverse(text, start, end);
tmpstart = 0;
// XXX: assumes getReverse doesn't change the length of the text
tmpend = end - start;
} else {
tmp = text;
tmpstart = start;
tmpend = end;
}
if (fmi != null) {
workPaint.getFontMetricsInt(fmi);
}
if (canvas != null) {
if (workPaint.bgColor != 0) {
int c = workPaint.getColor();
Paint.Style s = workPaint.getStyle();
workPaint.setColor(workPaint.bgColor);
workPaint.setStyle(Paint.Style.FILL);
if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
haveWidth = true;
}
if (dir == Layout.DIR_RIGHT_TO_LEFT)
canvas.drawRect(x - ret, top, x, bottom, workPaint);
else
canvas.drawRect(x, top, x + ret, bottom, workPaint);
workPaint.setStyle(s);
workPaint.setColor(c);
}
if (dir == Layout.DIR_RIGHT_TO_LEFT) {
if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
haveWidth = true;
}
canvas.drawText(tmp, tmpstart, tmpend, x - ret, y + workPaint.baselineShift, workPaint);
} else {
if (needWidth) {
if (!haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
haveWidth = true;
}
}
canvas.drawText(tmp, tmpstart, tmpend, x, y + workPaint.baselineShift, workPaint);
}
} else {
if (needWidth && !haveWidth) {
ret = workPaint.measureText(tmp, tmpstart, tmpend);
haveWidth = true;
}
}
} else {
ret = replacement.getSize(workPaint, text, start, end, fmi);
if (canvas != null) {
if (dir == Layout.DIR_RIGHT_TO_LEFT)
replacement.draw(canvas, text, start, end, x - ret, top, y, bottom, workPaint);
else
replacement.draw(canvas, text, start, end, x, top, y, bottom, workPaint);
}
}
if (dir == Layout.DIR_RIGHT_TO_LEFT)
return -ret;
else
return ret;
}
use of android.text.TextPaint in project Jota-Text-Editor-old by jiro-aqua.
the class BoringLayout method init.
/* package */
void init(CharSequence source, TextPaint paint, int outerwidth, Alignment align, float spacingmult, float spacingadd, BoringLayout.Metrics metrics, boolean includepad, boolean trustWidth) {
int spacing;
if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
mDirect = source.toString();
} else {
mDirect = null;
}
mPaint = paint;
if (includepad) {
spacing = metrics.bottom - metrics.top;
} else {
spacing = metrics.descent - metrics.ascent;
}
if (spacingmult != 1 || spacingadd != 0) {
spacing = (int) (spacing * spacingmult + spacingadd + 0.5f);
}
mBottom = spacing;
if (includepad) {
mDesc = spacing + metrics.top;
} else {
mDesc = spacing + metrics.ascent;
}
if (trustWidth) {
mMax = metrics.width;
} else {
/*
* If we have ellipsized, we have to actually calculate the
* width because the width that was passed in was for the
* full text, not the ellipsized form.
*/
synchronized (sTemp) {
mMax = (int) (FloatMath.ceil(Styled.measureText(paint, sTemp, source, 0, source.length(), null)));
}
}
if (includepad) {
mTopPadding = metrics.top - metrics.ascent;
mBottomPadding = metrics.bottom - metrics.descent;
}
}
Aggregations