Merge "Add Paint methods for cursor positioning"
This commit is contained in:
@@ -11524,8 +11524,12 @@ package android.graphics {
|
||||
method public int getHinting();
|
||||
method public float getLetterSpacing();
|
||||
method public android.graphics.MaskFilter getMaskFilter();
|
||||
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
|
||||
method public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
|
||||
method public android.graphics.PathEffect getPathEffect();
|
||||
method public deprecated android.graphics.Rasterizer getRasterizer();
|
||||
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
|
||||
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
|
||||
method public android.graphics.Shader getShader();
|
||||
method public android.graphics.Paint.Cap getStrokeCap();
|
||||
method public android.graphics.Paint.Join getStrokeJoin();
|
||||
|
||||
@@ -11818,8 +11818,12 @@ package android.graphics {
|
||||
method public int getHinting();
|
||||
method public float getLetterSpacing();
|
||||
method public android.graphics.MaskFilter getMaskFilter();
|
||||
method public int getOffsetForAdvance(char[], int, int, int, int, boolean, float);
|
||||
method public int getOffsetForAdvance(java.lang.CharSequence, int, int, int, int, boolean, float);
|
||||
method public android.graphics.PathEffect getPathEffect();
|
||||
method public deprecated android.graphics.Rasterizer getRasterizer();
|
||||
method public float getRunAdvance(char[], int, int, int, int, boolean, int);
|
||||
method public float getRunAdvance(java.lang.CharSequence, int, int, int, int, boolean, int);
|
||||
method public android.graphics.Shader getShader();
|
||||
method public android.graphics.Paint.Cap getStrokeCap();
|
||||
method public android.graphics.Paint.Join getStrokeJoin();
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#include "jni.h"
|
||||
#include "GraphicsJNI.h"
|
||||
#include "core_jni_helpers.h"
|
||||
#include <ScopedUtfChars.h>
|
||||
#include <ScopedStringChars.h>
|
||||
#include <ScopedUtfChars.h>
|
||||
|
||||
#include "SkBlurDrawLooper.h"
|
||||
#include "SkColorFilter.h"
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "utils/Blur.h"
|
||||
|
||||
#include <minikin/GraphemeBreak.h>
|
||||
#include <minikin/Measurement.h>
|
||||
#include "MinikinSkia.h"
|
||||
#include "MinikinUtils.h"
|
||||
#include "Paint.h"
|
||||
@@ -1038,6 +1039,48 @@ public:
|
||||
return nGlyphs > 0 && !layoutContainsNotdef(layout);
|
||||
}
|
||||
|
||||
static jfloat doRunAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
|
||||
jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
|
||||
Layout layout;
|
||||
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
|
||||
return getRunAdvance(layout, buf, start, count, offset);
|
||||
}
|
||||
|
||||
static jfloat getRunAdvance___CIIIIZI_F(JNIEnv *env, jclass, jlong paintHandle,
|
||||
jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
|
||||
jint contextEnd, jboolean isRtl, jint offset) {
|
||||
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
// TODO performance: optimize JNI array access
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
jfloat result = doRunAdvance(paint, typeface, textArray + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart, isRtl, offset);
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
return result;
|
||||
}
|
||||
|
||||
static jint doOffsetForAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
|
||||
jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) {
|
||||
Layout layout;
|
||||
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
|
||||
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, buf, start, count, bufSize);
|
||||
return getOffsetForAdvance(layout, buf, start, count, advance);
|
||||
}
|
||||
static jint getOffsetForAdvance___CIIIIZF_I(JNIEnv *env, jclass, jlong paintHandle,
|
||||
jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
|
||||
jint contextEnd, jboolean isRtl, jfloat advance) {
|
||||
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
|
||||
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
|
||||
// TODO performance: optimize JNI array access
|
||||
jchar* textArray = env->GetCharArrayElements(text, NULL);
|
||||
jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart,
|
||||
start - contextStart, end - start, contextEnd - contextStart, isRtl, advance);
|
||||
result += contextStart;
|
||||
env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static JNINativeMethod methods[] = {
|
||||
@@ -1094,36 +1137,43 @@ static JNINativeMethod methods[] = {
|
||||
{"setTextSkewX","!(F)V", (void*) PaintGlue::setTextSkewX},
|
||||
{"native_getLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing},
|
||||
{"native_setLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing},
|
||||
{"native_setFontFeatureSettings","(JLjava/lang/String;)V", (void*) PaintGlue::setFontFeatureSettings},
|
||||
{"native_setFontFeatureSettings","(JLjava/lang/String;)V",
|
||||
(void*) PaintGlue::setFontFeatureSettings},
|
||||
{"native_getHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit},
|
||||
{"native_setHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit},
|
||||
{"ascent","!()F", (void*) PaintGlue::ascent},
|
||||
{"descent","!()F", (void*) PaintGlue::descent},
|
||||
|
||||
{"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)PaintGlue::getFontMetrics},
|
||||
{"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)PaintGlue::getFontMetricsInt},
|
||||
{"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F",
|
||||
(void*)PaintGlue::getFontMetrics},
|
||||
{"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I",
|
||||
(void*)PaintGlue::getFontMetricsInt},
|
||||
{"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII},
|
||||
{"native_measureText","(Ljava/lang/String;I)F", (void*) PaintGlue::measureText_StringI},
|
||||
{"native_measureText","(Ljava/lang/String;III)F", (void*) PaintGlue::measureText_StringIII},
|
||||
{"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC},
|
||||
{"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS},
|
||||
{"native_getTextWidths","(JJ[CIII[F)I", (void*) PaintGlue::getTextWidths___CIII_F},
|
||||
{"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) PaintGlue::getTextWidths__StringIII_F},
|
||||
{"native_getTextWidths","(JJLjava/lang/String;III[F)I",
|
||||
(void*) PaintGlue::getTextWidths__StringIII_F},
|
||||
{"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F",
|
||||
(void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI},
|
||||
(void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI},
|
||||
{"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F",
|
||||
(void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI},
|
||||
(void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI},
|
||||
|
||||
{"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C},
|
||||
{"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
|
||||
(void*) PaintGlue::getTextRunCursor__String},
|
||||
{"native_getTextPath","(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
|
||||
{"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
|
||||
(void*) PaintGlue::getTextRunCursor__String},
|
||||
{"native_getTextPath", "(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C},
|
||||
{"native_getTextPath", "(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String},
|
||||
{"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
|
||||
(void*) PaintGlue::getStringBounds },
|
||||
(void*) PaintGlue::getStringBounds },
|
||||
{"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
|
||||
(void*) PaintGlue::getCharArrayBounds },
|
||||
{"native_hasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
|
||||
(void*) PaintGlue::getCharArrayBounds },
|
||||
{"native_hasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
|
||||
{"native_getRunAdvance", "(JJ[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F},
|
||||
{"native_getOffsetForAdvance", "(JJ[CIIIIZF)I",
|
||||
(void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I},
|
||||
|
||||
{"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
|
||||
{"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
|
||||
|
||||
@@ -2269,6 +2269,168 @@ public class Paint {
|
||||
return native_hasGlyph(mNativePaint, mNativeTypeface, mBidiFlags, string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure cursor position within a run of text.
|
||||
*
|
||||
* <p>The run of text includes the characters from {@code start} to {@code end} in the text. In
|
||||
* addition, the range {@code contextStart} to {@code contextEnd} is used as context for the
|
||||
* purpose of complex text shaping, such as Arabic text potentially shaped differently based on
|
||||
* the text next to it.
|
||||
*
|
||||
* All text outside the range {@code contextStart..contextEnd} is ignored. The text between
|
||||
* {@code start} and {@code end} will be laid out to be measured.
|
||||
*
|
||||
* The returned width measurement is the advance from {@code start} to {@code offset}. It is
|
||||
* generally a positive value, no matter the direction of the run. If {@code offset == end},
|
||||
* the return value is simply the width of the whole run from {@code start} to {@code end}.
|
||||
*
|
||||
* Ligatures are formed for characters in the range {@code start..end} (but not for
|
||||
* {@code start..contextStart} or {@code end..contextEnd}). If {@code offset} points to a
|
||||
* character in the middle of such a formed ligature, but at a grapheme cluster boundary, the
|
||||
* return value will also reflect an advance in the middle of the ligature. See
|
||||
* {@link #getOffsetForAdvance} for more discussion of grapheme cluster boundaries.
|
||||
*
|
||||
* The direction of the run is explicitly specified by {@code isRtl}. Thus, this method is
|
||||
* suitable only for runs of a single direction.
|
||||
*
|
||||
* <p>All indices are relative to the start of {@code text}. Further, {@code 0 <= contextStart
|
||||
* <= start <= offset <= end <= contextEnd <= text.length} must hold on entry.
|
||||
*
|
||||
* @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 range to measure
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param offset index of caret position
|
||||
* @return width measurement between start and offset
|
||||
*/
|
||||
public float getRunAdvance(char[] text, int start, int end, int contextStart, int contextEnd,
|
||||
boolean isRtl, int offset) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if ((contextStart | start | offset | end | contextEnd
|
||||
| start - contextStart | offset - start | end - offset
|
||||
| contextEnd - end | text.length - contextEnd) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (end == start) {
|
||||
return 0.0f;
|
||||
}
|
||||
// TODO: take mCompatScaling into account (or eliminate compat scaling)?
|
||||
return native_getRunAdvance(mNativePaint, mNativeTypeface, text, start, end,
|
||||
contextStart, contextEnd, isRtl, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getRunAdvance(char[], int, int, int, int, boolean, 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 range to measure
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param offset index of caret position
|
||||
* @return width measurement between start and offset
|
||||
*/
|
||||
public float getRunAdvance(CharSequence text, int start, int end, int contextStart,
|
||||
int contextEnd, boolean isRtl, int offset) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if ((contextStart | start | offset | end | contextEnd
|
||||
| start - contextStart | offset - start | end - offset
|
||||
| contextEnd - end | text.length() - contextEnd) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (end == start) {
|
||||
return 0.0f;
|
||||
}
|
||||
// TODO performance: specialized alternatives to avoid buffer copy, if win is significant
|
||||
char[] buf = TemporaryBuffer.obtain(contextEnd - contextStart);
|
||||
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
|
||||
float result = getRunAdvance(buf, start - contextStart, end - contextStart, 0,
|
||||
contextEnd - contextStart, isRtl, offset - contextStart);
|
||||
TemporaryBuffer.recycle(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the character offset within the string whose position is closest to the specified
|
||||
* horizontal position.
|
||||
*
|
||||
* <p>The returned value is generally the value of {@code offset} for which
|
||||
* {@link #getRunAdvance} yields a result most closely approximating {@code advance},
|
||||
* and which is also on a grapheme cluster boundary. As such, it is the preferred method
|
||||
* for positioning a cursor in response to a touch or pointer event. The grapheme cluster
|
||||
* boundaries are based on
|
||||
* <a href="http://unicode.org/reports/tr29/">Unicode Standard Annex #29</a> but with some
|
||||
* tailoring for better user experience.
|
||||
*
|
||||
* <p>Note that {@code advance} is a (generally positive) width measurement relative to the start
|
||||
* of the run. Thus, for RTL runs it the distance from the point to the right edge.
|
||||
*
|
||||
* <p>All indices are relative to the start of {@code text}. Further, {@code 0 <= contextStart
|
||||
* <= start <= end <= contextEnd <= text.length} must hold on entry, and {@code start <= result
|
||||
* <= end} will hold on return.
|
||||
*
|
||||
* @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 range to measure
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param advance width relative to start of run
|
||||
* @return index of offset
|
||||
*/
|
||||
public int getOffsetForAdvance(char[] text, int start, int end, int contextStart,
|
||||
int contextEnd, boolean isRtl, float advance) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if ((contextStart | start | end | contextEnd
|
||||
| start - contextStart | end - start | contextEnd - end
|
||||
| text.length - contextEnd) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
// TODO: take mCompatScaling into account (or eliminate compat scaling)?
|
||||
return native_getOffsetForAdvance(mNativePaint, mNativeTypeface, text, start, end,
|
||||
contextStart, contextEnd, isRtl, advance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getOffsetForAdvance(char[], int, int, int, int, boolean, float)
|
||||
*
|
||||
* @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 range to measure
|
||||
* @param isRtl whether the run is in RTL direction
|
||||
* @param advance width relative to start of run
|
||||
* @return index of offset
|
||||
*/
|
||||
public int getOffsetForAdvance(CharSequence text, int start, int end, int contextStart,
|
||||
int contextEnd, boolean isRtl, float advance) {
|
||||
if (text == null) {
|
||||
throw new IllegalArgumentException("text cannot be null");
|
||||
}
|
||||
if ((contextStart | start | end | contextEnd
|
||||
| start - contextStart | end - start | contextEnd - end
|
||||
| text.length() - contextEnd) < 0) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
// TODO performance: specialized alternatives to avoid buffer copy, if win is significant
|
||||
char[] buf = TemporaryBuffer.obtain(contextEnd - contextStart);
|
||||
TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
|
||||
int result = getOffsetForAdvance(buf, start - contextStart, end - contextStart, 0,
|
||||
contextEnd - contextStart, isRtl, advance) + contextStart;
|
||||
TemporaryBuffer.recycle(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
@@ -2356,4 +2518,10 @@ public class Paint {
|
||||
private static native void native_setHyphenEdit(long native_object, int hyphen);
|
||||
private static native boolean native_hasGlyph(long native_object, long native_typeface,
|
||||
int bidiFlags, String string);
|
||||
private static native float native_getRunAdvance(long native_object, long native_typeface,
|
||||
char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
|
||||
int offset);
|
||||
private static native int native_getOffsetForAdvance(long native_object,
|
||||
long native_typeface, char[] text, int start, int end, int contextStart, int contextEnd,
|
||||
boolean isRtl, float advance);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user