1 /**
2  * @file lv_txt_ap.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include <stddef.h>
10 #include "lv_bidi.h"
11 #include "lv_txt.h"
12 #include "lv_txt_ap.h"
13 #include "../lv_draw/lv_draw.h"
14 
15 
16 /*********************
17  *      DEFINES
18  *********************/
19 
20 /**********************
21  *      TYPEDEFS
22  **********************/
23 
24 /**********************
25  *  STATIC PROTOTYPES
26  **********************/
27 #if LV_USE_ARABIC_PERSIAN_CHARS == 1
28 static uint32_t lv_ap_get_char_index(uint16_t c);
29 
30 /**********************
31  *  STATIC VARIABLES
32  **********************/
33 
34 const ap_chars_map_t ap_chars_map[] = {
35     /* {Key Offset, End, Beginning, Middle, Isolated, {conjunction}} */
36     {1, 0xFE84, -1, 0, -1,  {1, 0}},    // أ
37     {2, 0xFE86, -1, 0, -1,  {1, 0}},    // ؤ
38     {3, 0xFE88, -1, 0, -1,  {1, 0}},    // ﺇ
39     {4, 0xFE8A, 1, 2, -1,  {1, 0}},    // ئ
40     {5, 0xFE8E, -1, 0, -1,  {1, 0}},    // آ
41     {6, 0xFE90, 1, 2, -1,  {1, 1}},    // ب
42     {92, 0xFB57, 1, 2, -1,  {1, 1}},   // پ
43     {8, 0xFE96, 1, 2, -1,  {1, 1}},    // ت
44     {9, 0xFE9A, 1, 2, -1,  {1, 1}},    // ث
45     {10, 0xFE9E, 1, 2, -1,  {1, 1}},   // ج
46     {100, 0xFB7B, 1, 2, -1,  {1, 1}},  // چ
47     {11, 0xFEA2, 1, 2, -1,  {1, 1}},   // ح
48     {12, 0xFEA6, 1, 2, -1,  {1, 1}},   // خ
49     {13, 0xFEAA, -1, 0, -1,  {1, 0}},   // د
50     {14, 0xFEAC, -1, 0, -1,  {1, 0}},   // ذ
51     {15, 0xFEAE, -1, 0, -1,  {1, 0}},   // ر
52     {16, 0xFEB0, -1, 0, -1,  {1, 0}},   // ز
53     {118, 0xFB8B, -1, 0, -1,  {1, 0}},  // ژ
54     {17, 0xFEB2, 1, 2, -1,  {1, 1}},   // س
55     {18, 0xFEB6, 1, 2, -1,  {1, 1}},   // ش
56     {19, 0xFEBA, 1, 2, -1,  {1, 1}},   // ص
57     {20, 0xFEBE, 1, 2, -1,  {1, 1}},   // ض
58     {21, 0xFEC2, 1, 2, -1,  {1, 1}},   // ط
59     {22, 0xFEC6, 1, 2, -1,  {1, 1}},   // ظ
60     {23, 0xFECA, 1, 2, -1,  {1, 1}},   // ع
61     {24, 0xFECE, 1, 2, -1,  {1, 1}},   // غ
62     {31, 0xFED2, 1, 2, -1,  {1, 1}},   // ف
63     {32, 0xFED6, 1, 2, -1,  {1, 1}},   // ق
64     {135, 0xFB8F, 1, 2, -1,  {1, 1}},  // ک
65     {33, 0xFEDA, 1, 2, -1,  {1, 1}},  // ﻙ
66     {141, 0xFB93, 1, 2, -1,  {1, 1}},  // گ
67     {34, 0xFEDE, 1, 2, -1,  {1, 1}},   // ل
68     {35, 0xFEE2, 1, 2, -1,  {1, 1}},   // م
69     {36, 0xFEE6, 1, 2, -1,  {1, 1}},   // ن
70     {38, 0xFEEE, -1, 0, -1,  {1, 0}},   // و
71     {37, 0xFEEA, 1, 2, -1,  {1, 1}},   // ه
72     {39, 0xFBFD, 1, 2, -1,  {1, 1}},   // ي
73     {40, 0xFEF2, 1, 2, -1,  {1, 1}},   // ي
74     {170, 0xFBFD, 1, 2, -1,  {1, 1}},   // ی
75     {7, 0xFE94, 1, 2, -1,  {1, 0}},   // ة
76     {206, 0x06F0, 1, 2, -1,  {0, 0}},  // ۰
77     {207, 0x06F1, 0, 0, 0,  {0, 0}},  // ۱
78     {208, 0x06F2, 0, 0, 0,  {0, 0}},  // ۲
79     {209, 0x06F3, 0, 0, 0,  {0, 0}},  // ۳
80     {210, 0x06F4, 0, 0, 0,  {0, 0}},  // ۴
81     {211, 0x06F5, 0, 0, 0,  {0, 0}},  // ۵
82     {212, 0x06F6, 0, 0, 0,  {0, 0}},  // ۶
83     {213, 0x06F7, 0, 0, 0,  {0, 0}},  // ۷
84     {214, 0x06F8, 0, 0, 0,  {0, 0}},  // ۸
85     {215, 0x06F9, 0, 0, 0,  {0, 0}},  // ۹
86     LV_AP_END_CHARS_LIST
87 };
88 /**********************
89 *      MACROS
90 **********************/
91 
92 /**********************
93 *   GLOBAL FUNCTIONS
94 **********************/
_lv_txt_ap_calc_bytes_cnt(const char * txt)95 uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt)
96 {
97     uint32_t txt_length = 0;
98     uint32_t chars_cnt = 0;
99     uint32_t current_ap_idx = 0;
100     uint32_t i, j;
101     uint32_t ch_enc;
102 
103     txt_length = _lv_txt_get_encoded_length(txt);
104 
105     i = 0;
106     j = 0;
107     while(i < txt_length) {
108         ch_enc = _lv_txt_encoded_next(txt, &j);
109         current_ap_idx = lv_ap_get_char_index(ch_enc);
110 
111         if(current_ap_idx != LV_UNDEF_ARABIC_PERSIAN_CHARS)
112             ch_enc = ap_chars_map[current_ap_idx].char_end_form;
113 
114         if(ch_enc < 0x80)
115             chars_cnt++;
116         else if(ch_enc < 0x0800)
117             chars_cnt += 2;
118         else  if(ch_enc < 0x010000)
119             chars_cnt += 3;
120         else
121             chars_cnt += 4;
122 
123         i++;
124     }
125 
126     return chars_cnt + 1;
127 }
128 
129 
_lv_txt_ap_proc(const char * txt,char * txt_out)130 void _lv_txt_ap_proc(const char * txt, char * txt_out)
131 {
132     uint32_t txt_length = 0;
133     uint32_t index_current, idx_next, idx_previous, i, j;
134     uint32_t * ch_enc;
135     char * txt_out_temp;
136 
137     txt_length = _lv_txt_get_encoded_length(txt);
138 
139     ch_enc = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1));
140 
141     i = 0;
142     j = 0;
143     while(j < txt_length)
144         ch_enc[j++] = _lv_txt_encoded_next(txt, &i);
145 
146     ch_enc[j] = 0;
147 
148     i = 0;
149     idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS;
150     while(i < txt_length) {
151         index_current = lv_ap_get_char_index(ch_enc[i]);
152         idx_next = lv_ap_get_char_index(ch_enc[i + 1]);
153 
154         if(index_current == LV_UNDEF_ARABIC_PERSIAN_CHARS) {
155             i++;
156             idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS;
157             continue;
158         }
159 
160         uint8_t conjunction_to_previuse = (i == 0 ||
161                                            idx_previous == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_previous].ap_chars_conjunction.conj_to_next;
162         uint8_t conjunction_to_next = ((i == txt_length - 1) ||
163                                        idx_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_next].ap_chars_conjunction.conj_to_previous;
164 
165         if(conjunction_to_previuse && conjunction_to_next)
166             ch_enc[i] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_middle_form_offset;
167         else if(!conjunction_to_previuse && conjunction_to_next)
168             ch_enc[i] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_begining_form_offset;
169         else if(conjunction_to_previuse && !conjunction_to_next)
170             ch_enc[i] = ap_chars_map[index_current].char_end_form;
171         else
172             ch_enc[i] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_isolated_form_offset;
173         idx_previous = index_current;
174         i++;
175     }
176 
177     txt_out_temp = txt_out;
178     i = 0;
179 
180     while(i < txt_length) {
181         if(ch_enc[i] < 0x80) {
182             *(txt_out_temp++) = ch_enc[i] & 0xFF;
183         }
184         else if(ch_enc[i] < 0x0800) {
185             *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x1F) | 0xC0;
186             *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
187         }
188         else if(ch_enc[i] < 0x010000) {
189             *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x0F) | 0xE0;
190             *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80;
191             *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
192         }
193         else if(ch_enc[i] < 0x110000) {
194             *(txt_out_temp++) = ((ch_enc[i] >> 18) & 0x07) | 0xF0;
195             *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x3F) | 0x80;
196             *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80;
197             *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80;
198         }
199 
200         i++;
201     }
202     *(txt_out_temp) = '\0';
203     lv_mem_free(ch_enc);
204 }
205 /**********************
206 *   STATIC FUNCTIONS
207 **********************/
208 
lv_ap_get_char_index(uint16_t c)209 static uint32_t lv_ap_get_char_index(uint16_t c)
210 {
211     for(uint8_t i = 0; ap_chars_map[i].char_end_form; i++) {
212         if(c == (ap_chars_map[i].char_offset + LV_AP_ALPHABET_BASE_CODE))
213             return i;
214     }
215     return LV_UNDEF_ARABIC_PERSIAN_CHARS;
216 }
217 
218 #endif
219