(Text Controller) Moved ShowPlaceholder method into PlaceholderHandler
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / character-set-conversion.cpp
1 /*
2  * Copyright (c) 2015 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 // FILE HEADER
19 #include <dali-toolkit/internal/text/character-set-conversion.h>
20
21 namespace Dali
22 {
23
24 namespace Toolkit
25 {
26
27 namespace Text
28 {
29
30 namespace
31 {
32   const static uint8_t U1 = 1u;
33   const static uint8_t U2 = 2u;
34   const static uint8_t U3 = 3u;
35   const static uint8_t U4 = 4u;
36   const static uint8_t U5 = 5u;
37   const static uint8_t U6 = 6u;
38   const static uint8_t U0 = 0u;
39   const static uint8_t UTF8_LENGTH[256] = {
40     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
41     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
42     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
43     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
44     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
45     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
46     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
47     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
48     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, // lead byte = 0xxx xxxx (U+0000 - U+007F + some extended ascii characters)
49     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
50     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
51     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
52     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
53     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
54     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
55     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
56     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
57     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
58     U1, U1, U1, U1, U1, U1, U1, U1, U1, U1, //
59     U1, U1,                                 //
60
61     U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, //
62     U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, // lead byte = 110x xxxx (U+0080 - U+07FF)
63     U2, U2, U2, U2, U2, U2, U2, U2, U2, U2, //
64     U2, U2,                                 //
65
66     U3, U3, U3, U3, U3, U3, U3, U3, U3, U3, // lead byte = 1110 xxxx (U+0800 - U+FFFF)
67     U3, U3, U3, U3, U3, U3,                 //
68
69     U4, U4, U4, U4, U4, U4, U4, U4,         // lead byte = 1111 0xxx (U+10000 - U+1FFFFF)
70
71     U5, U5, U5, U5,                         // lead byte = 1111 10xx (U+200000 - U+3FFFFFF)
72
73     U6, U6,                                 // lead byte = 1111 110x (U+4000000 - U+7FFFFFFF)
74
75     U0, U0,                                 // Non valid.
76   };
77
78   const uint8_t CR = 0xd;
79   const uint8_t LF = 0xa;
80 } // namespace
81
82 uint8_t GetUtf8Length( uint8_t utf8LeadByte )
83 {
84   return UTF8_LENGTH[utf8LeadByte];
85 }
86
87 uint32_t GetNumberOfUtf8Characters( const uint8_t* const utf8, uint32_t length )
88 {
89   uint32_t numberOfCharacters = 0u;
90
91   const uint8_t* begin = utf8;
92   const uint8_t* end = utf8 + length;
93
94   for( ; begin < end ; begin += UTF8_LENGTH[*begin], ++numberOfCharacters );
95
96   return numberOfCharacters;
97 }
98
99 uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters )
100 {
101   uint32_t numberOfBytes = 0u;
102
103   const uint32_t* begin = utf32;
104   const uint32_t* end = utf32 + numberOfCharacters;
105
106   for( ; begin < end; ++begin )
107   {
108     const uint32_t code = *begin;
109
110     if( code < 0x80u )
111     {
112       ++numberOfBytes;
113     }
114     else if( code < 0x800u )
115     {
116       numberOfBytes += U2;
117     }
118     else if( code < 0x10000u )
119     {
120       numberOfBytes += U3;
121     }
122     else if( code < 0x200000u )
123     {
124       numberOfBytes += U4;
125     }
126     else if( code < 0x4000000u )
127     {
128       numberOfBytes += U5;
129     }
130     else if( code < 0x80000000u )
131     {
132       numberOfBytes += U6;
133     }
134   }
135
136   return numberOfBytes;
137 }
138
139 uint32_t Utf8ToUtf32( const uint8_t* const utf8, uint32_t length, uint32_t* utf32 )
140 {
141   uint32_t numberOfCharacters = 0u;
142
143   const uint8_t* begin = utf8;
144   const uint8_t* end = utf8 + length;
145
146   for( ; begin < end ; ++numberOfCharacters )
147   {
148     const uint8_t leadByte = *begin;
149
150     switch( UTF8_LENGTH[leadByte] )
151     {
152       case U1:
153       {
154         if( CR == leadByte )
155         {
156           // Replace CR+LF or CR by LF
157           *utf32++ = LF;
158
159           // Look ahead if the next one is a LF.
160           ++begin;
161           if( begin < end )
162           {
163             if( LF == *begin )
164             {
165               ++begin;
166             }
167           }
168         }
169         else
170         {
171           *utf32++ = leadByte;
172           begin++;
173         }
174         break;
175       }
176
177       case U2:
178       {
179         uint32_t& code = *utf32++;
180         code = leadByte & 0x1fu;
181         begin++;
182         code <<= 6u;
183         code |= *begin++ & 0x3fu;
184         break;
185       }
186
187       case U3:
188       {
189         uint32_t& code = *utf32++;
190         code = leadByte & 0x0fu;
191         begin++;
192         code <<= 6u;
193         code |= *begin++ & 0x3fu;
194         code <<= 6u;
195         code |= *begin++ & 0x3fu;
196         break;
197       }
198
199       case U4:
200       {
201         uint32_t& code = *utf32++;
202         code = leadByte & 0x07u;
203         begin++;
204         code <<= 6u;
205         code |= *begin++ & 0x3fu;
206         code <<= 6u;
207         code |= *begin++ & 0x3fu;
208         code <<= 6u;
209         code |= *begin++ & 0x3fu;
210         break;
211       }
212
213       case U5:
214       {
215         uint32_t& code = *utf32++;
216         code = leadByte & 0x03u;
217         begin++;
218         code <<= 6u;
219         code |= *begin++ & 0x3fu;
220         code <<= 6u;
221         code |= *begin++ & 0x3fu;
222         code <<= 6u;
223         code |= *begin++ & 0x3fu;
224         code <<= 6u;
225         code |= *begin++ & 0x3fu;
226         break;
227       }
228
229       case U6:
230       {
231         uint32_t& code = *utf32++;
232         code = leadByte & 0x01u;
233         begin++;
234         code <<= 6u;
235         code |= *begin++ & 0x3fu;
236         code <<= 6u;
237         code |= *begin++ & 0x3fu;
238         code <<= 6u;
239         code |= *begin++ & 0x3fu;
240         code <<= 6u;
241         code |= *begin++ & 0x3fu;
242         code <<= 6u;
243         code |= *begin++ & 0x3fu;
244         break;
245       }
246
247       case U0:    // Invalid case
248       {
249         begin++;
250         *utf32++ = 0x20;    // Use white space
251         break;
252       }
253     }
254   }
255
256   return numberOfCharacters;
257 }
258
259 uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 )
260 {
261   const uint32_t* begin = utf32;
262   const uint32_t* end = utf32 + numberOfCharacters;
263
264   uint8_t* utf8Begin = utf8;
265
266   for( ; begin < end; ++begin )
267   {
268     const uint32_t code = *begin;
269
270     if( code < 0x80u )
271     {
272       *utf8++ = code;
273     }
274     else if( code < 0x800u )
275     {
276       *utf8++ = static_cast<uint8_t>(   code >> 6u )           | 0xc0u; // lead byte for 2 byte sequence
277       *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
278     }
279     else if( code < 0x10000u )
280     {
281       *utf8++ = static_cast<uint8_t>(   code >> 12u )          | 0xe0u; // lead byte for 3 byte sequence
282       *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
283       *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
284     }
285     else if( code < 0x200000u )
286     {
287       *utf8++ = static_cast<uint8_t>(   code >> 18u )          | 0xf0u; // lead byte for 4 byte sequence
288       *utf8++ = static_cast<uint8_t>( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte
289       *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
290       *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
291     }
292     else if( code < 0x4000000u )
293     {
294       *utf8++ = static_cast<uint8_t>(   code >> 24u )          | 0xf8u; // lead byte for 5 byte sequence
295       *utf8++ = static_cast<uint8_t>( ( code >> 18u ) & 0x3f ) | 0x80u; // continuation byte
296       *utf8++ = static_cast<uint8_t>( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte
297       *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
298       *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
299     }
300     else if( code < 0x80000000u )
301     {
302       *utf8++ = static_cast<uint8_t>(   code >> 30u )          | 0xfcu; // lead byte for 6 byte sequence
303       *utf8++ = static_cast<uint8_t>( ( code >> 24u ) & 0x3f ) | 0x80u; // continuation byte
304       *utf8++ = static_cast<uint8_t>( ( code >> 18u ) & 0x3f ) | 0x80u; // continuation byte
305       *utf8++ = static_cast<uint8_t>( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte
306       *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
307       *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
308     }
309   }
310
311   return utf8 - utf8Begin;
312 }
313
314 void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 )
315 {
316   utf8.clear();
317
318   uint32_t numberOfBytes = GetNumberOfUtf8Bytes( &utf32[0], numberOfCharacters );
319   utf8.resize( numberOfBytes );
320
321   // This is a bit horrible but std::string returns a (signed) char*
322   Utf32ToUtf8( utf32, numberOfCharacters, reinterpret_cast<uint8_t*>(&utf8[0]) );
323 }
324
325 } // namespace Text
326
327 } // namespace Toolkit
328
329 } // namespace Dali