[AT-SPI] Rework intercepting key events
[platform/core/uifw/dali-adaptor.git] / dali / internal / text / text-abstraction / hyphenation-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
18 // CLASS  HEADER
19 #include <dali/internal/text/text-abstraction/hyphenation-impl.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 #include <dali/devel-api/common/singleton-service.h>
25
26 // EXTERNAL INCLUDES
27 #ifdef HYPHEN_LIBRARY_AVAILABLE
28 #include <hyphen.h>
29 #else
30 #define HyphenDict void
31 #endif
32
33 #ifndef HYPHEN_DIC
34 #define HYPHEN_DIC "abc"
35 #endif
36
37 namespace
38 {
39 #if defined(DEBUG_ENABLED)
40 Dali::Integration::Log::Filter* gLogFilter = Dali::Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_HYPHENATION");
41 #endif
42
43 } // namespace
44
45 namespace Dali
46 {
47 namespace TextAbstraction
48 {
49 namespace Internal
50 {
51 const char* const  DEFAULT_LANGUAGE        = "en_US";
52 const unsigned int DEFAULT_LANGUAGE_LENGTH = 5u;
53
54 struct Hyphenation::HyphenDictionary
55 {
56   HyphenDictionary(std::string lang, HyphenDict* dict)
57   {
58     mLanguage   = lang;
59     mDictionary = dict;
60   }
61
62   ~HyphenDictionary()
63   {
64   }
65
66   std::string mLanguage;
67   HyphenDict* mDictionary;
68 };
69
70 struct Hyphenation::Plugin
71 {
72   Plugin()
73   : mHyphenDictionary()
74   {
75   }
76
77   ~Plugin()
78   {
79 #ifdef HYPHEN_LIBRARY_AVAILABLE
80     for(auto&& it : mHyphenDictionary)
81     {
82       hnj_hyphen_free(it.mDictionary);
83     }
84 #endif
85   }
86
87   std::string GetPathForLanguage(const char* lang)
88   {
89     std::string path    = HYPHEN_DIC;
90     std::string filName = "/hyph_";
91     filName.append(lang);
92     filName.append(".dic");
93     path.append(filName);
94
95     return path; // must be ..../hyph_en_US.dic
96   }
97
98   HyphenDict* LoadDictionary(const char* language)
99   {
100 #ifdef HYPHEN_LIBRARY_AVAILABLE
101     const char* lang = (language ? language : DEFAULT_LANGUAGE);
102
103     for(auto&& it : mHyphenDictionary)
104     {
105       if(!it.mLanguage.compare(lang))
106       {
107         return it.mDictionary;
108       }
109     }
110
111     std::string path = GetPathForLanguage(lang);
112     HyphenDict* dict = hnj_hyphen_load(path.c_str());
113     if(!dict)
114     {
115       DALI_LOG_ERROR("Couldn't load hyphen dictionary:%s\n", lang);
116     }
117     else
118     {
119       mHyphenDictionary.push_back(HyphenDictionary(lang, dict));
120     }
121
122     return dict;
123 #else
124     return nullptr;
125 #endif
126   }
127
128   const char* GetDictionaryEncoding(const char* lang)
129   {
130 #ifdef HYPHEN_LIBRARY_AVAILABLE
131     HyphenDict* dict = LoadDictionary(lang);
132     if(!dict)
133     {
134       return nullptr;
135     }
136
137     return dict->cset;
138 #else
139     return "UTF_32";
140 #endif
141   }
142
143   Vector<bool> GetWordHyphens(const char* word,
144                               Length      wordLength,
145                               const char* lang)
146   {
147     Vector<bool> hyphensList;
148
149 #ifdef HYPHEN_LIBRARY_AVAILABLE
150     char*       hyphens = nullptr;
151     char**      rep     = nullptr;
152     int*        pos     = nullptr;
153     int*        cut     = nullptr;
154     HyphenDict* dict;
155
156     if((!word) || (wordLength < 1))
157     {
158       return hyphensList;
159     }
160
161     dict = LoadDictionary(lang);
162     if(!dict)
163     {
164       return hyphensList;
165     }
166
167     hyphens = (char*)malloc(wordLength + 5);
168     if(hyphens)
169     {
170       hnj_hyphen_hyphenate2(dict, (char*)(word), wordLength, hyphens, NULL, &rep, &pos, &cut);
171
172       hyphensList.PushBack(false);
173
174       for(Length i = 0; i < wordLength - 1; i++)
175       {
176         hyphensList.PushBack((bool)(hyphens[i + 1] & 1));
177       }
178
179       free(hyphens);
180     }
181 #endif
182
183     return hyphensList;
184   }
185
186   std::vector<HyphenDictionary> mHyphenDictionary;
187 };
188
189 Hyphenation::Hyphenation()
190 : mPlugin(nullptr)
191 {
192 }
193
194 Hyphenation::~Hyphenation()
195 {
196 }
197
198 TextAbstraction::Hyphenation Hyphenation::Get()
199 {
200   TextAbstraction::Hyphenation hyphenationHandle;
201
202   SingletonService service(SingletonService::Get());
203   if(service)
204   {
205     // Check whether the singleton is already created
206     Dali::BaseHandle handle = service.GetSingleton(typeid(TextAbstraction::Hyphenation));
207     if(handle)
208     {
209       // If so, downcast the handle
210       Hyphenation* impl = dynamic_cast<Internal::Hyphenation*>(handle.GetObjectPtr());
211       hyphenationHandle = TextAbstraction::Hyphenation(impl);
212     }
213     else // create and register the object
214     {
215       hyphenationHandle = TextAbstraction::Hyphenation(new Hyphenation);
216       service.Register(typeid(hyphenationHandle), hyphenationHandle);
217     }
218   }
219
220   return hyphenationHandle;
221 }
222
223 const char* Hyphenation::GetDictionaryEncoding(const char* lang)
224 {
225   CreatePlugin();
226
227   return mPlugin->GetDictionaryEncoding(lang);
228 }
229
230 Vector<bool> Hyphenation::GetWordHyphens(const char* word,
231                                          Length      wordLength,
232                                          const char* lang)
233 {
234   CreatePlugin();
235
236   return mPlugin->GetWordHyphens(word, wordLength, lang);
237 }
238
239 void Hyphenation::CreatePlugin()
240 {
241   if(!mPlugin)
242   {
243     mPlugin = std::make_unique<Plugin>();
244   }
245 }
246
247 } // namespace Internal
248
249 } // namespace TextAbstraction
250
251 } // namespace Dali