182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project
382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License");
582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * you may not use this file except in compliance with the License.
682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * You may obtain a copy of the License at
782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *      http://www.apache.org/licenses/LICENSE-2.0
982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
1082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Unless required by applicable law or agreed to in writing, software
1182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS,
1282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * See the License for the specific language governing permissions and
1482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * limitations under the License.
1582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */
16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.emoji.text;
1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
18ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
1982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.graphics.Canvas;
2182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.graphics.Paint;
223dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport android.graphics.Typeface;
2338746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikas
24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.AnyThread;
25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntDef;
26ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntRange;
27ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull;
28ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RequiresApi;
29ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo;
3038746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikasimport androidx.text.emoji.flatbuffer.MetadataItem;
3138746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikasimport androidx.text.emoji.flatbuffer.MetadataList;
3282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.lang.annotation.Retention;
3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport java.lang.annotation.RetentionPolicy;
3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/**
3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Information about a single emoji.
3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * @hide
4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */
4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@RestrictTo(LIBRARY_GROUP)
4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@AnyThread
4377b5c5b734f9f665577d1e3d178615db43ae1d4fSiyamed Sinir@RequiresApi(19)
4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class EmojiMetadata {
4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Defines whether the system can render the emoji.
4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @IntDef({HAS_GLYPH_UNKNOWN, HAS_GLYPH_ABSENT, HAS_GLYPH_EXISTS})
4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @Retention(RetentionPolicy.SOURCE)
5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public @interface HasGlyph {
5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Not calculated on device yet.
5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public static final int HAS_GLYPH_UNKNOWN = 0;
5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Device cannot render the emoji.
6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public static final int HAS_GLYPH_ABSENT = 1;
6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Device can render the emoji.
6582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
6682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public static final int HAS_GLYPH_EXISTS = 2;
6782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
6882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
6982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @see #getMetadataItem()
7082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
7182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private static final ThreadLocal<MetadataItem> sMetadataItem = new ThreadLocal<>();
7282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
7382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
7482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Index of the EmojiMetadata in {@link MetadataList}.
7582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
7682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private final int mIndex;
7782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
7882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
7982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * MetadataRepo that holds this instance.
8082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
8182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private final MetadataRepo mMetadataRepo;
8282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
8382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
8482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Whether the system can render the emoji. Calculated at runtime on the device.
8582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
8682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @HasGlyph
8782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private volatile int mHasGlyph = HAS_GLYPH_UNKNOWN;
8882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
8982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    EmojiMetadata(@NonNull final MetadataRepo metadataRepo, @IntRange(from = 0) final int index) {
9082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mMetadataRepo = metadataRepo;
9182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mIndex = index;
9282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
9382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
9482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
9582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Draws the emoji represented by this EmojiMetadata onto a canvas with origin at (x,y), using
9682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * the specified paint.
9782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     *
9882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param canvas Canvas to be drawn
9982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param x x-coordinate of the origin of the emoji being drawn
10082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param y y-coordinate of the baseline of the emoji being drawn
10182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param paint Paint used for the text (e.g. color, size, style)
10282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
10382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public void draw(@NonNull final Canvas canvas, final float x, final float y,
10482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            @NonNull final Paint paint) {
1053dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final Typeface typeface = mMetadataRepo.getTypeface();
1063dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final Typeface oldTypeface = paint.getTypeface();
1073dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        paint.setTypeface(typeface);
10882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // MetadataRepo.getEmojiCharArray() is a continous array of chars that is used to store the
10982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // chars for emojis. since all emojis are mapped to a single codepoint, and since it is 2
11082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // chars wide, we assume that the start index of the current emoji is mIndex * 2, and it is
11182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // 2 chars long.
11282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final int charArrayStartIndex = mIndex * 2;
11382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        canvas.drawText(mMetadataRepo.getEmojiCharArray(), charArrayStartIndex, 2, x, y, paint);
1143dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        paint.setTypeface(oldTypeface);
11582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
11682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
11782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
118478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir     * @return return typeface to be used to render this metadata
119478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir     */
120478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    public Typeface getTypeface() {
121478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        return mMetadataRepo.getTypeface();
122478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    }
123478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir
124478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    /**
12582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return a ThreadLocal instance of MetadataItem for this EmojiMetadata
12682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
12782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    private MetadataItem getMetadataItem() {
12882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        MetadataItem result = sMetadataItem.get();
12982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        if (result == null) {
13082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            result = new MetadataItem();
13182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            sMetadataItem.set(result);
13282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        }
13382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // MetadataList is a wrapper around the metadata ByteBuffer. MetadataItem is a wrapper with
13482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // an index (pointer) on this ByteBuffer that represents a single emoji. Both are FlatBuffer
13582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // classes that wraps a ByteBuffer and gives access to the information in it. In order not
13682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // to create a wrapper class for each EmojiMetadata, we use mIndex as the index of the
13782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // MetadataItem in the ByteBuffer. We need to reiniitalize the current thread local instance
13882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // by executing the statement below. All the statement does is to set an int index in
13982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // MetadataItem. the same instance is used by all EmojiMetadata classes in the same thread.
14082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mMetadataRepo.getMetadataList().list(result, mIndex);
14182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return result;
14282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
14382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
14482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
14582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return unique id for the emoji
14682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
14782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public int getId() {
14882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().id();
14982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
15082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
15182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
15282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return width of the emoji image
15382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
15482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public short getWidth() {
15582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().width();
15682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
15782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
15882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
15982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return height of the emoji image
16082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
16182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public short getHeight() {
16282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().height();
16382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
16482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
16582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
16682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return in which metadata version the emoji was added to metadata
16782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
16882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public short getCompatAdded() {
16982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().compatAdded();
17082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
17182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
17282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
17382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return first SDK that the support for this emoji was added
17482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
17582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public short getSdkAdded() {
17682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().sdkAdded();
17782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
17882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
17982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
18082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return whether the emoji is in Emoji Presentation by default (without emoji
18182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * style selector 0xFE0F)
18282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
18382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @HasGlyph
18482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public int getHasGlyph() {
18582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return mHasGlyph;
18682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
18782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
18882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
18982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * Set whether the system can render the emoji.
19082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     *
19182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param hasGlyph {@code true} if system can render the emoji
19282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
19382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public void setHasGlyph(boolean hasGlyph) {
19482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        mHasGlyph = hasGlyph ? HAS_GLYPH_EXISTS : HAS_GLYPH_ABSENT;
19582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
19682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
19782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
19882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return whether the emoji is in Emoji Presentation by default (without emoji
19982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     *         style selector 0xFE0F)
20082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
20182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public boolean isDefaultEmoji() {
20282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().emojiStyle();
20382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
20482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
20582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
20682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @param index index of the codepoint
20782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     *
20882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return the codepoint at index
20982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
21082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public int getCodepointAt(int index) {
21182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().codepoints(index);
21282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
21382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
21482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    /**
21582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     * @return the length of the codepoints for this emoji
21682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir     */
21782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public int getCodepointsLength() {
21882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        return getMetadataItem().codepointsLength();
21982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
22082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
221478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    @Override
222478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    public String toString() {
223478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        final StringBuilder builder = new StringBuilder();
224478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        builder.append(super.toString());
225478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        builder.append(", id:");
226478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        builder.append(Integer.toHexString(getId()));
227478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        builder.append(", codepoints:");
228478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        final int codepointsLength = getCodepointsLength();
229478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        for (int i = 0; i < codepointsLength; i++) {
230478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir            builder.append(Integer.toHexString(getCodepointAt(i)));
231478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir            builder.append(" ");
232478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        }
233478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir        return builder.toString();
234478b4ffdd939482869779da95c45b259771a620bSiyamed Sinir    }
23582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir}
236