Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f673acb6 authored by Raph Levien's avatar Raph Levien Committed by Android (Google) Code Review
Browse files

Merge "Add Paint.hasGlyph method"

parents fd93eaf2 f7f969e6
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -11388,6 +11388,7 @@ package android.graphics {
    method public int getTextWidths(java.lang.String, float[]);
    method public int getTextWidths(java.lang.String, float[]);
    method public android.graphics.Typeface getTypeface();
    method public android.graphics.Typeface getTypeface();
    method public android.graphics.Xfermode getXfermode();
    method public android.graphics.Xfermode getXfermode();
    method public boolean hasGlyph(java.lang.String);
    method public final boolean isAntiAlias();
    method public final boolean isAntiAlias();
    method public final boolean isDither();
    method public final boolean isDither();
    method public boolean isElegantTextHeight();
    method public boolean isElegantTextHeight();
+1 −0
Original line number Original line Diff line number Diff line
@@ -11677,6 +11677,7 @@ package android.graphics {
    method public int getTextWidths(java.lang.String, float[]);
    method public int getTextWidths(java.lang.String, float[]);
    method public android.graphics.Typeface getTypeface();
    method public android.graphics.Typeface getTypeface();
    method public android.graphics.Xfermode getXfermode();
    method public android.graphics.Xfermode getXfermode();
    method public boolean hasGlyph(java.lang.String);
    method public final boolean isAntiAlias();
    method public final boolean isAntiAlias();
    method public final boolean isDither();
    method public final boolean isDither();
    method public boolean isElegantTextHeight();
    method public boolean isElegantTextHeight();
+66 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@
#include "GraphicsJNI.h"
#include "GraphicsJNI.h"
#include "core_jni_helpers.h"
#include "core_jni_helpers.h"
#include <ScopedUtfChars.h>
#include <ScopedUtfChars.h>
#include <ScopedStringChars.h>


#include "SkBlurDrawLooper.h"
#include "SkBlurDrawLooper.h"
#include "SkColorFilter.h"
#include "SkColorFilter.h"
@@ -41,6 +42,8 @@
#include "Paint.h"
#include "Paint.h"
#include "TypefaceImpl.h"
#include "TypefaceImpl.h"


#include <vector>

// temporary for debugging
// temporary for debugging
#include <Caches.h>
#include <Caches.h>
#include <utils/Log.h>
#include <utils/Log.h>
@@ -972,6 +975,68 @@ public:
                                      JNI_ABORT);
                                      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[] = {
static JNINativeMethod methods[] = {
@@ -1057,6 +1122,7 @@ static JNINativeMethod methods[] = {
                                        (void*) PaintGlue::getStringBounds },
                                        (void*) PaintGlue::getStringBounds },
    {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
    {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
                                    (void*) PaintGlue::getCharArrayBounds },
                                    (void*) PaintGlue::getCharArrayBounds },
    {"native_hasGlyph",           "(JJILjava/lang/String;)Z", (void*) PaintGlue::hasGlyph },


    {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
    {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer},
    {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
    {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer}
+1 −1
Original line number Original line Diff line number Diff line
@@ -18,7 +18,7 @@
#include "core_jni_helpers.h"
#include "core_jni_helpers.h"


#include "GraphicsJNI.h"
#include "GraphicsJNI.h"
#include <ScopedPrimitiveArray.h>
#include "ScopedPrimitiveArray.h"
#include "SkTypeface.h"
#include "SkTypeface.h"
#include "TypefaceImpl.h"
#include "TypefaceImpl.h"
#include <android_runtime/android_util_AssetManager.h>
#include <android_runtime/android_util_AssetManager.h>
+22 −0
Original line number Original line Diff line number Diff line
@@ -2249,6 +2249,26 @@ public class Paint {
            bounds);
            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
    @Override
    protected void finalize() throws Throwable {
    protected void finalize() throws Throwable {
        try {
        try {
@@ -2334,4 +2354,6 @@ public class Paint {
                                                             String settings);
                                                             String settings);
    private static native int native_getHyphenEdit(long native_object);
    private static native int native_getHyphenEdit(long native_object);
    private static native void native_setHyphenEdit(long native_object, int hyphen);
    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);
}
}