Loading core/java/android/text/Layout.java +46 −0 Original line number Original line Diff line number Diff line Loading @@ -2360,6 +2360,52 @@ public abstract class Layout { public Directions(int[] dirs) { public Directions(int[] dirs) { mDirections = dirs; mDirections = dirs; } } /** * Returns number of BiDi runs. * * @hide */ public @IntRange(from = 0) int getRunCount() { return mDirections.length / 2; } /** * Returns the start offset of the BiDi run. * * @param runIndex the index of the BiDi run * @return the start offset of the BiDi run. * @hide */ public @IntRange(from = 0) int getRunStart(@IntRange(from = 0) int runIndex) { return mDirections[runIndex * 2]; } /** * Returns the length of the BiDi run. * * Note that this method may return too large number due to reducing the number of object * allocations. The too large number means the remaining part is assigned to this run. The * caller must clamp the returned value. * * @param runIndex the index of the BiDi run * @return the length of the BiDi run. * @hide */ public @IntRange(from = 0) int getRunLength(@IntRange(from = 0) int runIndex) { return mDirections[runIndex * 2 + 1] & RUN_LENGTH_MASK; } /** * Returns true if the BiDi run is RTL. * * @param runIndex the index of the BiDi run * @return true if the BiDi run is RTL. * @hide */ public boolean isRunRtl(int runIndex) { return (mDirections[runIndex * 2 + 1] & RUN_RTL_FLAG) != 0; } } } /** /** Loading core/java/android/text/TextLine.java +94 −142 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; package android.text; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.annotation.UnsupportedAppUsage; Loading Loading @@ -51,6 +52,8 @@ import java.util.ArrayList; public class TextLine { public class TextLine { private static final boolean DEBUG = false; private static final boolean DEBUG = false; private static final char TAB_CHAR = '\t'; private TextPaint mPaint; private TextPaint mPaint; @UnsupportedAppUsage @UnsupportedAppUsage private CharSequence mText; private CharSequence mText; Loading Loading @@ -232,6 +235,10 @@ public class TextLine { mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0; mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0; } } private char charAt(int i) { return mCharsValid ? mChars[i] : mText.charAt(i + mStart); } /** /** * Justify the line to the given width. * Justify the line to the given width. */ */ Loading Loading @@ -261,51 +268,23 @@ public class TextLine { * @param bottom the bottom of the line * @param bottom the bottom of the line */ */ void draw(Canvas c, float x, int top, int y, int bottom) { void draw(Canvas c, float x, int top, int y, int bottom) { if (!mHasTabs) { if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { drawRun(c, 0, mLen, false, x, top, y, bottom, false); return; } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { drawRun(c, 0, mLen, true, x, top, y, bottom, false); return; } } float h = 0; float h = 0; int[] runs = mDirections.mDirections; final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); int lastRunIndex = runs.length - 2; int segStart = runStart; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { h += drawRun(c, segStart, j, runIsRtl, x + h, top, y, bottom, codept = mChars[j]; runIndex != (runCount - 1) || j != mLen); if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { codept = Character.codePointAt(mChars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR h += drawRun(c, segstart, j, runIsRtl, x+h, top, y, bottom, i != lastRunIndex || j != mLen); if (codept == '\t') { h = mDir * nextTab(h * mDir); h = mDir * nextTab(h * mDir); } } segstart = j + 1; segStart = j + 1; } } } } } } Loading @@ -323,75 +302,81 @@ public class TextLine { } } /** /** * Returns information about a position on the line. * Returns the signed graphical offset from the leading margin. * * * @param offset the line-relative character offset, between 0 and the * Following examples are all for measuring offset=3. LX(e.g. L0, L1, ...) denotes a * line length, inclusive * character which has LTR BiDi property. On the other hand, RX(e.g. R0, R1, ...) denotes a * @param trailing true to measure the trailing edge of the character * character which has RTL BiDi property. Assuming all character has 1em width. * before offset, false to measure the leading edge of the character * * at offset. * Example 1: All LTR chars within LTR context * @param fmi receives metrics information about the requested * Input Text (logical) : L0 L1 L2 L3 L4 L5 L6 L7 L8 * character, can be null. * Input Text (visual) : L0 L1 L2 L3 L4 L5 L6 L7 L8 * @return the signed offset from the leading margin to the requested * Output(trailing=true) : |--------| (Returns 3em) * character edge. * Output(trailing=false): |--------| (Returns 3em) * * Example 2: All RTL chars within RTL context. * Input Text (logical) : R0 R1 R2 R3 R4 R5 R6 R7 R8 * Input Text (visual) : R8 R7 R6 R5 R4 R3 R2 R1 R0 * Output(trailing=true) : |--------| (Returns -3em) * Output(trailing=false): |--------| (Returns -3em) * * Example 3: BiDi chars within LTR context. * Input Text (logical) : L0 L1 L2 R3 R4 R5 L6 L7 L8 * Input Text (visual) : L0 L1 L2 R5 R4 R3 L6 L7 L8 * Output(trailing=true) : |-----------------| (Returns 6em) * Output(trailing=false): |--------| (Returns 3em) * * Example 4: BiDi chars within RTL context. * Input Text (logical) : L0 L1 L2 R3 R4 R5 L6 L7 L8 * Input Text (visual) : L6 L7 L8 R5 R4 R3 L0 L1 L2 * Output(trailing=true) : |-----------------| (Returns -6em) * Output(trailing=false): |--------| (Returns -3em) * * @param offset the line-relative character offset, between 0 and the line length, inclusive * @param trailing no effect if the offset is not on the BiDi transition offset. If the offset * is on the BiDi transition offset and true is passed, the offset is regarded * as the edge of the trailing run's edge. If false, the offset is regarded as * the edge of the preceding run's edge. See example above. * @param fmi receives metrics information about the requested character, can be null * @return the signed graphical offset from the leading margin to the requested character edge. * The positive value means the offset is right from the leading edge. The negative * value means the offset is left from the leading edge. */ */ public float measure(int offset, boolean trailing, FontMetricsInt fmi) { public float measure(@IntRange(from = 0) int offset, boolean trailing, int target = trailing ? offset - 1 : offset; @NonNull FontMetricsInt fmi) { if (offset > mLen) { throw new IndexOutOfBoundsException( "offset(" + offset + ") should be less than line limit(" + mLen + ")"); } final int target = trailing ? offset - 1 : offset; if (target < 0) { if (target < 0) { return 0; return 0; } } float h = 0; float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); if (!mHasTabs) { int segStart = runStart; if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { return measureRun(0, offset, mLen, false, fmi); } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { return measureRun(0, offset, mLen, true, fmi); } } char[] chars = mChars; int[] runs = mDirections.mDirections; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { final boolean targetIsInThisSegment = target >= segStart && target < j; codept = chars[j]; final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { codept = Character.codePointAt(chars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { boolean inSegment = target >= segstart && target < j; boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (targetIsInThisSegment && sameDirection) { if (inSegment && advance) { return h + measureRun(segStart, offset, j, runIsRtl, fmi); return h + measureRun(segstart, offset, j, runIsRtl, fmi); } } float w = measureRun(segstart, j, j, runIsRtl, fmi); final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi); h += advance ? w : -w; h += sameDirection ? segmentWidth : -segmentWidth; if (inSegment) { if (targetIsInThisSegment) { return h + measureRun(segstart, offset, j, runIsRtl, null); return h + measureRun(segStart, offset, j, runIsRtl, null); } } if (codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR if (offset == j) { if (offset == j) { return h; return h; } } Loading @@ -401,7 +386,7 @@ public class TextLine { } } } } segstart = j + 1; segStart = j + 1; } } } } } } Loading @@ -426,62 +411,29 @@ public class TextLine { } } float h = 0; float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); if (!mHasTabs) { int segStart = runStart; if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { for (int offset = 0; offset <= mLen; ++offset) { measurement[offset] = measureRun(0, offset, mLen, false, fmi); } return measurement; } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { for (int offset = 0; offset <= mLen; ++offset) { measurement[offset] = measureRun(0, offset, mLen, true, fmi); } return measurement; } } char[] chars = mChars; int[] runs = mDirections.mDirections; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i + 1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i + 1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { final float oldh = h; codept = chars[j]; final boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { final float w = measureRun(segStart, j, j, runIsRtl, fmi); codept = Character.codePointAt(chars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { float oldh = h; boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; float w = measureRun(segstart, j, j, runIsRtl, fmi); h += advance ? w : -w; h += advance ? w : -w; float baseh = advance ? oldh : h; final float baseh = advance ? oldh : h; FontMetricsInt crtfmi = advance ? fmi : null; FontMetricsInt crtfmi = advance ? fmi : null; for (int offset = segstart; offset <= j && offset <= mLen; ++offset) { for (int offset = segStart; offset <= j && offset <= mLen; ++offset) { if (target[offset] >= segstart && target[offset] < j) { if (target[offset] >= segStart && target[offset] < j) { measurement[offset] = measurement[offset] = baseh + measureRun(segstart, offset, j, runIsRtl, crtfmi); baseh + measureRun(segStart, offset, j, runIsRtl, crtfmi); } } } } if (codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR if (target[j] == j) { if (target[j] == j) { measurement[j] = h; measurement[j] = h; } } Loading @@ -491,7 +443,7 @@ public class TextLine { } } } } segstart = j + 1; segStart = j + 1; } } } } } } Loading Loading
core/java/android/text/Layout.java +46 −0 Original line number Original line Diff line number Diff line Loading @@ -2360,6 +2360,52 @@ public abstract class Layout { public Directions(int[] dirs) { public Directions(int[] dirs) { mDirections = dirs; mDirections = dirs; } } /** * Returns number of BiDi runs. * * @hide */ public @IntRange(from = 0) int getRunCount() { return mDirections.length / 2; } /** * Returns the start offset of the BiDi run. * * @param runIndex the index of the BiDi run * @return the start offset of the BiDi run. * @hide */ public @IntRange(from = 0) int getRunStart(@IntRange(from = 0) int runIndex) { return mDirections[runIndex * 2]; } /** * Returns the length of the BiDi run. * * Note that this method may return too large number due to reducing the number of object * allocations. The too large number means the remaining part is assigned to this run. The * caller must clamp the returned value. * * @param runIndex the index of the BiDi run * @return the length of the BiDi run. * @hide */ public @IntRange(from = 0) int getRunLength(@IntRange(from = 0) int runIndex) { return mDirections[runIndex * 2 + 1] & RUN_LENGTH_MASK; } /** * Returns true if the BiDi run is RTL. * * @param runIndex the index of the BiDi run * @return true if the BiDi run is RTL. * @hide */ public boolean isRunRtl(int runIndex) { return (mDirections[runIndex * 2 + 1] & RUN_RTL_FLAG) != 0; } } } /** /** Loading
core/java/android/text/TextLine.java +94 −142 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; package android.text; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.annotation.UnsupportedAppUsage; import android.annotation.UnsupportedAppUsage; Loading Loading @@ -51,6 +52,8 @@ import java.util.ArrayList; public class TextLine { public class TextLine { private static final boolean DEBUG = false; private static final boolean DEBUG = false; private static final char TAB_CHAR = '\t'; private TextPaint mPaint; private TextPaint mPaint; @UnsupportedAppUsage @UnsupportedAppUsage private CharSequence mText; private CharSequence mText; Loading Loading @@ -232,6 +235,10 @@ public class TextLine { mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0; mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0; } } private char charAt(int i) { return mCharsValid ? mChars[i] : mText.charAt(i + mStart); } /** /** * Justify the line to the given width. * Justify the line to the given width. */ */ Loading Loading @@ -261,51 +268,23 @@ public class TextLine { * @param bottom the bottom of the line * @param bottom the bottom of the line */ */ void draw(Canvas c, float x, int top, int y, int bottom) { void draw(Canvas c, float x, int top, int y, int bottom) { if (!mHasTabs) { if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { drawRun(c, 0, mLen, false, x, top, y, bottom, false); return; } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { drawRun(c, 0, mLen, true, x, top, y, bottom, false); return; } } float h = 0; float h = 0; int[] runs = mDirections.mDirections; final int runCount = mDirections.getRunCount(); for (int runIndex = 0; runIndex < runCount; runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); int lastRunIndex = runs.length - 2; int segStart = runStart; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { h += drawRun(c, segStart, j, runIsRtl, x + h, top, y, bottom, codept = mChars[j]; runIndex != (runCount - 1) || j != mLen); if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { codept = Character.codePointAt(mChars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR h += drawRun(c, segstart, j, runIsRtl, x+h, top, y, bottom, i != lastRunIndex || j != mLen); if (codept == '\t') { h = mDir * nextTab(h * mDir); h = mDir * nextTab(h * mDir); } } segstart = j + 1; segStart = j + 1; } } } } } } Loading @@ -323,75 +302,81 @@ public class TextLine { } } /** /** * Returns information about a position on the line. * Returns the signed graphical offset from the leading margin. * * * @param offset the line-relative character offset, between 0 and the * Following examples are all for measuring offset=3. LX(e.g. L0, L1, ...) denotes a * line length, inclusive * character which has LTR BiDi property. On the other hand, RX(e.g. R0, R1, ...) denotes a * @param trailing true to measure the trailing edge of the character * character which has RTL BiDi property. Assuming all character has 1em width. * before offset, false to measure the leading edge of the character * * at offset. * Example 1: All LTR chars within LTR context * @param fmi receives metrics information about the requested * Input Text (logical) : L0 L1 L2 L3 L4 L5 L6 L7 L8 * character, can be null. * Input Text (visual) : L0 L1 L2 L3 L4 L5 L6 L7 L8 * @return the signed offset from the leading margin to the requested * Output(trailing=true) : |--------| (Returns 3em) * character edge. * Output(trailing=false): |--------| (Returns 3em) * * Example 2: All RTL chars within RTL context. * Input Text (logical) : R0 R1 R2 R3 R4 R5 R6 R7 R8 * Input Text (visual) : R8 R7 R6 R5 R4 R3 R2 R1 R0 * Output(trailing=true) : |--------| (Returns -3em) * Output(trailing=false): |--------| (Returns -3em) * * Example 3: BiDi chars within LTR context. * Input Text (logical) : L0 L1 L2 R3 R4 R5 L6 L7 L8 * Input Text (visual) : L0 L1 L2 R5 R4 R3 L6 L7 L8 * Output(trailing=true) : |-----------------| (Returns 6em) * Output(trailing=false): |--------| (Returns 3em) * * Example 4: BiDi chars within RTL context. * Input Text (logical) : L0 L1 L2 R3 R4 R5 L6 L7 L8 * Input Text (visual) : L6 L7 L8 R5 R4 R3 L0 L1 L2 * Output(trailing=true) : |-----------------| (Returns -6em) * Output(trailing=false): |--------| (Returns -3em) * * @param offset the line-relative character offset, between 0 and the line length, inclusive * @param trailing no effect if the offset is not on the BiDi transition offset. If the offset * is on the BiDi transition offset and true is passed, the offset is regarded * as the edge of the trailing run's edge. If false, the offset is regarded as * the edge of the preceding run's edge. See example above. * @param fmi receives metrics information about the requested character, can be null * @return the signed graphical offset from the leading margin to the requested character edge. * The positive value means the offset is right from the leading edge. The negative * value means the offset is left from the leading edge. */ */ public float measure(int offset, boolean trailing, FontMetricsInt fmi) { public float measure(@IntRange(from = 0) int offset, boolean trailing, int target = trailing ? offset - 1 : offset; @NonNull FontMetricsInt fmi) { if (offset > mLen) { throw new IndexOutOfBoundsException( "offset(" + offset + ") should be less than line limit(" + mLen + ")"); } final int target = trailing ? offset - 1 : offset; if (target < 0) { if (target < 0) { return 0; return 0; } } float h = 0; float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); if (!mHasTabs) { int segStart = runStart; if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { return measureRun(0, offset, mLen, false, fmi); } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { return measureRun(0, offset, mLen, true, fmi); } } char[] chars = mChars; int[] runs = mDirections.mDirections; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i+1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i+1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { final boolean targetIsInThisSegment = target >= segStart && target < j; codept = chars[j]; final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { codept = Character.codePointAt(chars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { boolean inSegment = target >= segstart && target < j; boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (targetIsInThisSegment && sameDirection) { if (inSegment && advance) { return h + measureRun(segStart, offset, j, runIsRtl, fmi); return h + measureRun(segstart, offset, j, runIsRtl, fmi); } } float w = measureRun(segstart, j, j, runIsRtl, fmi); final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi); h += advance ? w : -w; h += sameDirection ? segmentWidth : -segmentWidth; if (inSegment) { if (targetIsInThisSegment) { return h + measureRun(segstart, offset, j, runIsRtl, null); return h + measureRun(segStart, offset, j, runIsRtl, null); } } if (codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR if (offset == j) { if (offset == j) { return h; return h; } } Loading @@ -401,7 +386,7 @@ public class TextLine { } } } } segstart = j + 1; segStart = j + 1; } } } } } } Loading @@ -426,62 +411,29 @@ public class TextLine { } } float h = 0; float h = 0; for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) { final int runStart = mDirections.getRunStart(runIndex); final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen); final boolean runIsRtl = mDirections.isRunRtl(runIndex); if (!mHasTabs) { int segStart = runStart; if (mDirections == Layout.DIRS_ALL_LEFT_TO_RIGHT) { for (int offset = 0; offset <= mLen; ++offset) { measurement[offset] = measureRun(0, offset, mLen, false, fmi); } return measurement; } if (mDirections == Layout.DIRS_ALL_RIGHT_TO_LEFT) { for (int offset = 0; offset <= mLen; ++offset) { measurement[offset] = measureRun(0, offset, mLen, true, fmi); } return measurement; } } char[] chars = mChars; int[] runs = mDirections.mDirections; for (int i = 0; i < runs.length; i += 2) { int runStart = runs[i]; int runLimit = runStart + (runs[i + 1] & Layout.RUN_LENGTH_MASK); if (runLimit > mLen) { runLimit = mLen; } boolean runIsRtl = (runs[i + 1] & Layout.RUN_RTL_FLAG) != 0; int segstart = runStart; for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) { for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; ++j) { int codept = 0; if (j == runLimit || charAt(j) == TAB_CHAR) { if (mHasTabs && j < runLimit) { final float oldh = h; codept = chars[j]; final boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; if (codept >= 0xD800 && codept < 0xDC00 && j + 1 < runLimit) { final float w = measureRun(segStart, j, j, runIsRtl, fmi); codept = Character.codePointAt(chars, j); if (codept > 0xFFFF) { ++j; continue; } } } if (j == runLimit || codept == '\t') { float oldh = h; boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl; float w = measureRun(segstart, j, j, runIsRtl, fmi); h += advance ? w : -w; h += advance ? w : -w; float baseh = advance ? oldh : h; final float baseh = advance ? oldh : h; FontMetricsInt crtfmi = advance ? fmi : null; FontMetricsInt crtfmi = advance ? fmi : null; for (int offset = segstart; offset <= j && offset <= mLen; ++offset) { for (int offset = segStart; offset <= j && offset <= mLen; ++offset) { if (target[offset] >= segstart && target[offset] < j) { if (target[offset] >= segStart && target[offset] < j) { measurement[offset] = measurement[offset] = baseh + measureRun(segstart, offset, j, runIsRtl, crtfmi); baseh + measureRun(segStart, offset, j, runIsRtl, crtfmi); } } } } if (codept == '\t') { if (j != runLimit) { // charAt(j) == TAB_CHAR if (target[j] == j) { if (target[j] == j) { measurement[j] = h; measurement[j] = h; } } Loading @@ -491,7 +443,7 @@ public class TextLine { } } } } segstart = j + 1; segStart = j + 1; } } } } } } Loading