Make Paint.hasGlyph variation selector aware.
With this CL, Paint.hasGlyph returns true if the typeface supports
the passed code point and variation selector pair.
Bug: 11256006
Change-Id: If29cd0c5942dc78bd862804106e29539bdeee569
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 7fd288a..9b774b3 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -63,6 +63,11 @@
layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
}
+bool MinikinUtils::hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs) {
+ const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
+ return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
+}
+
float MinikinUtils::xOffsetForTextAlign(Paint* paint, const Layout& layout) {
switch (paint->getTextAlign()) {
case Paint::kCenter_Align:
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 1ee6245..5bf1eec 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -40,6 +40,8 @@
TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize);
+ static bool hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs);
+
static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index b50046f..9c11dd1 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -39,6 +39,7 @@
#include <minikin/GraphemeBreak.h>
#include <minikin/Measurement.h>
+#include <unicode/utf16.h>
#include "MinikinSkia.h"
#include "MinikinUtils.h"
#include "Paint.h"
@@ -852,45 +853,44 @@
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) */
+ /* Start by rejecting unsupported base code point and variation selector pairs. */
size_t nChars = 0;
+ const uint32_t kStartOfString = 0xFFFFFFFF;
+ uint32_t prevCp = kStartOfString;
for (size_t i = 0; i < str.size(); i++) {
- jchar c = str[i];
- if (0xDC00 <= c && c <= 0xDFFF) {
+ jchar cu = str[i];
+ uint32_t cp = cu;
+ if (U16_IS_TRAIL(cu)) {
// invalid UTF-16, unpaired trailing surrogate
return false;
- } else if (0xD800 <= c && c <= 0xDBFF) {
+ } else if (U16_IS_LEAD(cu)) {
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)) {
+ jchar cu2 = str[i];
+ if (!U16_IS_TRAIL(cu2)) {
// 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());
+ cp = U16_GET_SUPPLEMENTARY(cu, cu2);
+ }
+
+ if (prevCp != kStartOfString &&
+ ((0xFE00 <= cp && cp <= 0xFE0F) || (0xE0100 <= cp && cp <= 0xE01EF)) &&
+ !MinikinUtils::hasVariationSelector(typeface, prevCp, cp)) {
+ // No font has a glyph for the code point and variation selector pair.
+ return false;
}
nChars++;
+ prevCp = cp;
}
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, str.get(), 0, str.size(),