Merge "Add Paint.hasGlyph method"

This commit is contained in:
Raph Levien
2015-04-02 23:27:20 +00:00
committed by Android (Google) Code Review
5 changed files with 91 additions and 1 deletions

View File

@@ -11388,6 +11388,7 @@ package android.graphics {
method public int getTextWidths(java.lang.String, float[]);
method public android.graphics.Typeface getTypeface();
method public android.graphics.Xfermode getXfermode();
method public boolean hasGlyph(java.lang.String);
method public final boolean isAntiAlias();
method public final boolean isDither();
method public boolean isElegantTextHeight();

View File

@@ -11677,6 +11677,7 @@ package android.graphics {
method public int getTextWidths(java.lang.String, float[]);
method public android.graphics.Typeface getTypeface();
method public android.graphics.Xfermode getXfermode();
method public boolean hasGlyph(java.lang.String);
method public final boolean isAntiAlias();
method public final boolean isDither();
method public boolean isElegantTextHeight();

View File

@@ -23,6 +23,7 @@
#include "GraphicsJNI.h"
#include "core_jni_helpers.h"
#include <ScopedUtfChars.h>
#include <ScopedStringChars.h>
#include "SkBlurDrawLooper.h"
#include "SkColorFilter.h"
@@ -41,6 +42,8 @@
#include "Paint.h"
#include "TypefaceImpl.h"
#include <vector>
// temporary for debugging
#include <Caches.h>
#include <utils/Log.h>
@@ -972,6 +975,68 @@ public:
JNI_ABORT);
}
static jboolean layoutContainsNotdef(const Layout& layout) {
for (size_t i = 0; i < layout.nGlyphs(); i++) {
if (layout.getGlyphId(i) == 0) {
return true;
}
}
return false;
}
static jboolean hasGlyphVariation(const Paint* paint, TypefaceImpl* typeface, jint bidiFlags,
const jchar* chars, size_t size) {
// TODO: query font for whether character has variation selector; requires a corresponding
// function in Minikin.
return false;
}
static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
jint bidiFlags, jstring string) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
ScopedStringChars str(env, string);
/* start by rejecting variation selectors (not supported yet) */
size_t nChars = 0;
for (size_t i = 0; i < str.size(); i++) {
jchar c = str[i];
if (0xDC00 <= c && c <= 0xDFFF) {
// invalid UTF-16, unpaired trailing surrogate
return false;
} else if (0xD800 <= c && c <= 0xDBFF) {
if (i + 1 == str.size()) {
// invalid UTF-16, unpaired leading surrogate at end of string
return false;
}
i++;
jchar c2 = str[i];
if (!(0xDC00 <= c2 && c2 <= 0xDFFF)) {
// invalid UTF-16, unpaired leading surrogate
return false;
}
// UTF-16 encoding of range U+E0100..U+E01EF is DB40 DD00 .. DB40 DDEF
if (c == 0xDB40 && 0xDD00 <= c2 && c2 <= 0xDDEF) {
return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
}
} else if (0xFE00 <= c && c <= 0xFE0F) {
return hasGlyphVariation(paint, typeface, bidiFlags, str.get(), str.size());
}
nChars++;
}
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),
str.size());
size_t nGlyphs = layout.nGlyphs();
if (nGlyphs != 1 && nChars > 1) {
// multiple-character input, and was not a ligature
// TODO: handle ZWJ/ZWNJ characters specially so we can detect certain ligatures
// in joining scripts, such as Arabic and Mongolian.
return false;
}
return nGlyphs > 0 && !layoutContainsNotdef(layout);
}
};
static JNINativeMethod methods[] = {
@@ -1057,6 +1122,7 @@ static JNINativeMethod methods[] = {
(void*) PaintGlue::getStringBounds },
{"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
(void*) PaintGlue::getCharArrayBounds },
{"native_hasGlyph", "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },
{"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
{"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}

View File

@@ -18,7 +18,7 @@
#include "core_jni_helpers.h"
#include "GraphicsJNI.h"
#include <ScopedPrimitiveArray.h>
#include "ScopedPrimitiveArray.h"
#include "SkTypeface.h"
#include "TypefaceImpl.h"
#include <android_runtime/android_util_AssetManager.h>

View File

@@ -2249,6 +2249,26 @@ public class Paint {
bounds);
}
/**
* Determine whether the typeface set on the paint has a glyph supporting the string. The
* simplest case is when the string contains a single character, in which this method
* determines whether the font has the character. In the case of multiple characters, the
* method returns true if there is a single glyph representing the ligature. For example, if
* the input is a pair of regional indicator symbols, determine whether there is an emoji flag
* for the pair.
*
* Finally, if the string contains a variation selector, the method only returns true if
* the fonts contains a glyph specific to that variation.
*
* Checking is done on the entire fallback chain, not just the immediate font referenced.
*
* @param string the string to test whether there is glyph support
* @return true if the typeface has a glyph for the string
*/
public boolean hasGlyph(String string) {
return native_hasGlyph(mNativePaint, mNativeTypeface, mBidiFlags, string);
}
@Override
protected void finalize() throws Throwable {
try {
@@ -2334,4 +2354,6 @@ public class Paint {
String settings);
private static native int native_getHyphenEdit(long native_object);
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);
}