• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 THIRD_PARTY_SKIA_HYPHENATOR_H
17 #define THIRD_PARTY_SKIA_HYPHENATOR_H
18 
19 #ifdef ENABLE_TEXT_ENHANCE
20 #include <atomic>
21 #include <cctype>
22 #include <cstring>
23 #include <memory>
24 #include <mutex>
25 #include <shared_mutex>
26 #include <ucase.h>
27 #include <map>
28 #include <vector>
29 
30 #include "include/core/SkString.h"
31 #include "include/HyphenTrie.h"
32 
33 namespace skia {
34 namespace textlayout {
35 constexpr size_t HYPHEN_WORD_SHIFT = 4;
36 constexpr size_t HYPHEN_BASE_CODE_SHIFT = 2;
37 constexpr size_t HYPHEN_SHIFT_BITS_14 = 14;
38 constexpr size_t HYPHEN_SHIFT_BITS_30 = 30;
39 
40 enum class PathType : uint8_t {
41     PATTERN = 0,
42     LINEAR = 1,
43     PAIRS = 2,
44     DIRECT = 3
45 };
46 
47 struct Pattern {
48     uint8_t patterns[8]; // dynamic
49 };
50 
51 struct ArrayOf16bits {
52     uint16_t count;
53     uint16_t codes[3]; // dynamic
54 };
55 
56 struct HyphenatorHeader {
57     uint8_t magic1{0};
58     uint8_t magic2{0};
59     uint8_t minCp{0};
60     uint8_t maxCp{0};
61     uint32_t toc{0};
62     uint32_t mappings{0};
63     uint32_t version{0};
64 
65     uint16_t codeOffset(uint16_t code, const ArrayOf16bits* maps = nullptr) const
66     {
67         // need still reconsider what we want to do with a nodes in the middle of graph
68         if (maps != nullptr && (code < minCp || code > maxCp)) {
69             // we could assert that count is even
70             for (size_t i = maps->count; i != 0;) {
71                 i -= HYPHEN_BASE_CODE_SHIFT;
72                 if (maps->codes[i] == code) {
73                     auto offset = maps->codes[i + 1];
74                     return (maxCp - minCp) * HYPHEN_BASE_CODE_SHIFT + (offset - maxCp) * HYPHEN_BASE_CODE_SHIFT + 1;
75                 }
76             }
77             return maxCount(maps);
78         }
79         if (maps) {
80             // + 1 because previous end is before next start
81             // 2x because every second value to beginning addres
82             return (code - minCp) * HYPHEN_BASE_CODE_SHIFT + 1;
83         } else {
84             if (code < minCp || code > maxCp) {
85                 return maxCp + 1;
86             }
87             return (code - minCp);
88         }
89     }
90 
toLowerHyphenatorHeader91     inline static void toLower(uint16_t& code)
92     {
93         if (code == '.') {
94             code = '`';
95         } else if (code == '\'') {
96             code = '^';
97         } else if (code == '-') {
98             code = '_';
99         } else {
100             // Open Harmony seems to have this even before C++20
101             code = ucase_tolower(code);
102         }
103     }
104 
maxCountHyphenatorHeader105     inline uint16_t maxCount(const ArrayOf16bits* maps) const
106     {
107         // need to write this in binary provider !!
108         return (maxCp - minCp) * HYPHEN_BASE_CODE_SHIFT + maps->count;
109     }
110 };
111 
112 class Hyphenator {
113 public:
getInstance()114     static Hyphenator& getInstance()
115     {
116         static Hyphenator instance;
117         std::call_once(initFlag, []() { instance.initTrieTree(); });
118         return instance;
119     }
120     const std::vector<uint8_t>& getHyphenatorData(const std::string& locale);
121     std::vector<uint8_t> findBreakPositions(const SkString& locale, const SkString& text,
122                                             size_t startPos, size_t endPos);
123 
124 private:
125     static std::once_flag initFlag;
126     Hyphenator() = default;
127     ~Hyphenator() = default;
128     Hyphenator(const Hyphenator&) = delete;
129     Hyphenator& operator=(const Hyphenator&) = delete;
130 
131     void initTrieTree();
132     const std::vector<uint8_t>& findHyphenatorData(const std::string& langCode);
133     const std::vector<uint8_t>& loadPatternFile(const std::string& langCode);
134 
135     mutable std::shared_mutex mutex_;
136     std::map<std::string, std::vector<uint8_t>> fHyphenMap;
137     HyphenTrie fTrieTree;
138     const std::vector<uint8_t> fEmptyResult;
139 };
140 } // namespace textlayout
141 } // namespace skia
142 #endif // ENABLE_TEXT_ENHANCE
143 #endif // THIRD_PARTY_SKIA_HYPHENATOR_H
144