1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_TEXT_ACE_TEXT_EMOJI_PROCESSOR_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_TEXT_ACE_TEXT_EMOJI_PROCESSOR_H
18 
19 #include "base/utils/string_utils.h"
20 
21 namespace OHOS::Ace {
22 enum class EmojiRelation { NO_EMOJI, IN_EMOJI, BEFORE_EMOJI, AFTER_EMOJI, MIDDLE_EMOJI };
23 
24 struct TextEmojiSubStringRange {
25     int startIndex;
26     int endIndex;
27 };
28 
29 class TextEmojiProcessor {
30 public:
31     // static functions
32     /*
33      * Delete characters from the content string according to the startIndex and length.
34      * startIndex: The UTF-16 start index.
35      * For backward delete, it's the end index + 1, for forward delete, it's the start index.
36      * Example: content = "abcde";
37      * For backward at end, the startIndex is 5. For forward at start, the startIndex is 0.
38      * length: The number of characters to delete.
39      * Note: An emoji may have multiple bytes, but it's considered as ONE character.
40      * content: The content string to delete.
41      * isBackward: Whether the delete action is backward.
42      * return deleted UTF-16 bytes length.
43      * Why UTF-16? TextSelectController->GetCaretIndex() returns UTF-16 index.
44      */
45     static int32_t Delete(int32_t startIndex, int32_t length, std::string& content, bool isBackward);
46     static bool IsEmoji(uint32_t codePoint);
47     static bool IsEmojiModifierBase(uint32_t codePoint);
48     static bool IsVariationSelector(uint32_t codePoint);
49     static bool IsRegionalIndicatorSymbol(uint32_t codePoint);
50     static bool IsEmojiModifier(uint32_t codePoint);
51     static bool IsTagSpec(uint32_t codePoint);
52     static bool IsKeycapBase(uint32_t codePoint);
53     static bool IsIndexInEmoji(int32_t index, const std::string& content, int32_t& startIndex, int32_t& endIndex);
54     static EmojiRelation GetIndexRelationToEmoji(int32_t index,
55         const std::string& content, int32_t& startIndex, int32_t& endIndex);
56     static bool IsIndexBeforeOrInEmoji(int32_t index, const std::string& content);
57     static bool IsIndexAfterOrInEmoji(int32_t index, const std::string& content);
58     static bool IsIndexBeforeOrInEmoji(int32_t index, const std::string& content,
59         int32_t& startIndex, int32_t& endIndex);
60     static bool IsIndexAfterOrInEmoji(int32_t index, const std::string& content,
61         int32_t& startIndex, int32_t& endIndex);
62     static std::wstring SubWstring(int32_t index, int32_t length,
63         const std::wstring& content, bool includeHalf = false);
64     static TextEmojiSubStringRange CalSubWstringRange(int32_t index, int32_t length,
65         const std::wstring& content, bool includeHalf);
66     static int32_t GetCharacterNum(const std::string& content);
67     static std::string ConvertU8stringUnpairedSurrogates(const std::string& value);
68 
69 private:
70     static void OnBeginState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
71     static void OnRISState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
72     static void OnCRLFState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
73     static void OnZWJState(uint32_t codePoint, int& state, int& deleteCount, int& lastVSCount, bool isBackward);
74     static void OnVSState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
75     static void OnKeyCapState(uint32_t codePoint, int& state, int& deleteCount, int& lastVSCount, bool isBackward);
76     static void OnEMState(uint32_t codePoint, int& state, int& deleteCount, int& lastVSCount, bool isBackward);
77     static void OnEmojiState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
78     static void OnForwardSecondState(uint32_t codePoint, int& state, int& deleteCount);
79     static void OnTagQueueState(uint32_t codePoint, int& state, int& deleteCount, bool isBackward);
80     static bool BackwardDelete(std::u32string& u32Content);
81     static bool ForwardDelete(std::u32string& u32Content);
82     static bool HandleDeleteAction(std::u32string& u32Content, int32_t deleteCount, bool isBackward);
83     static int32_t GetEmojiLengthBackward(std::u32string& u32Content,
84         int32_t& startIndex, const std::u16string& u16Content);
85     static int32_t GetEmojiLengthForward(std::u32string& u32Content,
86         int32_t& startIndex, const std::u16string& u16Content);
87     static int32_t GetEmojiLengthU16Forward(std::u32string& u32Content,
88         int32_t& startIndex, const std::u16string& u16Content);
89     static int32_t GetEmojiLengthAtEnd(const std::u32string& u32Content, bool isCountNonEmoji);
90     static int32_t GetEmojiLengthAtFront(const std::u32string& u32Content, bool isCountNonEmoji);
91     static std::u16string U32ToU16string(const std::u32string& u32str);
92 };
93 
94 } // namespace OHOS::Ace
95 
96 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_TEXT_ACE_TEXT_EMOJI_PROCESSOR_H
97