3 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 #include <dali-toolkit/internal/text/emoji-helper.h>
28 bool IsTextPresentationSequence(const TextAbstraction::Script& currentRunScript,
29 const TextAbstraction::Character& character)
31 return (IsSymbolOrEmojiOrTextScript(currentRunScript) && TextAbstraction::IsTextPresentationSelector(character));
34 bool IsEmojiPresentationSequence(const TextAbstraction::Script& currentRunScript,
35 const TextAbstraction::Character& character)
37 return ((IsSymbolOrEmojiScript(currentRunScript) || IsEmojiColorScript(currentRunScript)) &&
38 TextAbstraction::IsEmojiPresentationSelector(character));
41 bool IsEmojiSequence(const TextAbstraction::Script& currentRunScript,
42 const TextAbstraction::Character& character,
43 const TextAbstraction::Script& characterScript)
45 return (IsOneOfEmojiScripts(currentRunScript) &&
46 (IsOneOfEmojiScripts(characterScript) ||
47 TextAbstraction::IsZeroWidthJoiner(character) ||
48 TextAbstraction::IsZeroWidthNonJoiner(character) ||
49 TextAbstraction::IsEmojiItem(character) ||
50 TextAbstraction::IsMiscellaneousSymbolsAndArrowsEmoji(character) ||
51 TextAbstraction::IsDingbatsEmoji(character)));
54 bool IsNewSequence(const Character* const textBuffer,
55 const TextAbstraction::Script& currentRunScript,
56 const Length& currentCharacterIndex,
57 const Length& lastCharacterIndex,
58 TextAbstraction::Script& currentCharacterScript)
60 // Until now we have two cases : VariationSelector & Keycap
61 // In-case there are more cases then should be added in this function
63 return IsNewKeycapSequence(textBuffer, currentCharacterIndex, lastCharacterIndex, currentCharacterScript) ||
64 IsNewVariationSelectorSequence(textBuffer, currentRunScript, currentCharacterIndex, lastCharacterIndex, currentCharacterScript);
69 bool IsNewKeycapSequence(const Character* const textBuffer,
70 const Length& currentCharacterIndex,
71 const Length& lastCharacterIndex,
72 TextAbstraction::Script& currentCharacterScript)
74 // Ref: https://www.unicode.org/Public/emoji/14.0/emoji-sequences.txt Search on "Emoji_Keycap_Sequence"
75 // Ref: https://www.unicode.org/Public/emoji/14.0/emoji-test.txt Search on "subgroup: keycap"
77 // Default initialization does not keycap sequence
78 bool isNewKeycapSequence = false;
80 if(currentCharacterIndex <= lastCharacterIndex)
82 Character currentCharacter = *(textBuffer + currentCharacterIndex);
83 if(IsStartForKeycapSequence(currentCharacter))
85 if(!isNewKeycapSequence && currentCharacterIndex + 2 <= lastCharacterIndex)
87 Character characterOne = *(textBuffer + currentCharacterIndex + 1);
88 Character characterTwo = *(textBuffer + currentCharacterIndex + 2);
90 if(TextAbstraction::IsEmojiPresentationSelector(characterOne) &&
91 TextAbstraction::IsCombiningEnclosingKeycap(characterTwo))
93 isNewKeycapSequence = true;
94 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
96 } // if(!isNewKeycapSequence && currentCharacterIndex + 2 <= lastCharacterIndex)
97 } // if(IsStartForKeycapSequence(currentCharacter))
98 } // if(currentCharacterIndex < lastCharacterIndex)
100 return isNewKeycapSequence;
103 bool IsNewVariationSelectorSequence(const Character* const textBuffer,
104 const TextAbstraction::Script& currentRunScript,
105 const Length& currentCharacterIndex,
106 const Length& lastCharacterIndex,
107 TextAbstraction::Script& currentCharacterScript)
109 // Ref: Emoji and Text Presentation Selectors: https://www.unicode.org/reports/tr51/#Emoji_Variation_Selectors
110 // Ref: Emoji Variation Sequences for UTS #51: https://www.unicode.org/Public/14.0.0/ucd/emoji/emoji-variation-sequences.txt
112 // Default initialization does not VariationSelector sequence
113 bool isNewVariationSelectorSequence = false;
115 if(currentCharacterIndex <= lastCharacterIndex)
117 Character currentCharacter = *(textBuffer + currentCharacterIndex);
118 if(TextAbstraction::IsEmojiVariationSequences(currentCharacter))
120 if(!isNewVariationSelectorSequence && currentCharacterIndex + 1 <= lastCharacterIndex)
122 Character characterVS = *(textBuffer + currentCharacterIndex + 1);
124 if(TextAbstraction::IsEmojiPresentationSelector(characterVS))
126 isNewVariationSelectorSequence = currentRunScript != TextAbstraction::EMOJI_COLOR;
127 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
129 else if(TextAbstraction::IsTextPresentationSelector(characterVS))
131 isNewVariationSelectorSequence = currentRunScript != TextAbstraction::EMOJI_TEXT;
132 currentCharacterScript = TextAbstraction::EMOJI_TEXT;
135 } // if(!isNewVariationSelectorSequence && currentCharacterIndex + 1 <= lastCharacterIndex)
136 } // if(TextAbstraction::IsEmojiVariationSequences(currentCharacter))
137 } // if(currentCharacterIndex < lastCharacterIndex)
139 return isNewVariationSelectorSequence;
142 bool IsStartForKeycapSequence(const TextAbstraction::Character& character)
144 return (TextAbstraction::IsASCIIDigits(character) ||
145 TextAbstraction::CHAR_NUMBER_SIGN == character ||
146 TextAbstraction::CHAR_ASTERISK == character);
149 bool IsScriptChangedToFollowSequence(const TextAbstraction::Script& currentRunScript,
150 const TextAbstraction::Character& character,
151 TextAbstraction::Script& currentCharacterScript)
153 bool isUpdated = false;
156 if(TextAbstraction::IsCombiningEnclosingKeycap(character))
158 if(TextAbstraction::EMOJI == currentRunScript)
160 // Keycap and unqualified
161 // Emoji request a default presentation for an emoji character.
162 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI);
163 currentCharacterScript = TextAbstraction::EMOJI;
165 else if(TextAbstraction::EMOJI_COLOR == currentRunScript)
167 // Keycap and fully-qualified
168 // Emoji request an emoji presentation for an emoji character.
169 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
170 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
173 // Emoji(Text) Presentation cases
174 else if(IsTextPresentationSequence(currentRunScript, character))
176 // Emoji request a text presentation for an emoji character.
177 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_TEXT);
178 currentCharacterScript = TextAbstraction::EMOJI_TEXT;
180 // Emoji(Color) Presentation cases
181 else if(IsEmojiPresentationSequence(currentRunScript, character))
183 // Emoji request an emoji presentation for an emoji character.
184 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
185 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
188 else if(IsEmojiScript(currentRunScript) && IsEmojiScript(currentCharacterScript))
190 // Emoji request an emoji presentation for an emoji character.
191 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI);
192 currentCharacterScript = TextAbstraction::EMOJI;
195 else if(IsEmojiSequence(currentRunScript, character, currentCharacterScript))
197 // Emoji request an emoji presentation for an emoji character.
198 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
199 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
205 Character GetVariationSelectorByScript(const TextAbstraction::Script& script)
207 Character character = 0u;
208 if(TextAbstraction::EMOJI_COLOR == script)
210 character = TextAbstraction::CHAR_VARIATION_SELECTOR_16;
212 else if(TextAbstraction::EMOJI_TEXT == script)
214 character = TextAbstraction::CHAR_VARIATION_SELECTOR_15;
222 } // namespace Toolkit