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 (!(TextAbstraction::IsNegativeSquaredLatinCapitalLetter(character)) &&
46 (IsOneOfEmojiScripts(currentRunScript) &&
47 (IsOneOfEmojiScripts(characterScript) ||
48 TextAbstraction::IsZeroWidthJoiner(character) ||
49 TextAbstraction::IsZeroWidthNonJoiner(character) ||
50 TextAbstraction::IsEmojiItem(character) ||
51 TextAbstraction::IsMiscellaneousSymbolsAndArrowsEmoji(character) ||
52 TextAbstraction::IsDingbatsEmoji(character))));
55 bool IsNewSequence(const Character* const textBuffer,
56 const TextAbstraction::Script& currentRunScript,
57 const Length& currentCharacterIndex,
58 const Length& lastCharacterIndex,
59 TextAbstraction::Script& currentCharacterScript)
61 // Until now we have two cases : VariationSelector & Keycap
62 // In-case there are more cases then should be added in this function
64 return IsNewKeycapSequence(textBuffer, currentCharacterIndex, lastCharacterIndex, currentCharacterScript) ||
65 IsNewVariationSelectorSequence(textBuffer, currentRunScript, currentCharacterIndex, lastCharacterIndex, currentCharacterScript);
70 bool IsNewKeycapSequence(const Character* const textBuffer,
71 const Length& currentCharacterIndex,
72 const Length& lastCharacterIndex,
73 TextAbstraction::Script& currentCharacterScript)
75 // Ref: https://www.unicode.org/Public/emoji/14.0/emoji-sequences.txt Search on "Emoji_Keycap_Sequence"
76 // Ref: https://www.unicode.org/Public/emoji/14.0/emoji-test.txt Search on "subgroup: keycap"
78 // Default initialization does not keycap sequence
79 bool isNewKeycapSequence = false;
81 if(currentCharacterIndex <= lastCharacterIndex)
83 Character currentCharacter = *(textBuffer + currentCharacterIndex);
84 if(IsStartForKeycapSequence(currentCharacter))
86 if(!isNewKeycapSequence && currentCharacterIndex + 2 <= lastCharacterIndex)
88 Character characterOne = *(textBuffer + currentCharacterIndex + 1);
89 Character characterTwo = *(textBuffer + currentCharacterIndex + 2);
91 if(TextAbstraction::IsEmojiPresentationSelector(characterOne) &&
92 TextAbstraction::IsCombiningEnclosingKeycap(characterTwo))
94 isNewKeycapSequence = true;
95 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
97 } // if(!isNewKeycapSequence && currentCharacterIndex + 2 <= lastCharacterIndex)
98 } // if(IsStartForKeycapSequence(currentCharacter))
99 } // if(currentCharacterIndex < lastCharacterIndex)
101 return isNewKeycapSequence;
104 bool IsNewVariationSelectorSequence(const Character* const textBuffer,
105 const TextAbstraction::Script& currentRunScript,
106 const Length& currentCharacterIndex,
107 const Length& lastCharacterIndex,
108 TextAbstraction::Script& currentCharacterScript)
110 // Ref: Emoji and Text Presentation Selectors: https://www.unicode.org/reports/tr51/#Emoji_Variation_Selectors
111 // Ref: Emoji Variation Sequences for UTS #51: https://www.unicode.org/Public/14.0.0/ucd/emoji/emoji-variation-sequences.txt
113 // Default initialization does not VariationSelector sequence
114 bool isNewVariationSelectorSequence = false;
116 if(currentCharacterIndex <= lastCharacterIndex)
118 Character currentCharacter = *(textBuffer + currentCharacterIndex);
119 if(TextAbstraction::IsEmojiVariationSequences(currentCharacter))
121 if(!isNewVariationSelectorSequence && currentCharacterIndex + 1 <= lastCharacterIndex)
123 Character characterVS = *(textBuffer + currentCharacterIndex + 1);
125 if(TextAbstraction::IsEmojiPresentationSelector(characterVS))
127 isNewVariationSelectorSequence = currentRunScript != TextAbstraction::EMOJI_COLOR;
128 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
130 else if(TextAbstraction::IsTextPresentationSelector(characterVS))
132 isNewVariationSelectorSequence = currentRunScript != TextAbstraction::EMOJI_TEXT;
133 currentCharacterScript = TextAbstraction::EMOJI_TEXT;
136 } // if(!isNewVariationSelectorSequence && currentCharacterIndex + 1 <= lastCharacterIndex)
137 } // if(TextAbstraction::IsEmojiVariationSequences(currentCharacter))
138 } // if(currentCharacterIndex < lastCharacterIndex)
140 return isNewVariationSelectorSequence;
143 bool IsStartForKeycapSequence(const TextAbstraction::Character& character)
145 return (TextAbstraction::IsASCIIDigits(character) ||
146 TextAbstraction::CHAR_NUMBER_SIGN == character ||
147 TextAbstraction::CHAR_ASTERISK == character);
150 bool IsScriptChangedToFollowSequence(const TextAbstraction::Script& currentRunScript,
151 const TextAbstraction::Character& character,
152 TextAbstraction::Script& currentCharacterScript)
154 bool isUpdated = false;
157 if(TextAbstraction::IsCombiningEnclosingKeycap(character))
159 if(TextAbstraction::EMOJI == currentRunScript)
161 // Keycap and unqualified
162 // Emoji request a default presentation for an emoji character.
163 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI);
164 currentCharacterScript = TextAbstraction::EMOJI;
166 else if(TextAbstraction::EMOJI_COLOR == currentRunScript)
168 // Keycap and fully-qualified
169 // Emoji request an emoji presentation for an emoji character.
170 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
171 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
174 // Emoji(Text) Presentation cases
175 else if(IsTextPresentationSequence(currentRunScript, character))
177 // Emoji request a text presentation for an emoji character.
178 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_TEXT);
179 currentCharacterScript = TextAbstraction::EMOJI_TEXT;
181 // Emoji(Color) Presentation cases
182 else if(IsEmojiPresentationSequence(currentRunScript, character))
184 // Emoji request an emoji presentation for an emoji character.
185 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
186 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
189 else if(IsEmojiScript(currentRunScript) && IsEmojiScript(currentCharacterScript))
191 // Emoji request an emoji presentation for an emoji character.
192 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI);
193 currentCharacterScript = TextAbstraction::EMOJI;
196 else if(IsEmojiSequence(currentRunScript, character, currentCharacterScript))
198 // Emoji request an emoji presentation for an emoji character.
199 isUpdated = (currentCharacterScript != TextAbstraction::EMOJI_COLOR);
200 currentCharacterScript = TextAbstraction::EMOJI_COLOR;
206 Character GetVariationSelectorByScript(const TextAbstraction::Script& script)
208 Character character = 0u;
209 if(TextAbstraction::EMOJI_COLOR == script)
211 character = TextAbstraction::CHAR_VARIATION_SELECTOR_16;
213 else if(TextAbstraction::EMOJI_TEXT == script)
215 character = TextAbstraction::CHAR_VARIATION_SELECTOR_15;
223 } // namespace Toolkit