summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaph Levien <raph@google.com>2015-11-30 21:05:46 -0800
committerRaph Levien <raph@google.com>2016-01-11 21:43:24 +0000
commit909c7bca570b6f50650d0872e2037389b29252e3 (patch)
treefd5cb60a11745eb78deca124d5236e166afd8543
parentd3b2826a1a3ff128db1e89a081124192ac70c509 (diff)
downloadframeworks_base-909c7bca570b6f50650d0872e2037389b29252e3.zip
frameworks_base-909c7bca570b6f50650d0872e2037389b29252e3.tar.gz
frameworks_base-909c7bca570b6f50650d0872e2037389b29252e3.tar.bz2
Fix measurement to respect grapheme and span boundaries
When measuring in TextLine (important for cursor positioning), the substring measured must neither be too short (it can't just be the substring up to the measure limit, but must include additional characters if they form a ligature) nor too long (it can't extend beyond the end of the CharacterStyle span, otherwise the measurement fails to account for the fact that the CharacterStyle span boundary breaks the ligature). This patch gets it just right. Bug: 25375561 Change-Id: I36e1c4bdc66424d3b611cf54031756cf54cf3fec
-rw-r--r--core/java/android/text/TextLine.java18
1 files changed, 10 insertions, 8 deletions
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 39e8694..3592187 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -718,13 +718,14 @@ class TextLine {
* @param bottom the bottom of the line
* @param fmi receives metrics information, can be null
* @param needWidth true if the width of the run is needed
+ * @param offset the offset for the purpose of measuring
* @return the signed width of the run based on the run direction; only
* valid if needWidth is true
*/
private float handleText(TextPaint wp, int start, int end,
int contextStart, int contextEnd, boolean runIsRtl,
Canvas c, float x, int top, int y, int bottom,
- FontMetricsInt fmi, boolean needWidth) {
+ FontMetricsInt fmi, boolean needWidth, int offset) {
// Get metrics first (even for empty strings or "0" width runs)
if (fmi != null) {
@@ -742,11 +743,11 @@ class TextLine {
if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) {
if (mCharsValid) {
ret = wp.getRunAdvance(mChars, start, end, contextStart, contextEnd,
- runIsRtl, end);
+ runIsRtl, offset);
} else {
int delta = mStart;
ret = wp.getRunAdvance(mText, delta + start, delta + end,
- delta + contextStart, delta + contextEnd, runIsRtl, delta + end);
+ delta + contextStart, delta + contextEnd, runIsRtl, delta + offset);
}
}
@@ -895,8 +896,8 @@ class TextLine {
TextPaint wp = mWorkPaint;
wp.set(mPaint);
final int mlimit = measureLimit;
- return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top,
- y, bottom, fmi, needWidth || mlimit < measureLimit);
+ return handleText(wp, start, limit, start, limit, runIsRtl, c, x, top,
+ y, bottom, fmi, needWidth || mlimit < measureLimit, mlimit);
}
mMetricAffectingSpanSpanSet.init(mSpanned, mStart + start, mStart + limit);
@@ -940,13 +941,14 @@ class TextLine {
}
for (int j = i, jnext; j < mlimit; j = jnext) {
- jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + mlimit) -
+ jnext = mCharacterStyleSpanSet.getNextTransition(mStart + j, mStart + inext) -
mStart;
+ int offset = Math.min(jnext, mlimit);
wp.set(mPaint);
for (int k = 0; k < mCharacterStyleSpanSet.numberOfSpans; k++) {
// Intentionally using >= and <= as explained above
- if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + jnext) ||
+ if ((mCharacterStyleSpanSet.spanStarts[k] >= mStart + offset) ||
(mCharacterStyleSpanSet.spanEnds[k] <= mStart + j)) continue;
CharacterStyle span = mCharacterStyleSpanSet.spans[k];
@@ -958,7 +960,7 @@ class TextLine {
wp.setHyphenEdit(0);
}
x += handleText(wp, j, jnext, i, inext, runIsRtl, c, x,
- top, y, bottom, fmi, needWidth || jnext < measureLimit);
+ top, y, bottom, fmi, needWidth || jnext < measureLimit, offset);
}
}