Merge "Introduce TextLine#measureAllbounds"
This commit is contained in:
@@ -14929,6 +14929,8 @@ package android.graphics {
|
||||
method public android.graphics.PathEffect getPathEffect();
|
||||
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
|
||||
method public float getRunAdvance(CharSequence, int, int, int, int, boolean, int);
|
||||
method public float getRunCharacterAdvance(@NonNull char[], int, int, int, int, boolean, int, @Nullable float[], int);
|
||||
method public float getRunCharacterAdvance(@NonNull CharSequence, int, int, int, int, boolean, int, @Nullable float[], int);
|
||||
method public android.graphics.Shader getShader();
|
||||
method @ColorInt public int getShadowLayerColor();
|
||||
method @ColorLong public long getShadowLayerColorLong();
|
||||
|
||||
@@ -408,14 +408,14 @@ public class TextLine {
|
||||
final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
|
||||
|
||||
if (targetIsInThisSegment && sameDirection) {
|
||||
return h + measureRun(segStart, offset, j, runIsRtl, fmi);
|
||||
return h + measureRun(segStart, offset, j, runIsRtl, fmi, null, 0);
|
||||
}
|
||||
|
||||
final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi);
|
||||
final float segmentWidth = measureRun(segStart, j, j, runIsRtl, fmi, null, 0);
|
||||
h += sameDirection ? segmentWidth : -segmentWidth;
|
||||
|
||||
if (targetIsInThisSegment) {
|
||||
return h + measureRun(segStart, offset, j, runIsRtl, null);
|
||||
return h + measureRun(segStart, offset, j, runIsRtl, null, null, 0);
|
||||
}
|
||||
|
||||
if (j != runLimit) { // charAt(j) == TAB_CHAR
|
||||
@@ -436,6 +436,116 @@ public class TextLine {
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the signed horizontal bounds of the characters in the line.
|
||||
*
|
||||
* The length of the returned array equals to 2 * mLen. The left bound of the i th character
|
||||
* is stored at index 2 * i. And the right bound of the i th character is stored at index
|
||||
* (2 * i + 1).
|
||||
*
|
||||
* Check the following examples. LX(e.g. L0, L1, ...) denotes a character which has LTR BiDi
|
||||
* property. On the other hand, RX(e.g. R0, R1, ...) denotes a character which has RTL BiDi
|
||||
* property. Assuming all character has 1em width.
|
||||
*
|
||||
* Example 1: All LTR chars within LTR context
|
||||
* Input Text (logical) : L0 L1 L2 L3
|
||||
* Input Text (visual) : L0 L1 L2 L3
|
||||
* Output : [0em, 1em, 1em, 2em, 2em, 3em, 3em, 4em]
|
||||
*
|
||||
* Example 2: All RTL chars within RTL context.
|
||||
* Input Text (logical) : R0 R1 R2 R3
|
||||
* Input Text (visual) : R3 R2 R1 R0
|
||||
* Output : [-1em, 0em, -2em, -1em, -3em, -2em, -4em, -3em]
|
||||
|
||||
*
|
||||
* Example 3: BiDi chars within LTR context.
|
||||
* Input Text (logical) : L0 L1 R2 R3 L4 L5
|
||||
* Input Text (visual) : L0 L1 R3 R2 L4 L5
|
||||
* Output : [0em, 1em, 1em, 2em, 3em, 4em, 2em, 3em, 4em, 5em, 5em, 6em]
|
||||
|
||||
*
|
||||
* Example 4: BiDi chars within RTL context.
|
||||
* Input Text (logical) : L0 L1 R2 R3 L4 L5
|
||||
* Input Text (visual) : L4 L5 R3 R2 L0 L1
|
||||
* Output : [-2em, -1em, -1em, 0em, -3em, -2em, -4em, -3em, -6em, -5em, -5em, -4em]
|
||||
*
|
||||
* @param bounds the array to receive the character bounds data. Its length should be at least
|
||||
* 2 times of the line length.
|
||||
* @param advances the array to receive the character advance data, nullable. If provided, its
|
||||
* length should be equal or larger than the line length.
|
||||
*
|
||||
* @throws IllegalArgumentException if the given {@code bounds} is null.
|
||||
* @throws IndexOutOfBoundsException if the given {@code bounds} or {@code advances} doesn't
|
||||
* have enough space to hold the result.
|
||||
*/
|
||||
public void measureAllBounds(@NonNull float[] bounds, @Nullable float[] advances) {
|
||||
if (bounds == null) {
|
||||
throw new IllegalArgumentException("bounds can't be null");
|
||||
}
|
||||
if (bounds.length < 2 * mLen) {
|
||||
throw new IndexOutOfBoundsException("bounds doesn't have enough space to receive the "
|
||||
+ "result, needed: " + (2 * mLen) + " had: " + bounds.length);
|
||||
}
|
||||
if (advances == null) {
|
||||
advances = new float[mLen];
|
||||
}
|
||||
if (advances.length < mLen) {
|
||||
throw new IndexOutOfBoundsException("advance doesn't have enough space to receive the "
|
||||
+ "result, needed: " + mLen + " had: " + advances.length);
|
||||
}
|
||||
float h = 0;
|
||||
for (int runIndex = 0; runIndex < mDirections.getRunCount(); runIndex++) {
|
||||
final int runStart = mDirections.getRunStart(runIndex);
|
||||
if (runStart > mLen) break;
|
||||
final int runLimit = Math.min(runStart + mDirections.getRunLength(runIndex), mLen);
|
||||
final boolean runIsRtl = mDirections.isRunRtl(runIndex);
|
||||
|
||||
int segStart = runStart;
|
||||
for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
|
||||
if (j == runLimit || charAt(j) == TAB_CHAR) {
|
||||
final boolean sameDirection = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
|
||||
|
||||
final float segmentWidth =
|
||||
measureRun(segStart, j, j, runIsRtl, null, advances, segStart);
|
||||
|
||||
final float oldh = h;
|
||||
h += sameDirection ? segmentWidth : -segmentWidth;
|
||||
float currh = sameDirection ? oldh : h;
|
||||
for (int offset = segStart; offset < j && offset < mLen; ++offset) {
|
||||
if (runIsRtl) {
|
||||
bounds[2 * offset + 1] = currh;
|
||||
currh -= advances[offset];
|
||||
bounds[2 * offset] = currh;
|
||||
} else {
|
||||
bounds[2 * offset] = currh;
|
||||
currh += advances[offset];
|
||||
bounds[2 * offset + 1] = currh;
|
||||
}
|
||||
}
|
||||
|
||||
if (j != runLimit) { // charAt(j) == TAB_CHAR
|
||||
final float leftX;
|
||||
final float rightX;
|
||||
if (runIsRtl) {
|
||||
rightX = h;
|
||||
h = mDir * nextTab(h * mDir);
|
||||
leftX = h;
|
||||
} else {
|
||||
leftX = h;
|
||||
h = mDir * nextTab(h * mDir);
|
||||
rightX = h;
|
||||
}
|
||||
bounds[2 * j] = leftX;
|
||||
bounds[2 * j + 1] = rightX;
|
||||
advances[j] = rightX - leftX;
|
||||
}
|
||||
|
||||
segStart = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #measure(int, boolean, FontMetricsInt)
|
||||
* @return The measure results for all possible offsets
|
||||
@@ -464,15 +574,15 @@ public class TextLine {
|
||||
if (j == runLimit || charAt(j) == TAB_CHAR) {
|
||||
final float oldh = h;
|
||||
final boolean advance = (mDir == Layout.DIR_RIGHT_TO_LEFT) == runIsRtl;
|
||||
final float w = measureRun(segStart, j, j, runIsRtl, fmi);
|
||||
final float w = measureRun(segStart, j, j, runIsRtl, fmi, null, 0);
|
||||
h += advance ? w : -w;
|
||||
|
||||
final float baseh = advance ? oldh : h;
|
||||
FontMetricsInt crtfmi = advance ? fmi : null;
|
||||
for (int offset = segStart; offset <= j && offset <= mLen; ++offset) {
|
||||
if (target[offset] >= segStart && target[offset] < j) {
|
||||
measurement[offset] =
|
||||
baseh + measureRun(segStart, offset, j, runIsRtl, crtfmi);
|
||||
measurement[offset] = baseh
|
||||
+ measureRun(segStart, offset, j, runIsRtl, crtfmi, null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,14 +628,14 @@ public class TextLine {
|
||||
boolean needWidth) {
|
||||
|
||||
if ((mDir == Layout.DIR_LEFT_TO_RIGHT) == runIsRtl) {
|
||||
float w = -measureRun(start, limit, limit, runIsRtl, null);
|
||||
float w = -measureRun(start, limit, limit, runIsRtl, null, null, 0);
|
||||
handleRun(start, limit, limit, runIsRtl, c, null, x + w, top,
|
||||
y, bottom, null, false);
|
||||
y, bottom, null, false, null, 0);
|
||||
return w;
|
||||
}
|
||||
|
||||
return handleRun(start, limit, limit, runIsRtl, c, null, x, top,
|
||||
y, bottom, null, needWidth);
|
||||
y, bottom, null, needWidth, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,12 +648,15 @@ public class TextLine {
|
||||
* @param runIsRtl true if the run is right-to-left
|
||||
* @param fmi receives metrics information about the requested
|
||||
* run, can be null.
|
||||
* @param advances receives the advance information about the requested run, can be null.
|
||||
* @param advancesIndex the start index to fill in the advance information.
|
||||
* @return the signed width from the start of the run to the leading edge
|
||||
* of the character at offset, based on the run (not paragraph) direction
|
||||
*/
|
||||
private float measureRun(int start, int offset, int limit, boolean runIsRtl,
|
||||
FontMetricsInt fmi) {
|
||||
return handleRun(start, offset, limit, runIsRtl, null, null, 0, 0, 0, 0, fmi, true);
|
||||
@Nullable FontMetricsInt fmi, @Nullable float[] advances, int advancesIndex) {
|
||||
return handleRun(start, offset, limit, runIsRtl, null, null, 0, 0, 0, 0, fmi, true,
|
||||
advances, advancesIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,13 +675,14 @@ public class TextLine {
|
||||
int limit, boolean runIsRtl, float x, boolean needWidth) {
|
||||
|
||||
if ((mDir == Layout.DIR_LEFT_TO_RIGHT) == runIsRtl) {
|
||||
float w = -measureRun(start, limit, limit, runIsRtl, null);
|
||||
handleRun(start, limit, limit, runIsRtl, null, consumer, x + w, 0, 0, 0, null, false);
|
||||
float w = -measureRun(start, limit, limit, runIsRtl, null, null, 0);
|
||||
handleRun(start, limit, limit, runIsRtl, null, consumer, x + w, 0, 0, 0, null,
|
||||
false, null, 0);
|
||||
return w;
|
||||
}
|
||||
|
||||
return handleRun(start, limit, limit, runIsRtl, null, consumer, x, 0, 0, 0, null,
|
||||
needWidth);
|
||||
needWidth, null, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -908,14 +1022,16 @@ public class TextLine {
|
||||
}
|
||||
|
||||
private float getRunAdvance(TextPaint wp, int start, int end, int contextStart, int contextEnd,
|
||||
boolean runIsRtl, int offset) {
|
||||
boolean runIsRtl, int offset, @Nullable float[] advances, int advancesIndex) {
|
||||
if (mCharsValid) {
|
||||
return wp.getRunAdvance(mChars, start, end, contextStart, contextEnd, runIsRtl, offset);
|
||||
return wp.getRunCharacterAdvance(mChars, start, end, contextStart, contextEnd,
|
||||
runIsRtl, offset, advances, advancesIndex);
|
||||
} else {
|
||||
final int delta = mStart;
|
||||
if (mComputed == null) {
|
||||
return wp.getRunAdvance(mText, delta + start, delta + end,
|
||||
delta + contextStart, delta + contextEnd, runIsRtl, delta + offset);
|
||||
if (mComputed == null || advances != null) {
|
||||
return wp.getRunCharacterAdvance(mText, delta + start, delta + end,
|
||||
delta + contextStart, delta + contextEnd, runIsRtl,
|
||||
delta + offset, advances, advancesIndex);
|
||||
} else {
|
||||
return mComputed.getWidth(start + delta, end + delta);
|
||||
}
|
||||
@@ -940,6 +1056,8 @@ public class TextLine {
|
||||
* @param needWidth true if the width of the run is needed
|
||||
* @param offset the offset for the purpose of measuring
|
||||
* @param decorations the list of locations and paremeters for drawing decorations
|
||||
* @param advances receives the advance information about the requested run, can be null.
|
||||
* @param advancesIndex the start index to fill in the advance information.
|
||||
* @return the signed width of the run based on the run direction; only
|
||||
* valid if needWidth is true
|
||||
*/
|
||||
@@ -947,7 +1065,8 @@ public class TextLine {
|
||||
int contextStart, int contextEnd, boolean runIsRtl,
|
||||
Canvas c, TextShaper.GlyphsConsumer consumer, float x, int top, int y, int bottom,
|
||||
FontMetricsInt fmi, boolean needWidth, int offset,
|
||||
@Nullable ArrayList<DecorationInfo> decorations) {
|
||||
@Nullable ArrayList<DecorationInfo> decorations,
|
||||
@Nullable float[] advances, int advancesIndex) {
|
||||
|
||||
if (mIsJustifying) {
|
||||
wp.setWordSpacing(mAddedWidthForJustify);
|
||||
@@ -967,7 +1086,8 @@ public class TextLine {
|
||||
final int numDecorations = decorations == null ? 0 : decorations.size();
|
||||
if (needWidth || ((c != null || consumer != null) && (wp.bgColor != 0
|
||||
|| numDecorations != 0 || runIsRtl))) {
|
||||
totalWidth = getRunAdvance(wp, start, end, contextStart, contextEnd, runIsRtl, offset);
|
||||
totalWidth = getRunAdvance(wp, start, end, contextStart, contextEnd, runIsRtl, offset,
|
||||
advances, advancesIndex);
|
||||
}
|
||||
|
||||
final float leftX, rightX;
|
||||
@@ -1009,10 +1129,10 @@ public class TextLine {
|
||||
|
||||
final int decorationStart = Math.max(info.start, start);
|
||||
final int decorationEnd = Math.min(info.end, offset);
|
||||
float decorationStartAdvance = getRunAdvance(
|
||||
wp, start, end, contextStart, contextEnd, runIsRtl, decorationStart);
|
||||
float decorationEndAdvance = getRunAdvance(
|
||||
wp, start, end, contextStart, contextEnd, runIsRtl, decorationEnd);
|
||||
float decorationStartAdvance = getRunAdvance(wp, start, end, contextStart,
|
||||
contextEnd, runIsRtl, decorationStart, null, 0);
|
||||
float decorationEndAdvance = getRunAdvance(wp, start, end, contextStart,
|
||||
contextEnd, runIsRtl, decorationEnd, null, 0);
|
||||
final float decorationXLeft, decorationXRight;
|
||||
if (runIsRtl) {
|
||||
decorationXLeft = rightX - decorationEndAdvance;
|
||||
@@ -1179,19 +1299,27 @@ public class TextLine {
|
||||
* @param bottom the bottom of the line
|
||||
* @param fmi receives metrics information, can be null
|
||||
* @param needWidth true if the width is required
|
||||
* @param advances receives the advance information about the requested run, can be null.
|
||||
* @param advancesIndex the start index to fill in the advance information.
|
||||
* @return the signed width of the run based on the run direction; only
|
||||
* valid if needWidth is true
|
||||
*/
|
||||
private float handleRun(int start, int measureLimit,
|
||||
int limit, boolean runIsRtl, Canvas c,
|
||||
TextShaper.GlyphsConsumer consumer, float x, int top, int y,
|
||||
int bottom, FontMetricsInt fmi, boolean needWidth) {
|
||||
int bottom, FontMetricsInt fmi, boolean needWidth,
|
||||
@Nullable float[] advances, int advancesIndex) {
|
||||
|
||||
if (measureLimit < start || measureLimit > limit) {
|
||||
throw new IndexOutOfBoundsException("measureLimit (" + measureLimit + ") is out of "
|
||||
+ "start (" + start + ") and limit (" + limit + ") bounds");
|
||||
}
|
||||
|
||||
if (advances != null && advances.length - advancesIndex < measureLimit - start) {
|
||||
throw new IndexOutOfBoundsException("advances doesn't have enough space to receive the "
|
||||
+ "result");
|
||||
}
|
||||
|
||||
// Case of an empty line, make sure we update fmi according to mPaint
|
||||
if (start == measureLimit) {
|
||||
final TextPaint wp = mWorkPaint;
|
||||
@@ -1218,7 +1346,7 @@ public class TextLine {
|
||||
wp.setStartHyphenEdit(adjustStartHyphenEdit(start, wp.getStartHyphenEdit()));
|
||||
wp.setEndHyphenEdit(adjustEndHyphenEdit(limit, wp.getEndHyphenEdit()));
|
||||
return handleText(wp, start, limit, start, limit, runIsRtl, c, consumer, x, top,
|
||||
y, bottom, fmi, needWidth, measureLimit, null);
|
||||
y, bottom, fmi, needWidth, measureLimit, null, advances, advancesIndex);
|
||||
}
|
||||
|
||||
// Shaping needs to take into account context up to metric boundaries,
|
||||
@@ -1257,8 +1385,16 @@ public class TextLine {
|
||||
}
|
||||
|
||||
if (replacement != null) {
|
||||
x += handleReplacement(replacement, wp, i, mlimit, runIsRtl, c, x, top, y,
|
||||
bottom, fmi, needWidth || mlimit < measureLimit);
|
||||
final float width = handleReplacement(replacement, wp, i, mlimit, runIsRtl, c,
|
||||
x, top, y, bottom, fmi, needWidth || mlimit < measureLimit);
|
||||
x += width;
|
||||
if (advances != null) {
|
||||
// For replacement, the entire width is assigned to the first character.
|
||||
advances[advancesIndex + i - start] = runIsRtl ? -width : width;
|
||||
for (int j = i + 1; j < mlimit; ++j) {
|
||||
advances[advancesIndex + j - start] = 0.0f;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1300,7 +1436,8 @@ public class TextLine {
|
||||
adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
|
||||
x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c,
|
||||
consumer, x, top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
|
||||
Math.min(activeEnd, mlimit), mDecorations);
|
||||
Math.min(activeEnd, mlimit), mDecorations,
|
||||
advances, advancesIndex + activeStart - start);
|
||||
|
||||
activeStart = j;
|
||||
activePaint.set(wp);
|
||||
@@ -1327,7 +1464,8 @@ public class TextLine {
|
||||
adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
|
||||
x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, consumer, x,
|
||||
top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
|
||||
Math.min(activeEnd, mlimit), mDecorations);
|
||||
Math.min(activeEnd, mlimit), mDecorations,
|
||||
advances, advancesIndex + activeStart - start);
|
||||
}
|
||||
|
||||
return x - originalX;
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.text.Layout.TabStops;
|
||||
import android.text.style.AbsoluteSizeSpan;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.text.style.TabStopSpan;
|
||||
|
||||
@@ -97,7 +98,7 @@ public class TextLineTest {
|
||||
InstrumentationRegistry.getInstrumentation().getTargetContext().getAssets(),
|
||||
"fonts/StaticLayoutLineBreakingTestFont.ttf");
|
||||
|
||||
private TextLine getTextLine(String str, TextPaint paint, TabStops tabStops) {
|
||||
private TextLine getTextLine(CharSequence str, TextPaint paint, TabStops tabStops) {
|
||||
Layout layout =
|
||||
StaticLayout.Builder.obtain(str, 0, str.length(), paint, Integer.MAX_VALUE)
|
||||
.build();
|
||||
@@ -109,7 +110,7 @@ public class TextLineTest {
|
||||
return tl;
|
||||
}
|
||||
|
||||
private TextLine getTextLine(String str, TextPaint paint) {
|
||||
private TextLine getTextLine(CharSequence str, TextPaint paint) {
|
||||
return getTextLine(str, paint, null);
|
||||
}
|
||||
|
||||
@@ -316,14 +317,275 @@ public class TextLineTest {
|
||||
assertTrue(span.mIsUsed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_LTR() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("IIIIIV", paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 20.0f, 20.0f, 30.0f, 30.0f, 40.0f,
|
||||
40.0f, 50.0f, 50.0f, 100.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 50.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_LTR_StyledText() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
SpannableString text = new SpannableString("IIIIIV");
|
||||
text.setSpan(new AbsoluteSizeSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 15.0f, 15.0f, 20.0f, 20.0f, 30.0f,
|
||||
30.0f, 40.0f, 40.0f, 90.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 5.0f, 10.0f, 10.0f, 50.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_RTL() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("\u05D0\u05D0\u05D0\u05D0\u05D0\u05D1", paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -20.0f, -10.0f, -30.0f, -20.0f, -40.0f, -30.0f,
|
||||
-50.0f, -40.0f, -100.0f, -50.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 50.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_RTL_StyledText() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
SpannableString text = new SpannableString("\u05D0\u05D0\u05D0\u05D0\u05D0\u05D1");
|
||||
text.setSpan(new AbsoluteSizeSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -15.0f, -10.0f, -20.0f, -15.0f,
|
||||
-30.0f, -20.0f, -40.0f, -30.0f, -90.0f, -40.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 5.0f, 10.0f, 10.0f, 50.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_BiDi() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("II\u05D0\u05D0II", paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 20.0f, 30.0f, 40.0f, 20.0f, 30.0f,
|
||||
40.0f, 50.0f, 50.0f, 60.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 10.0f, 10.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_BiDi2() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("I" + RLI + "I\u05D0\u05D0" + PDI + "I", paint);
|
||||
float[] bounds = new float[14];
|
||||
float[] advances = new float[7];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 10.0f, 30.0f, 40.0f, 20.0f, 30.0f,
|
||||
10.0f, 20.0f, 40.0f, 40.0f, 40.0f, 50.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 0.0f, 10.0f, 10.0f, 10.0f, 0.0f, 10.0f}, advances,
|
||||
0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_BiDi3() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("\u05D0" + LRI + "\u05D0II" + PDI + "\u05D0", paint);
|
||||
float[] bounds = new float[14];
|
||||
float[] advances = new float[7];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -10.0f, -10.0f, -40.0f, -30.0f,
|
||||
-30.0f, -20.0f, -20.0f, -10.0f, -40.0f, -40.0f, -50.0f, -40.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 0.0f, 10.0f, 10.0f, 10.0f, 0.0f, 10.0f}, advances,
|
||||
0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_styled_BiDi() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
SpannableString text = new SpannableString("II\u05D0\u05D0II");
|
||||
text.setSpan(new AbsoluteSizeSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 15.0f, 25.0f, 30.0f,
|
||||
15.0f, 25.0f, 30.0f, 40.0f, 40.0f, 50.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 5.0f, 10.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_Tab_LTR() {
|
||||
final Object[] spans = { new TabStopSpan.Standard(100) };
|
||||
final TabStops stops = new TabStops(100, spans);
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("II\tII", paint, stops);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 20.0f, 20.0f, 100.0f, 100.0f, 110.0f,
|
||||
110.0f, 120.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 80.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_Tab_RTL() {
|
||||
final Object[] spans = { new TabStopSpan.Standard(100) };
|
||||
final TabStops stops = new TabStops(100, spans);
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("\u05D0\u05D0\t\u05D0\u05D0", paint, stops);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -20.0f, -10.0f, -100.0f, -20.0f,
|
||||
-110.0f, -100.0f, -120.0f, -110.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 80.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_Tab_BiDi() {
|
||||
final Object[] spans = { new TabStopSpan.Standard(100) };
|
||||
final TabStops stops = new TabStops(100, spans);
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("I\u05D0\tI\u05D0", paint, stops);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 20.0f, 20.0f, 100.0f,
|
||||
100.0f, 110.0f, 110.0f, 120.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 80.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_Tab_BiDi2() {
|
||||
final Object[] spans = { new TabStopSpan.Standard(100) };
|
||||
final TabStops stops = new TabStops(100, spans);
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
TextLine tl = getTextLine("\u05D0I\t\u05D0I", paint, stops);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -20.0f, -10.0f, -100.0f, -20.0f,
|
||||
-110.0f, -100.0f, -120.0f, -110.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 10.0f, 80.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_replacement_LTR() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
SpannableString text = new SpannableString("IIIII");
|
||||
text.setSpan(new TestReplacementSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 15.0f, 15.0f, 15.0f,
|
||||
15.0f, 25.0f, 25.0f, 35.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 0.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_replacement_RTL() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
SpannableString text = new SpannableString("\u05D0\u05D0\u05D0\u05D0\u05D0");
|
||||
text.setSpan(new TestReplacementSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[10];
|
||||
float[] advances = new float[5];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {-10.0f, 0.0f, -15.0f, -10.0f, -15.0f, -15.0f,
|
||||
-25.0f, -15.0f, -35.0f, -25.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 0.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMeasureAllBounds_replacement_BiDi() {
|
||||
final TextPaint paint = new TextPaint();
|
||||
paint.setTypeface(TYPEFACE);
|
||||
paint.setTextSize(10.0f); // make 1em = 10px
|
||||
|
||||
SpannableString text = new SpannableString("II\u05D0\u05D0II");
|
||||
text.setSpan(new TestReplacementSpan(5), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
TextLine tl = getTextLine(text, paint);
|
||||
float[] bounds = new float[12];
|
||||
float[] advances = new float[6];
|
||||
tl.measureAllBounds(bounds, advances);
|
||||
assertArrayEquals(new float[] {0.0f, 10.0f, 10.0f, 15.0f, 15.0f, 15.0f,
|
||||
15.0f, 25.0f, 25.0f, 35.0f, 35.0f, 45.0f}, bounds, 0.0f);
|
||||
assertArrayEquals(new float[] {10.0f, 5.0f, 0.0f, 10.0f, 10.0f, 10.0f}, advances, 0.0f);
|
||||
}
|
||||
|
||||
private static class TestReplacementSpan extends ReplacementSpan {
|
||||
boolean mIsUsed;
|
||||
private final int mWidth;
|
||||
|
||||
TestReplacementSpan() {
|
||||
mWidth = 0;
|
||||
}
|
||||
|
||||
TestReplacementSpan(int width) {
|
||||
mWidth = width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Paint paint, CharSequence text, int start, int end,
|
||||
Paint.FontMetricsInt fm) {
|
||||
mIsUsed = true;
|
||||
return 0;
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3136,6 +3136,128 @@ public class Paint {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Measure the advance of each character within a run of text and also return the cursor
|
||||
* position within the run.
|
||||
*
|
||||
* @see #getRunAdvance(char[], int, int, int, int, boolean, int) for more details.
|
||||
*
|
||||
* @param text the text to measure. Cannot be null.
|
||||
* @param start the index of the start of the range to measure
|
||||
* @param end the index + 1 of the end of the range to measure
|
||||
* @param contextStart the index of the start of the shaping context
|
||||
* @param contextEnd the index + 1 of the end of the shaping context
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param offset index of caret position
|
||||
* @param advances the array that receives the computed character advances
|
||||
* @param advancesIndex the start index from which the advances array is filled
|
||||
* @return width measurement between start and offset
|
||||
* @throws IndexOutOfBoundsException if a) contextStart or contextEnd is out of array's range
|
||||
* or contextStart is larger than contextEnd,
|
||||
* b) start or end is not within the range [contextStart, contextEnd), or start is larger than
|
||||
* end,
|
||||
* c) offset is not within the range [start, end),
|
||||
* d) advances.length - advanceIndex is smaller than the length of the run, which equals to
|
||||
* end - start.
|
||||
*
|
||||
*/
|
||||
public float getRunCharacterAdvance(@NonNull char[] text, int start, int end, int contextStart,
|
||||
int contextEnd, boolean isRtl, int offset,
|
||||
@Nullable float[] advances, int advancesIndex) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if (contextStart < 0 || contextEnd > text.length) {
|
||||
throw new IndexOutOfBoundsException("Invalid Context Range: " + contextStart + ", "
|
||||
+ contextEnd + " must be in 0, " + text.length);
|
||||
}
|
||||
|
||||
if (start < contextStart || contextEnd < end) {
|
||||
throw new IndexOutOfBoundsException("Invalid start/end range: " + start + ", " + end
|
||||
+ " must be in " + contextStart + ", " + contextEnd);
|
||||
}
|
||||
|
||||
if (offset < start || end < offset) {
|
||||
throw new IndexOutOfBoundsException("Invalid offset position: " + offset
|
||||
+ " must be in " + start + ", " + end);
|
||||
}
|
||||
|
||||
if (advances != null && advances.length < advancesIndex - start + end) {
|
||||
throw new IndexOutOfBoundsException("Given array doesn't have enough space to receive "
|
||||
+ "the result, advances.length: " + advances.length + " advanceIndex: "
|
||||
+ advancesIndex + " needed space: " + (offset - start));
|
||||
}
|
||||
|
||||
if (end == start) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return nGetRunCharacterAdvance(mNativePaint, text, start, end, contextStart, contextEnd,
|
||||
isRtl, offset, advances, advancesIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getRunCharacterAdvance(char[], int, int, int, int, boolean, int, float[], int)
|
||||
*
|
||||
* @param text the text to measure. Cannot be null.
|
||||
* @param start the index of the start of the range to measure
|
||||
* @param end the index + 1 of the end of the range to measure
|
||||
* @param contextStart the index of the start of the shaping context
|
||||
* @param contextEnd the index + 1 of the end of the shaping context
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param offset index of caret position
|
||||
* @param advances the array that receives the computed character advances
|
||||
* @param advancesIndex the start index from which the advances array is filled
|
||||
* @return width measurement between start and offset
|
||||
* @throws IndexOutOfBoundsException if a) contextStart or contextEnd is out of array's range
|
||||
* or contextStart is larger than contextEnd,
|
||||
* b) start or end is not within the range [contextStart, contextEnd), or end is larger than
|
||||
* start,
|
||||
* c) offset is not within the range [start, end),
|
||||
* d) advances.length - advanceIndex is smaller than the run length, which equals to
|
||||
* end - start.
|
||||
*/
|
||||
public float getRunCharacterAdvance(@NonNull CharSequence text, int start, int end,
|
||||
int contextStart, int contextEnd, boolean isRtl, int offset,
|
||||
@Nullable float[] advances, int advancesIndex) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if (contextStart < 0 || contextEnd > text.length()) {
|
||||
throw new IndexOutOfBoundsException("Invalid Context Range: " + contextStart + ", "
|
||||
+ contextEnd + " must be in 0, " + text.length());
|
||||
}
|
||||
|
||||
if (start < contextStart || contextEnd < end) {
|
||||
throw new IndexOutOfBoundsException("Invalid start/end range: " + start + ", " + end
|
||||
+ " must be in " + contextStart + ", " + contextEnd);
|
||||
}
|
||||
|
||||
if (offset < start || end < offset) {
|
||||
throw new IndexOutOfBoundsException("Invalid offset position: " + offset
|
||||
+ " must be in " + start + ", " + end);
|
||||
}
|
||||
|
||||
if (advances != null && advances.length < advancesIndex - start + end) {
|
||||
throw new IndexOutOfBoundsException("Given array doesn't have enough space to receive "
|
||||
+ "the result, advances.length: " + advances.length + " advanceIndex: "
|
||||
+ advancesIndex + " needed space: " + (offset - start));
|
||||
}
|
||||
|
||||
if (end == start) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
char[] buf = TemporaryBuffer.obtain(contextEnd - contextStart);
|
||||
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
|
||||
final float result = getRunCharacterAdvance(buf, start - contextStart, end - contextStart,
|
||||
0, contextEnd - contextStart, isRtl, offset - contextStart,
|
||||
advances, advancesIndex);
|
||||
TemporaryBuffer.recycle(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the character offset within the string whose position is closest to the specified
|
||||
* horizontal position.
|
||||
@@ -3247,6 +3369,9 @@ public class Paint {
|
||||
private static native boolean nHasGlyph(long paintPtr, int bidiFlags, String string);
|
||||
private static native float nGetRunAdvance(long paintPtr, char[] text, int start, int end,
|
||||
int contextStart, int contextEnd, boolean isRtl, int offset);
|
||||
private static native float nGetRunCharacterAdvance(long paintPtr, char[] text, int start,
|
||||
int end, int contextStart, int contextEnd, boolean isRtl, int offset, float[] advances,
|
||||
int advancesIndex);
|
||||
private static native int nGetOffsetForAdvance(long paintPtr, char[] text, int start, int end,
|
||||
int contextStart, int contextEnd, boolean isRtl, float advance);
|
||||
private static native void nGetFontMetricsIntForText(long paintPtr, char[] text,
|
||||
|
||||
@@ -497,16 +497,29 @@ namespace PaintGlue {
|
||||
return true;
|
||||
}
|
||||
|
||||
static jfloat doRunAdvance(const Paint* paint, const Typeface* typeface, const jchar buf[],
|
||||
jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
|
||||
static jfloat doRunAdvance(JNIEnv* env, const Paint* paint, const Typeface* typeface,
|
||||
const jchar buf[], jint start, jint count, jint bufSize,
|
||||
jboolean isRtl, jint offset, jfloatArray advances,
|
||||
jint advancesIndex) {
|
||||
if (advances) {
|
||||
size_t advancesLength = env->GetArrayLength(advances);
|
||||
if ((size_t)(count + advancesIndex) > advancesLength) {
|
||||
doThrowAIOOBE(env);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
minikin::Bidi bidiFlags = isRtl ? minikin::Bidi::FORCE_RTL : minikin::Bidi::FORCE_LTR;
|
||||
if (offset == start + count) {
|
||||
if (offset == start + count && advances == nullptr) {
|
||||
return MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count,
|
||||
bufSize, nullptr);
|
||||
}
|
||||
std::unique_ptr<float[]> advancesArray(new float[count]);
|
||||
MinikinUtils::measureText(paint, bidiFlags, typeface, buf, start, count, bufSize,
|
||||
advancesArray.get());
|
||||
|
||||
if (advances) {
|
||||
env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray.get());
|
||||
}
|
||||
return minikin::getRunAdvance(advancesArray.get(), buf, start, count, offset);
|
||||
}
|
||||
|
||||
@@ -515,9 +528,23 @@ namespace PaintGlue {
|
||||
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
const Typeface* typeface = paint->getAndroidTypeface();
|
||||
ScopedCharArrayRO textArray(env, text);
|
||||
jfloat result = doRunAdvance(paint, typeface, textArray.get() + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart, isRtl,
|
||||
offset - contextStart);
|
||||
jfloat result = doRunAdvance(env, paint, typeface, textArray.get() + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart,
|
||||
isRtl, offset - contextStart, nullptr, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
static jfloat getRunCharacterAdvance___CIIIIZI_FI_F(JNIEnv* env, jclass, jlong paintHandle,
|
||||
jcharArray text, jint start, jint end,
|
||||
jint contextStart, jint contextEnd,
|
||||
jboolean isRtl, jint offset,
|
||||
jfloatArray advances, jint advancesIndex) {
|
||||
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
const Typeface* typeface = paint->getAndroidTypeface();
|
||||
ScopedCharArrayRO textArray(env, text);
|
||||
jfloat result = doRunAdvance(env, paint, typeface, textArray.get() + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart,
|
||||
isRtl, offset - contextStart, advances, advancesIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1034,113 +1061,112 @@ namespace PaintGlue {
|
||||
}; // namespace PaintGlue
|
||||
|
||||
static const JNINativeMethod methods[] = {
|
||||
{"nGetNativeFinalizer", "()J", (void*) PaintGlue::getNativeFinalizer},
|
||||
{"nInit","()J", (void*) PaintGlue::init},
|
||||
{"nInitWithPaint","(J)J", (void*) PaintGlue::initWithPaint},
|
||||
{"nBreakText","(J[CIIFI[F)I", (void*) PaintGlue::breakTextC},
|
||||
{"nBreakText","(JLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
|
||||
{"nGetTextAdvances","(J[CIIIII[FI)F",
|
||||
(void*) PaintGlue::getTextAdvances___CIIIII_FI},
|
||||
{"nGetTextAdvances","(JLjava/lang/String;IIIII[FI)F",
|
||||
(void*) PaintGlue::getTextAdvances__StringIIIII_FI},
|
||||
{"nGetNativeFinalizer", "()J", (void*)PaintGlue::getNativeFinalizer},
|
||||
{"nInit", "()J", (void*)PaintGlue::init},
|
||||
{"nInitWithPaint", "(J)J", (void*)PaintGlue::initWithPaint},
|
||||
{"nBreakText", "(J[CIIFI[F)I", (void*)PaintGlue::breakTextC},
|
||||
{"nBreakText", "(JLjava/lang/String;ZFI[F)I", (void*)PaintGlue::breakTextS},
|
||||
{"nGetTextAdvances", "(J[CIIIII[FI)F", (void*)PaintGlue::getTextAdvances___CIIIII_FI},
|
||||
{"nGetTextAdvances", "(JLjava/lang/String;IIIII[FI)F",
|
||||
(void*)PaintGlue::getTextAdvances__StringIIIII_FI},
|
||||
|
||||
{"nGetTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
|
||||
{"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I",
|
||||
(void*) PaintGlue::getTextRunCursor__String},
|
||||
{"nGetTextPath", "(JI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
|
||||
{"nGetTextPath", "(JILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
|
||||
{"nGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
|
||||
(void*) PaintGlue::getStringBounds },
|
||||
{"nGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
|
||||
(void*) PaintGlue::getCharArrayBounds },
|
||||
{"nHasGlyph", "(JILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
|
||||
{"nGetRunAdvance", "(J[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
|
||||
{"nGetOffsetForAdvance", "(J[CIIIIZF)I",
|
||||
(void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
|
||||
{"nGetFontMetricsIntForText", "(J[CIIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
|
||||
(void*)PaintGlue::getFontMetricsIntForText___C},
|
||||
{"nGetFontMetricsIntForText",
|
||||
"(JLjava/lang/String;IIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
|
||||
(void*)PaintGlue::getFontMetricsIntForText___String},
|
||||
{"nGetTextRunCursor", "(J[CIIIII)I", (void*)PaintGlue::getTextRunCursor___C},
|
||||
{"nGetTextRunCursor", "(JLjava/lang/String;IIIII)I",
|
||||
(void*)PaintGlue::getTextRunCursor__String},
|
||||
{"nGetTextPath", "(JI[CIIFFJ)V", (void*)PaintGlue::getTextPath___C},
|
||||
{"nGetTextPath", "(JILjava/lang/String;IIFFJ)V", (void*)PaintGlue::getTextPath__String},
|
||||
{"nGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
|
||||
(void*)PaintGlue::getStringBounds},
|
||||
{"nGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
|
||||
(void*)PaintGlue::getCharArrayBounds},
|
||||
{"nHasGlyph", "(JILjava/lang/String;)Z", (void*)PaintGlue::hasGlyph},
|
||||
{"nGetRunAdvance", "(J[CIIIIZI)F", (void*)PaintGlue::getRunAdvance___CIIIIZI_F},
|
||||
{"nGetRunCharacterAdvance", "(J[CIIIIZI[FI)F",
|
||||
(void*)PaintGlue::getRunCharacterAdvance___CIIIIZI_FI_F},
|
||||
{"nGetOffsetForAdvance", "(J[CIIIIZF)I", (void*)PaintGlue::getOffsetForAdvance___CIIIIZF_I},
|
||||
{"nGetFontMetricsIntForText", "(J[CIIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
|
||||
(void*)PaintGlue::getFontMetricsIntForText___C},
|
||||
{"nGetFontMetricsIntForText",
|
||||
"(JLjava/lang/String;IIIIZLandroid/graphics/Paint$FontMetricsInt;)V",
|
||||
(void*)PaintGlue::getFontMetricsIntForText___String},
|
||||
|
||||
// --------------- @FastNative ----------------------
|
||||
// --------------- @FastNative ----------------------
|
||||
|
||||
{"nSetTextLocales","(JLjava/lang/String;)I", (void*) PaintGlue::setTextLocales},
|
||||
{"nSetFontFeatureSettings","(JLjava/lang/String;)V",
|
||||
(void*) PaintGlue::setFontFeatureSettings},
|
||||
{"nGetFontMetrics", "(JLandroid/graphics/Paint$FontMetrics;)F",
|
||||
(void*)PaintGlue::getFontMetrics},
|
||||
{"nGetFontMetricsInt", "(JLandroid/graphics/Paint$FontMetricsInt;)I",
|
||||
(void*)PaintGlue::getFontMetricsInt},
|
||||
{"nSetTextLocales", "(JLjava/lang/String;)I", (void*)PaintGlue::setTextLocales},
|
||||
{"nSetFontFeatureSettings", "(JLjava/lang/String;)V",
|
||||
(void*)PaintGlue::setFontFeatureSettings},
|
||||
{"nGetFontMetrics", "(JLandroid/graphics/Paint$FontMetrics;)F",
|
||||
(void*)PaintGlue::getFontMetrics},
|
||||
{"nGetFontMetricsInt", "(JLandroid/graphics/Paint$FontMetricsInt;)I",
|
||||
(void*)PaintGlue::getFontMetricsInt},
|
||||
|
||||
// --------------- @CriticalNative ------------------
|
||||
// --------------- @CriticalNative ------------------
|
||||
|
||||
{"nReset","(J)V", (void*) PaintGlue::reset},
|
||||
{"nSet","(JJ)V", (void*) PaintGlue::assign},
|
||||
{"nGetFlags","(J)I", (void*) PaintGlue::getFlags},
|
||||
{"nSetFlags","(JI)V", (void*) PaintGlue::setFlags},
|
||||
{"nGetHinting","(J)I", (void*) PaintGlue::getHinting},
|
||||
{"nSetHinting","(JI)V", (void*) PaintGlue::setHinting},
|
||||
{"nSetAntiAlias","(JZ)V", (void*) PaintGlue::setAntiAlias},
|
||||
{"nSetSubpixelText","(JZ)V", (void*) PaintGlue::setSubpixelText},
|
||||
{"nSetLinearText","(JZ)V", (void*) PaintGlue::setLinearText},
|
||||
{"nSetUnderlineText","(JZ)V", (void*) PaintGlue::setUnderlineText},
|
||||
{"nSetStrikeThruText","(JZ)V", (void*) PaintGlue::setStrikeThruText},
|
||||
{"nSetFakeBoldText","(JZ)V", (void*) PaintGlue::setFakeBoldText},
|
||||
{"nSetFilterBitmap","(JZ)V", (void*) PaintGlue::setFilterBitmap},
|
||||
{"nSetDither","(JZ)V", (void*) PaintGlue::setDither},
|
||||
{"nGetStyle","(J)I", (void*) PaintGlue::getStyle},
|
||||
{"nSetStyle","(JI)V", (void*) PaintGlue::setStyle},
|
||||
{"nSetColor","(JI)V", (void*) PaintGlue::setColor},
|
||||
{"nSetColor","(JJJ)V", (void*) PaintGlue::setColorLong},
|
||||
{"nSetAlpha","(JI)V", (void*) PaintGlue::setAlpha},
|
||||
{"nGetStrokeWidth","(J)F", (void*) PaintGlue::getStrokeWidth},
|
||||
{"nSetStrokeWidth","(JF)V", (void*) PaintGlue::setStrokeWidth},
|
||||
{"nGetStrokeMiter","(J)F", (void*) PaintGlue::getStrokeMiter},
|
||||
{"nSetStrokeMiter","(JF)V", (void*) PaintGlue::setStrokeMiter},
|
||||
{"nGetStrokeCap","(J)I", (void*) PaintGlue::getStrokeCap},
|
||||
{"nSetStrokeCap","(JI)V", (void*) PaintGlue::setStrokeCap},
|
||||
{"nGetStrokeJoin","(J)I", (void*) PaintGlue::getStrokeJoin},
|
||||
{"nSetStrokeJoin","(JI)V", (void*) PaintGlue::setStrokeJoin},
|
||||
{"nGetFillPath","(JJJ)Z", (void*) PaintGlue::getFillPath},
|
||||
{"nSetShader","(JJ)J", (void*) PaintGlue::setShader},
|
||||
{"nSetColorFilter","(JJ)J", (void*) PaintGlue::setColorFilter},
|
||||
{"nSetXfermode","(JI)V", (void*) PaintGlue::setXfermode},
|
||||
{"nSetPathEffect","(JJ)J", (void*) PaintGlue::setPathEffect},
|
||||
{"nSetMaskFilter","(JJ)J", (void*) PaintGlue::setMaskFilter},
|
||||
{"nSetTypeface","(JJ)V", (void*) PaintGlue::setTypeface},
|
||||
{"nGetTextAlign","(J)I", (void*) PaintGlue::getTextAlign},
|
||||
{"nSetTextAlign","(JI)V", (void*) PaintGlue::setTextAlign},
|
||||
{"nSetTextLocalesByMinikinLocaleListId","(JI)V",
|
||||
(void*) PaintGlue::setTextLocalesByMinikinLocaleListId},
|
||||
{"nIsElegantTextHeight","(J)Z", (void*) PaintGlue::isElegantTextHeight},
|
||||
{"nSetElegantTextHeight","(JZ)V", (void*) PaintGlue::setElegantTextHeight},
|
||||
{"nGetTextSize","(J)F", (void*) PaintGlue::getTextSize},
|
||||
{"nSetTextSize","(JF)V", (void*) PaintGlue::setTextSize},
|
||||
{"nGetTextScaleX","(J)F", (void*) PaintGlue::getTextScaleX},
|
||||
{"nSetTextScaleX","(JF)V", (void*) PaintGlue::setTextScaleX},
|
||||
{"nGetTextSkewX","(J)F", (void*) PaintGlue::getTextSkewX},
|
||||
{"nSetTextSkewX","(JF)V", (void*) PaintGlue::setTextSkewX},
|
||||
{"nGetLetterSpacing","(J)F", (void*) PaintGlue::getLetterSpacing},
|
||||
{"nSetLetterSpacing","(JF)V", (void*) PaintGlue::setLetterSpacing},
|
||||
{"nGetWordSpacing","(J)F", (void*) PaintGlue::getWordSpacing},
|
||||
{"nSetWordSpacing","(JF)V", (void*) PaintGlue::setWordSpacing},
|
||||
{"nGetStartHyphenEdit", "(J)I", (void*) PaintGlue::getStartHyphenEdit},
|
||||
{"nGetEndHyphenEdit", "(J)I", (void*) PaintGlue::getEndHyphenEdit},
|
||||
{"nSetStartHyphenEdit", "(JI)V", (void*) PaintGlue::setStartHyphenEdit},
|
||||
{"nSetEndHyphenEdit", "(JI)V", (void*) PaintGlue::setEndHyphenEdit},
|
||||
{"nAscent","(J)F", (void*) PaintGlue::ascent},
|
||||
{"nDescent","(J)F", (void*) PaintGlue::descent},
|
||||
{"nGetUnderlinePosition","(J)F", (void*) PaintGlue::getUnderlinePosition},
|
||||
{"nGetUnderlineThickness","(J)F", (void*) PaintGlue::getUnderlineThickness},
|
||||
{"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition},
|
||||
{"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness},
|
||||
{"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
|
||||
{"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
|
||||
{"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
|
||||
{"nReset", "(J)V", (void*)PaintGlue::reset},
|
||||
{"nSet", "(JJ)V", (void*)PaintGlue::assign},
|
||||
{"nGetFlags", "(J)I", (void*)PaintGlue::getFlags},
|
||||
{"nSetFlags", "(JI)V", (void*)PaintGlue::setFlags},
|
||||
{"nGetHinting", "(J)I", (void*)PaintGlue::getHinting},
|
||||
{"nSetHinting", "(JI)V", (void*)PaintGlue::setHinting},
|
||||
{"nSetAntiAlias", "(JZ)V", (void*)PaintGlue::setAntiAlias},
|
||||
{"nSetSubpixelText", "(JZ)V", (void*)PaintGlue::setSubpixelText},
|
||||
{"nSetLinearText", "(JZ)V", (void*)PaintGlue::setLinearText},
|
||||
{"nSetUnderlineText", "(JZ)V", (void*)PaintGlue::setUnderlineText},
|
||||
{"nSetStrikeThruText", "(JZ)V", (void*)PaintGlue::setStrikeThruText},
|
||||
{"nSetFakeBoldText", "(JZ)V", (void*)PaintGlue::setFakeBoldText},
|
||||
{"nSetFilterBitmap", "(JZ)V", (void*)PaintGlue::setFilterBitmap},
|
||||
{"nSetDither", "(JZ)V", (void*)PaintGlue::setDither},
|
||||
{"nGetStyle", "(J)I", (void*)PaintGlue::getStyle},
|
||||
{"nSetStyle", "(JI)V", (void*)PaintGlue::setStyle},
|
||||
{"nSetColor", "(JI)V", (void*)PaintGlue::setColor},
|
||||
{"nSetColor", "(JJJ)V", (void*)PaintGlue::setColorLong},
|
||||
{"nSetAlpha", "(JI)V", (void*)PaintGlue::setAlpha},
|
||||
{"nGetStrokeWidth", "(J)F", (void*)PaintGlue::getStrokeWidth},
|
||||
{"nSetStrokeWidth", "(JF)V", (void*)PaintGlue::setStrokeWidth},
|
||||
{"nGetStrokeMiter", "(J)F", (void*)PaintGlue::getStrokeMiter},
|
||||
{"nSetStrokeMiter", "(JF)V", (void*)PaintGlue::setStrokeMiter},
|
||||
{"nGetStrokeCap", "(J)I", (void*)PaintGlue::getStrokeCap},
|
||||
{"nSetStrokeCap", "(JI)V", (void*)PaintGlue::setStrokeCap},
|
||||
{"nGetStrokeJoin", "(J)I", (void*)PaintGlue::getStrokeJoin},
|
||||
{"nSetStrokeJoin", "(JI)V", (void*)PaintGlue::setStrokeJoin},
|
||||
{"nGetFillPath", "(JJJ)Z", (void*)PaintGlue::getFillPath},
|
||||
{"nSetShader", "(JJ)J", (void*)PaintGlue::setShader},
|
||||
{"nSetColorFilter", "(JJ)J", (void*)PaintGlue::setColorFilter},
|
||||
{"nSetXfermode", "(JI)V", (void*)PaintGlue::setXfermode},
|
||||
{"nSetPathEffect", "(JJ)J", (void*)PaintGlue::setPathEffect},
|
||||
{"nSetMaskFilter", "(JJ)J", (void*)PaintGlue::setMaskFilter},
|
||||
{"nSetTypeface", "(JJ)V", (void*)PaintGlue::setTypeface},
|
||||
{"nGetTextAlign", "(J)I", (void*)PaintGlue::getTextAlign},
|
||||
{"nSetTextAlign", "(JI)V", (void*)PaintGlue::setTextAlign},
|
||||
{"nSetTextLocalesByMinikinLocaleListId", "(JI)V",
|
||||
(void*)PaintGlue::setTextLocalesByMinikinLocaleListId},
|
||||
{"nIsElegantTextHeight", "(J)Z", (void*)PaintGlue::isElegantTextHeight},
|
||||
{"nSetElegantTextHeight", "(JZ)V", (void*)PaintGlue::setElegantTextHeight},
|
||||
{"nGetTextSize", "(J)F", (void*)PaintGlue::getTextSize},
|
||||
{"nSetTextSize", "(JF)V", (void*)PaintGlue::setTextSize},
|
||||
{"nGetTextScaleX", "(J)F", (void*)PaintGlue::getTextScaleX},
|
||||
{"nSetTextScaleX", "(JF)V", (void*)PaintGlue::setTextScaleX},
|
||||
{"nGetTextSkewX", "(J)F", (void*)PaintGlue::getTextSkewX},
|
||||
{"nSetTextSkewX", "(JF)V", (void*)PaintGlue::setTextSkewX},
|
||||
{"nGetLetterSpacing", "(J)F", (void*)PaintGlue::getLetterSpacing},
|
||||
{"nSetLetterSpacing", "(JF)V", (void*)PaintGlue::setLetterSpacing},
|
||||
{"nGetWordSpacing", "(J)F", (void*)PaintGlue::getWordSpacing},
|
||||
{"nSetWordSpacing", "(JF)V", (void*)PaintGlue::setWordSpacing},
|
||||
{"nGetStartHyphenEdit", "(J)I", (void*)PaintGlue::getStartHyphenEdit},
|
||||
{"nGetEndHyphenEdit", "(J)I", (void*)PaintGlue::getEndHyphenEdit},
|
||||
{"nSetStartHyphenEdit", "(JI)V", (void*)PaintGlue::setStartHyphenEdit},
|
||||
{"nSetEndHyphenEdit", "(JI)V", (void*)PaintGlue::setEndHyphenEdit},
|
||||
{"nAscent", "(J)F", (void*)PaintGlue::ascent},
|
||||
{"nDescent", "(J)F", (void*)PaintGlue::descent},
|
||||
{"nGetUnderlinePosition", "(J)F", (void*)PaintGlue::getUnderlinePosition},
|
||||
{"nGetUnderlineThickness", "(J)F", (void*)PaintGlue::getUnderlineThickness},
|
||||
{"nGetStrikeThruPosition", "(J)F", (void*)PaintGlue::getStrikeThruPosition},
|
||||
{"nGetStrikeThruThickness", "(J)F", (void*)PaintGlue::getStrikeThruThickness},
|
||||
{"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
|
||||
{"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
|
||||
{"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
|
||||
};
|
||||
|
||||
|
||||
int register_android_graphics_Paint(JNIEnv* env) {
|
||||
return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user