Home | History | Annotate | Download | only in text
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.text;
     18 
     19 import android.icu.lang.UCharacter;
     20 import android.icu.lang.UProperty;
     21 
     22 /**
     23  * An utility class for Emoji.
     24  * @hide
     25  */
     26 public class Emoji {
     27     public static int COMBINING_ENCLOSING_KEYCAP = 0x20E3;
     28 
     29     public static int ZERO_WIDTH_JOINER = 0x200D;
     30 
     31     public static int VARIATION_SELECTOR_16 = 0xFE0F;
     32 
     33     public static int CANCEL_TAG = 0xE007F;
     34 
     35     /**
     36      * Returns true if the given code point is regional indicator symbol.
     37      */
     38     public static boolean isRegionalIndicatorSymbol(int codePoint) {
     39         return 0x1F1E6 <= codePoint && codePoint <= 0x1F1FF;
     40     }
     41 
     42     /**
     43      * Returns true if the given code point is emoji modifier.
     44      */
     45     public static boolean isEmojiModifier(int codePoint) {
     46         return UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI_MODIFIER);
     47     }
     48 
     49     //
     50 
     51     /**
     52      * Returns true if the given code point is emoji modifier base.
     53      * @param c codepoint to check
     54      * @return true if is emoji modifier base
     55      */
     56     public static boolean isEmojiModifierBase(int c) {
     57         // These two characters were removed from Emoji_Modifier_Base in Emoji 4.0, but we need to
     58         // keep them as emoji modifier bases since there are fonts and user-generated text out there
     59         // that treats these as potential emoji bases.
     60         if (c == 0x1F91D || c == 0x1F93C) {
     61             return true;
     62         }
     63         // Emoji Modifier Base characters new in Unicode emoji 11
     64         // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
     65         // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
     66         if ((0x1F9B5 <= c && c <= 0x1F9B6) || (0x1F9B8 <= c && c <= 0x1F9B9)) {
     67             return true;
     68         }
     69         return UCharacter.hasBinaryProperty(c, UProperty.EMOJI_MODIFIER_BASE);
     70     }
     71 
     72     /**
     73      * Returns true if the character is a new emoji still not supported in our version of ICU.
     74      */
     75     public static boolean isNewEmoji(int c) {
     76         // Emoji characters new in Unicode emoji 11
     77         // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
     78         // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
     79         if (c < 0x1F6F9 || c > 0x1F9FF) {
     80             // Optimization for characters outside the new emoji range.
     81             return false;
     82         }
     83         return c == 0x265F || c == 0x267E || c == 0x1F6F9 || c == 0x1F97A
     84                 || (0x1F94D <= c && c <= 0x1F94F)
     85                 || (0x1F96C <= c && c <= 0x1F970)
     86                 || (0x1F973 <= c && c <= 0x1F976)
     87                 || (0x1F97C <= c && c <= 0x1F97F)
     88                 || (0x1F998 <= c && c <= 0x1F9A2)
     89                 || (0x1F9B0 <= c && c <= 0x1F9B9)
     90                 || (0x1F9C1 <= c && c <= 0x1F9C2)
     91                 || (0x1F9E7 <= c && c <= 0x1F9FF);
     92     }
     93 
     94     /**
     95      * Returns true if the character has Emoji property.
     96      */
     97     public static boolean isEmoji(int codePoint) {
     98         return isNewEmoji(codePoint) || UCharacter.hasBinaryProperty(codePoint, UProperty.EMOJI);
     99     }
    100 
    101     // Returns true if the character can be a base character of COMBINING ENCLOSING KEYCAP.
    102     public static boolean isKeycapBase(int codePoint) {
    103         return ('0' <= codePoint && codePoint <= '9') || codePoint == '#' || codePoint == '*';
    104     }
    105 
    106     /**
    107      * Returns true if the character can be a part of tag_spec in emoji tag sequence.
    108      *
    109      * Note that 0xE007F (CANCEL TAG) is not included.
    110      */
    111     public static boolean isTagSpecChar(int codePoint) {
    112         return 0xE0020 <= codePoint && codePoint <= 0xE007E;
    113     }
    114 }
    115