Merge branch 'devel/master(1.1.1)' into tizen
[platform/core/uifw/dali-adaptor.git] / text / dali / devel-api / text-abstraction / script.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/devel-api/text-abstraction/script.h>
20
21 namespace Dali
22 {
23
24 namespace TextAbstraction
25 {
26
27 namespace
28 {
29 const unsigned int WHITE_SPACE_THRESHOLD  = 0x21; ///< All characters below 0x21 are considered white spaces.
30 const unsigned int CHAR_LF   = 0x000A; ///< NL Line feed, new line.
31 const unsigned int CHAR_VT   = 0x000B; ///< Vertical tab.
32 const unsigned int CHAR_FF   = 0x000C; ///< NP Form feed, new page.
33 const unsigned int CHAR_CR   = 0x000D; ///< Carriage return, new line.
34 const unsigned int CHAR_NEL  = 0x0085; ///< Next line.
35 const unsigned int CHAR_LS   = 0x2028; ///< Line separator.
36 const unsigned int CHAR_PS   = 0x2029; ///< Paragraph separator
37
38 const unsigned int CHAR_ZWS  = 0x200B; ///< Zero width space.
39 const unsigned int CHAR_ZWNJ = 0x200C; ///< Zero width non joiner.
40 const unsigned int CHAR_ZWJ  = 0x200D; ///< Zero width joiner.
41 const unsigned int CHAR_LTRM = 0x200E; ///< Left to Right Mark.
42 const unsigned int CHAR_RTLM = 0x200F; ///< Right to Left Mark.
43 const unsigned int CHAR_TS   = 0x2009; ///< Thin Space.
44 } // namespace
45
46 bool IsRightToLeftScript( Script script )
47 {
48   return ( ( ARABIC == script ) ||
49            ( HEBREW == script ) );
50 }
51
52 Script GetCharacterScript( Character character )
53 {
54   // Latin script:
55   // 0x0000 - 0x007f C0 Controls and Basic Latin
56   // 0x0080 - 0x00ff C1 Controls and Latin-1 Supplement
57   // 0x0100 - 0x017f Latin Extended-A
58   // 0x0180 - 0x024f Latin Extended-B
59   // 0x0250 - 0x02af IPA Extensions
60   // 0x02b0 - 0x02ff Spacing Modifier Letters
61   // 0x1d00 - 0x1d7f Phonetic Extensions
62   // 0x1d80 - 0x1dbf Phonetic Extensions Supplement
63   // 0x1e00 - 0x1eff Latin Extended Additional
64   // 0x2070 - 0x209f Superscripts and Subscripts
65   // 0x2100 - 0x214f Letterlike symbols
66   // 0x2150 - 0x218f Number Forms
67   // 0x2c60 - 0x2c7f Latin Extended-C
68   // 0xa720 - 0xa7ff Latin Extended-D
69   // 0xab30 - 0xab6f Latin Extended-E
70   // 0xfb00 - 0xfb06 Latin Alphabetic Presentation Forms
71   // 0xff00 - 0xffef Halfwidth and Fullwidth Forms
72
73   // Brahmic scripts:
74   // 0x0900 - 0x097f Devanagari
75   // 0x0980 - 0x09ff Bengali
76   // 0x0a00 - 0x0a7f Gurmukhi
77   // 0x0a80 - 0x0aff Gujarati
78   // 0x0b00 - 0x0b7f Oriya
79   // 0x0b80 - 0x0bff Tamil
80   // 0x0c00 - 0x0c7f Telugu
81   // 0x0c80 - 0x0cff Kannada
82   // 0x0d00 - 0x0d7f Malayalam
83
84   // Sinhala script.
85   // 0x0d80 - 0x0dff Sinhala
86
87   // Arabic script.
88   // 0x0600 - 0x06ff Arabic
89   // 0x0750 - 0x077f Arabic Supplement
90   // 0x08A0 - 0x08ff Arabic Extended-A
91   // 0xfb50 - 0xfdff Arabic Presentation Forms-A
92   // 0xfe70 - 0xfeff Arabic Presentation Forms-B
93   // 0x1ee00 - 0x1eeff Arabic Mathematical Alphabetic Symbols
94
95   // CJK (Chinese, Japanese and Korean) and Vietnamese script.
96   // 0x2e80 - 0x2eff CJK Radicals Supplement
97   // 0x2f00 - 0x2fdf Kangxi Radicals
98   // 0x3000 - 0x303f CJK Symbols and Punctuation
99   // 0x3200 - 0x32ff Enclosed CJK Letters and Months
100   // 0x3400 - 0x4dbf CJK Unified Ideographs Extension A
101   // 0x4e00 - 0x62ff CJK Unified Ideographs
102   // 0x6300 - 0x77ff CJK Unified Ideographs
103   // 0x7800 - 0x8cff CJK Unified Ideographs
104   // 0x8d00 - 0x9fff CJK Unified Ideographs
105   // 0x20000 - 0x215ff CJK Unified Ideographs Extension B
106   // 0x21600 - 0x230ff CJK Unified Ideographs Extension B
107   // 0x23100 - 0x245ff CJK Unified Ideographs Extension B
108   // 0x24600 - 0x260ff CJK Unified Ideographs Extension B
109   // 0x26100 - 0x275ff CJK Unified Ideographs Extension B
110   // 0x27600 - 0x290ff CJK Unified Ideographs Extension B
111   // 0x29100 - 0x2a6df CJK Unified Ideographs Extension B
112   // 0x2a700 - 0x2b73f CJK Unified Ideographs Extension C
113   // 0x2b740 - 0x2b81f CJK Unified Ideographs Extension D
114
115   // Japanese scripts.
116   // 0x3040 - 0x309f Hiragana
117   // 0x30a0 - 0x30ff Katakana
118
119   // Hangul script
120   // 0x1100 - 0x11ff Hangul jamo
121   // 0x3130 - 0x318f Hangul Compatibility Jamo
122   // 0xa960 - 0xa97f Hangul Jamo Extended-A
123   // 0xac00 - 0xd7af Hangul Syllables
124   // 0xd7b0 - 0xd7ff Hangul Jamo Extended-B
125
126   // Bopomofo script
127   // 0x3100 - 0x312f Bopomofo
128   // 0x31a0 - 0x31bf Bopomofo Extended
129
130   // Khmer script
131   // 0x1780 - 0x17ff Khmer
132   // 0x19e0 - 0x19ff Khmer Symbols
133
134   // Lao script
135   // 0x0e80 - 0x0eff Lao
136
137   // Thai script
138   // 0x0e00 - 0x0e7f Thai
139
140   // Burmese script
141   // 0x1000 - 0x109f Myanmar
142
143   // Hebrew script
144   // 0x0591 - 0x05f4 Hebrew
145   // 0xfb1d - 0xfb4f Hebrew subset of Alphabetic Presentation Forms
146
147   // Cyrillic script
148   // 0x0400 - 0x04ff Cyrillic
149   // 0x0500 - 0x052f Cyrillic suplement
150   // 0x2de0 - 0x2dff Cyrillic Extended-A
151   // 0xa640 - 0xa69f Cyrillic Extended-B
152
153   // Georgian script
154   // 0x10a0 - 0x10ff Georgian
155   // 0x2d00 - 0x2d2f Georgian suplement
156
157   // Greek script
158   // 0x0370 - 0x03ff Greek & Coptic
159   // 0x1f00 - 0x1fff Greek Extended
160
161   // Armenian script
162   // 0x0530 - 0x058f Armenian
163   // 0xfb13 - 0xfb17 Armenian subset of Alphabetic prefentation forms
164
165   // The Emoji which map to standardized Unicode characters
166   // 1. Emoticons ( 1F601 - 1F64F )
167   // 2. Dingbats ( 2702 - 27B0 )
168   // 3. Transport and map symbols ( 1F680 - 1F6C0 )
169   // 4. Enclosed characters ( 24C2 - 1F251 )
170   // 5. Uncategorized :-S
171   // 6. Additional Emoticons ( 1F600 - 1F636 )
172   // 6b. Additional transport and map symbols ( 1F681 - 1F6C5 )
173   // 6c. Other additional symbols ( 1F30D - 1F567 )
174
175   if( IsCommonScript( character ) )
176   {
177     return COMMON;
178   }
179
180   if( character <= 0x0cff )
181   {
182     if( character <= 0x09ff )
183     {
184       if( character <= 0x077f )
185       {
186         if( character == 0x00A9 )
187         {
188           return EMOJI; // 5. Uncategorized: copyright sign
189         }
190         if( character == 0x00AE )
191         {
192           return EMOJI; // 5. Uncategorized: registered sign
193         }
194         if( character <= 0x02ff )
195         {
196           return LATIN;
197         }
198         if( ( 0x0370 <= character ) && ( character <= 0x03ff ) )
199         {
200           return GREEK;
201         }
202         if( ( 0x0400 <= character ) && ( character <= 0x04ff ) )
203         {
204           return CYRILLIC;
205         }
206         if( ( 0x0500 <= character ) && ( character <= 0x052f ) )
207         {
208           return CYRILLIC;
209         }
210         if( ( 0x0530 <= character ) && ( character <= 0x058f ) )
211         {
212           return ARMENIAN;
213         }
214         if( ( 0x0591 <= character ) && ( character <= 0x05f4 ) )
215         {
216           return HEBREW;
217         }
218         if( ( 0x0600 <= character ) && ( character <= 0x06ff ) )
219         {
220           return ARABIC;
221         }
222         if( ( 0x0750 <= character ) && ( character <= 0x077f ) )
223         {
224           return ARABIC;
225         }
226       }
227       else // > 0x077f
228       {
229         if( ( 0x08A0 <= character ) && ( character <= 0x08ff ) )
230         {
231           return ARABIC;
232         }
233         if( ( 0x0900 <= character ) && ( character <= 0x097f ) )
234         {
235           return DEVANAGARI;
236         }
237         if( ( 0x0980 <= character ) && ( character <= 0x09ff ) )
238         {
239           return BENGALI;
240         }
241       }
242     }
243     else // > 0x09ff
244     {
245       if( character <= 0x0b7f )
246       {
247         if( ( 0x0a00 <= character ) && ( character <= 0x0a7f ) )
248         {
249           return GURMUKHI;
250         }
251         if( ( 0x0a80 <= character ) && ( character <= 0x0aff ) )
252         {
253           return GUJARATI;
254         }
255         if( ( 0x0b00 <= character ) && ( character <= 0x0b7f ) )
256         {
257           return ORIYA;
258         }
259       }
260       else // > 0x0b7f
261       {
262         if( ( 0x0b80 <= character ) && ( character <= 0x0bff ) )
263         {
264           return TAMIL;
265         }
266         if( ( 0x0c00 <= character ) && ( character <= 0x0c7f ) )
267         {
268           return TELUGU;
269         }
270         if( ( 0x0c80 <= character ) && ( character <= 0x0cff ) )
271         {
272           return KANNADA;
273         }
274       }
275     }
276   }
277   else // > 0x0cff
278   {
279     if( character <= 0x2c7f )
280     {
281       if( character <= 0x1eff )
282       {
283         if( ( 0x0d00 <= character ) && ( character <= 0x0d7f ) )
284         {
285           return MALAYALAM;
286         }
287         if( ( 0x0d80 <= character ) && ( character <= 0x0dff ) )
288         {
289           return SINHALA;
290         }
291         if( ( 0x0e00 <= character ) && ( character <= 0x0e7f ) )
292         {
293           return THAI;
294         }
295         if( ( 0x0e80 <= character ) && ( character <= 0x0eff ) )
296         {
297           return LAO;
298         }
299         if( ( 0x1000 <= character ) && ( character <= 0x109f ) )
300         {
301           return BURMESE;
302         }
303         if( ( 0x10a0 <= character ) && ( character <= 0x10ff ) )
304         {
305           return GEORGIAN;
306         }
307         if( ( 0x1100 <= character ) && ( character <= 0x11ff ) )
308         {
309           return HANGUL;
310         }
311         if( ( 0x1780 <= character ) && ( character <= 0x17ff ) )
312         {
313           return KHMER;
314         }
315         if( ( 0x19e0 <= character ) && ( character <= 0x19ff ) )
316         {
317           return KHMER;
318         }
319         if( ( 0x1d00 <= character ) && ( character <= 0x1eff ) )
320         {
321           return LATIN;
322         }
323       }
324       else // > 0x1eff
325       {
326         if( ( 0x1f00 <= character ) && ( character <= 0x1fff ) )
327         {
328           return GREEK;
329         }
330         if( character == 0x203c )
331         {
332           return EMOJI; // 5. Uncategorized: double exclamation mark
333         }
334         if( character == 0x2049 )
335         {
336           return EMOJI; // 5. Uncategorized: exclamation question mark
337         }
338         if( ( 0x2070 <= character ) && ( character <= 0x209f ) )
339         {
340           return LATIN;
341         }
342         if( character == 0x20e3 )
343         {
344           return EMOJI; // 5. Uncategorized: combining enclosing keycap
345         }
346         if( character == 0x2122 )
347         {
348           return EMOJI; // 5. Uncategorized: trade mark sign
349         }
350         if( character == 0x2139 )
351         {
352           return EMOJI; // 5. Uncategorized: information source
353         }
354         if( ( 0x2100 <= character ) && ( character <= 0x218f ) )
355         {
356           return LATIN;
357         }
358         // U+2194 5. Uncategorized: left right arrow
359         // U+2B55 5. Uncategorized: heavy large circle
360         if( ( 0x2194 <= character ) && ( character <= 0x2B55 ) )
361         {
362           return EMOJI;
363         }
364         if( ( 0x2c60 <= character ) && ( character <= 0x2c7f ) )
365         {
366           return LATIN;
367         }
368       }
369     }
370     else // > 0x2c7f
371     {
372       if( character <= 0xfdff )
373       {
374         if( ( 0x2d00 <= character ) && ( character <= 0x2d2f ) )
375         {
376           return GEORGIAN;
377         }
378         if( ( 0x2de0 <= character ) && ( character <= 0x2dff ) )
379         {
380           return CYRILLIC;
381         }
382         if( ( 0x2e80 <= character ) && ( character <= 0x2eff ) )
383         {
384           return CJK;
385         }
386         if( ( 0x2f00 <= character ) && ( character <= 0x2fdf ) )
387         {
388           return CJK;
389         }
390         if( ( 0x3000 <= character ) && ( character <= 0x303f ) )
391         {
392           return CJK;
393         }
394         if( ( 0x3040 <= character ) && ( character <= 0x309f ) )
395         {
396           return HIRAGANA;
397         }
398         if( ( 0x30a0 <= character ) && ( character <= 0x30ff ) )
399         {
400           return KATAKANA;
401         }
402         if( ( 0x3100 <= character ) && ( character <= 0x312f ) )
403         {
404           return BOPOMOFO;
405         }
406         if( ( 0x3130 <= character ) && ( character <= 0x318f ) )
407         {
408           return HANGUL;
409         }
410         if( ( 0x31a0 <= character ) && ( character <= 0x31bf ) )
411         {
412           return BOPOMOFO;
413         }
414         if( ( 0x3200 <= character ) && ( character <= 0x32ff ) )
415         {
416           return CJK;
417         }
418         if( ( 0x3400 <= character ) && ( character <= 0x4dbf ) )
419         {
420           return CJK;
421         }
422         if( ( 0x4e00 <= character ) && ( character <= 0x62ff ) )
423         {
424           return CJK;
425         }
426         if( ( 0x6300 <= character ) && ( character <= 0x77ff ) )
427         {
428           return CJK;
429         }
430         if( ( 0x7800 <= character ) && ( character <= 0x8cff ) )
431         {
432           return CJK;
433         }
434         if( ( 0x8d00 <= character ) && ( character <= 0x9fff ) )
435         {
436           return CJK;
437         }
438         if( ( 0xa640 <= character ) && ( character <= 0xa69f ) )
439         {
440           return CYRILLIC;
441         }
442         if( ( 0xa720 <= character ) && ( character <= 0xa7ff ) )
443         {
444           return LATIN;
445         }
446         if( ( 0xa960 <= character ) && ( character <= 0xa97f ) )
447         {
448           return HANGUL;
449         }
450         if( ( 0xab30 <= character ) && ( character <= 0xab6f ) )
451         {
452           return LATIN;
453         }
454         if( ( 0xac00 <= character ) && ( character <= 0xd7af ) )
455         {
456           return HANGUL;
457         }
458         if( ( 0xd7b0 <= character ) && ( character <= 0xd7ff ) )
459         {
460           return HANGUL;
461         }
462         if( ( 0xfb00 <= character ) && ( character <= 0xfb06 ) )
463         {
464           return LATIN;
465         }
466         if( ( 0xfb13 <= character ) && ( character <= 0xfb17 ) )
467         {
468           return ARMENIAN;
469         }
470         if( ( 0xfb1d <= character ) && ( character <= 0xfb4f ) )
471         {
472           return HEBREW;
473         }
474         if( ( 0xfb50 <= character ) && ( character <= 0xfdff ) )
475         {
476           return ARABIC;
477         }
478       }
479       else // > 0xfdff
480       {
481         if( ( 0xfe70 <= character ) && ( character <= 0xfeff ) )
482         {
483           return ARABIC;
484         }
485         if( ( 0xff00 <= character ) && ( character <= 0xffef ) )
486         {
487           return LATIN;
488         }
489         if( ( 0x1ee00 <= character ) && ( character <= 0x1eeff ) )
490         {
491           return ARABIC;
492         }
493         // U+1f170 4. Enclosed characters: negative squared latin capital letter A
494         // U+1f6c5 6b. Additional transport and map symbols
495         if( ( 0x1f170 <= character ) && ( character <= 0x1f6c5 ) )
496         {
497           return EMOJI;
498         }
499         if( ( 0x20000 <= character ) && ( character <= 0x215ff ) )
500         {
501           return CJK;
502         }
503         if( ( 0x21600 <= character ) && ( character <= 0x230ff ) )
504         {
505           return CJK;
506         }
507         if( ( 0x23100 <= character ) && ( character <= 0x245ff ) )
508         {
509           return CJK;
510         }
511         if( ( 0x24600 <= character ) && ( character <= 0x260ff ) )
512         {
513           return CJK;
514         }
515         if( ( 0x26100 <= character ) && ( character <= 0x275ff ) )
516         {
517           return CJK;
518         }
519         if( ( 0x27600 <= character ) && ( character <= 0x290ff ) )
520         {
521           return CJK;
522         }
523         if( ( 0x29100 <= character ) && ( character <= 0x2a6df ) )
524         {
525           return CJK;
526         }
527         if( ( 0x2a700 <= character ) && ( character <= 0x2b73f ) )
528         {
529           return CJK;
530         }
531         if( ( 0x2b740 <= character ) && ( character <= 0x2b81f ) )
532         {
533           return CJK;
534         }
535       }
536     }
537   }
538
539   return UNKNOWN;
540 }
541
542 bool IsWhiteSpace( Character character )
543 {
544   return character < WHITE_SPACE_THRESHOLD;
545 }
546
547 bool IsNewParagraph( Character character )
548 {
549   return ( ( CHAR_LF == character )  ||
550            ( CHAR_VT == character )  ||
551            ( CHAR_FF == character )  ||
552            ( CHAR_CR == character )  ||
553            ( CHAR_NEL == character ) ||
554            ( CHAR_LS == character )  ||
555            ( CHAR_PS == character ) );
556 }
557
558 bool IsZeroWidthNonJoiner( Character character )
559 {
560   return CHAR_ZWNJ == character;
561 }
562
563 bool IsZeroWidthJoiner( Character character )
564 {
565   return CHAR_ZWJ == character;
566 }
567
568 bool IsZeroWidthSpace( Character character )
569 {
570   return CHAR_ZWS == character;
571 }
572
573 bool IsLeftToRightMark( Character character )
574 {
575   return CHAR_LTRM == character;
576 }
577
578 bool IsRightToLeftMark( Character character )
579 {
580   return CHAR_RTLM == character;
581 }
582
583 bool IsThinSpace( Character character )
584 {
585   return CHAR_TS == character;
586 }
587
588 bool IsCommonScript( Character character )
589 {
590   return ( IsWhiteSpace( character )         ||
591            IsZeroWidthNonJoiner( character ) ||
592            IsZeroWidthJoiner( character )    ||
593            IsZeroWidthSpace( character )     ||
594            IsLeftToRightMark( character )    ||
595            IsRightToLeftMark( character )    ||
596            IsThinSpace( character )          ||
597            IsNewParagraph( character ) );
598 }
599
600 bool HasLigatureMustBreak( Script script )
601 {
602   return ( ( LATIN == script ) ||
603            ( ARABIC == script ) );
604 }
605
606 } // namespace TextAbstraction
607
608 } // namespace Dali