Merge "atspi: reduce DBus signal 'BoundsChanged'" into devel/master
[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
169     hnj_hyphen_hyphenate2(dict, (char*)(word), wordLength, hyphens, NULL, &rep, &pos, &cut);
170
171     hyphensList.PushBack(false);
172
173     for(Length i = 0; i < wordLength - 1; i++)
174     {
175       hyphensList.PushBack((bool)(hyphens[i + 1] & 1));
176     }
177
178     free(hyphens);
179 #endif
180
181     return hyphensList;
182   }
183
184   std::vector<HyphenDictionary> mHyphenDictionary;
185 };
186
187 Hyphenation::Hyphenation()
188 : mPlugin(nullptr)
189 {
190 }
191
192 Hyphenation::~Hyphenation()
193 {
194 }
195
196 TextAbstraction::Hyphenation Hyphenation::Get()
197 {
198   TextAbstraction::Hyphenation hyphenationHandle;
199
200   SingletonService service(SingletonService::Get());
201   if(service)
202   {
203     // Check whether the singleton is already created
204     Dali::BaseHandle handle = service.GetSingleton(typeid(TextAbstraction::Hyphenation));
205     if(handle)
206     {
207       // If so, downcast the handle
208       Hyphenation* impl = dynamic_cast<Internal::Hyphenation*>(handle.GetObjectPtr());
209       hyphenationHandle = TextAbstraction::Hyphenation(impl);
210     }
211     else // create and register the object
212     {
213       hyphenationHandle = TextAbstraction::Hyphenation(new Hyphenation);
214       service.Register(typeid(hyphenationHandle), hyphenationHandle);
215     }
216   }
217
218   return hyphenationHandle;
219 }
220
221 const char* Hyphenation::GetDictionaryEncoding(const char* lang)
222 {
223   CreatePlugin();
224
225   return mPlugin->GetDictionaryEncoding(lang);
226 }
227
228 Vector<bool> Hyphenation::GetWordHyphens(const char* word,
229                                          Length      wordLength,
230                                          const char* lang)
231 {
232   CreatePlugin();
233
234   return mPlugin->GetWordHyphens(word, wordLength, lang);
235 }
236
237 void Hyphenation::CreatePlugin()
238 {
239   if(!mPlugin)
240   {
241     mPlugin = std::make_unique<Plugin>();
242   }
243 }
244
245 } // namespace Internal
246
247 } // namespace TextAbstraction
248
249 } // namespace Dali