acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_txt_ap.c (10026B)
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_mem.h" 14 #include "../draw/lv_draw.h" 15 16 /********************* 17 * DEFINES 18 *********************/ 19 20 /********************** 21 * TYPEDEFS 22 **********************/ 23 typedef struct { 24 uint8_t char_offset; 25 uint16_t char_end_form; 26 int8_t char_begining_form_offset; 27 int8_t char_middle_form_offset; 28 int8_t char_isolated_form_offset; 29 struct { 30 uint8_t conj_to_previous; 31 uint8_t conj_to_next; 32 } ap_chars_conjunction; 33 } ap_chars_map_t; 34 35 /********************** 36 * STATIC PROTOTYPES 37 **********************/ 38 #if LV_USE_ARABIC_PERSIAN_CHARS == 1 39 static uint32_t lv_ap_get_char_index(uint16_t c); 40 static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next); 41 static bool lv_txt_is_arabic_vowel(uint16_t c); 42 43 /********************** 44 * STATIC VARIABLES 45 **********************/ 46 47 const ap_chars_map_t ap_chars_map[] = { 48 /*{Key Offset, End, Beginning, Middle, Isolated, {conjunction}}*/ 49 {1, 0xFE84, -1, 0, -1, {1, 0}}, // أ 50 {2, 0xFE86, -1, 0, -1, {1, 0}}, // ؤ 51 {3, 0xFE88, -1, 0, -1, {1, 0}}, // ﺇ 52 {4, 0xFE8A, 1, 2, -1, {1, 0}}, // ئ 53 {5, 0xFE8E, -1, 0, -1, {1, 0}}, // آ 54 {6, 0xFE90, 1, 2, -1, {1, 1}}, // ب 55 {92, 0xFB57, 1, 2, -1, {1, 1}}, // پ 56 {8, 0xFE96, 1, 2, -1, {1, 1}}, // ت 57 {9, 0xFE9A, 1, 2, -1, {1, 1}}, // ث 58 {10, 0xFE9E, 1, 2, -1, {1, 1}}, // ج 59 {100, 0xFB7B, 1, 2, -1, {1, 1}}, // چ 60 {11, 0xFEA2, 1, 2, -1, {1, 1}}, // ح 61 {12, 0xFEA6, 1, 2, -1, {1, 1}}, // خ 62 {13, 0xFEAA, -1, 0, -1, {1, 0}}, // د 63 {14, 0xFEAC, -1, 0, -1, {1, 0}}, // ذ 64 {15, 0xFEAE, -1, 0, -1, {1, 0}}, // ر 65 {16, 0xFEB0, -1, 0, -1, {1, 0}}, // ز 66 {118, 0xFB8B, -1, 0, -1, {1, 0}}, // ژ 67 {17, 0xFEB2, 1, 2, -1, {1, 1}}, // س 68 {18, 0xFEB6, 1, 2, -1, {1, 1}}, // ش 69 {19, 0xFEBA, 1, 2, -1, {1, 1}}, // ص 70 {20, 0xFEBE, 1, 2, -1, {1, 1}}, // ض 71 {21, 0xFEC2, 1, 2, -1, {1, 1}}, // ط 72 {22, 0xFEC6, 1, 2, -1, {1, 1}}, // ظ 73 {23, 0xFECA, 1, 2, -1, {1, 1}}, // ع 74 {24, 0xFECE, 1, 2, -1, {1, 1}}, // غ 75 {30, 0x0640, 0, 0, 0, {1, 1}}, // - (mad, hyphen) 76 {31, 0xFED2, 1, 2, -1, {1, 1}}, // ف 77 {32, 0xFED6, 1, 2, -1, {1, 1}}, // ق 78 {135, 0xFB8F, 1, 2, -1, {1, 1}}, // ک 79 {33, 0xFEDA, 1, 2, -1, {1, 1}}, // ﻙ 80 {141, 0xFB93, 1, 2, -1, {1, 1}}, // گ 81 {34, 0xFEDE, 1, 2, -1, {1, 1}}, // ل 82 {35, 0xFEE2, 1, 2, -1, {1, 1}}, // م 83 {36, 0xFEE6, 1, 2, -1, {1, 1}}, // ن 84 {38, 0xFEEE, -1, 0, -1, {1, 0}}, // و 85 {37, 0xFEEA, 1, 2, -1, {1, 1}}, // ه 86 {39, 0xFEF0, 0, 0, -1, {1, 0}}, // ى 87 {40, 0xFEF2, 1, 2, -1, {1, 1}}, // ي 88 {170, 0xFBFD, 1, 2, -1, {1, 1}}, // ی 89 {7, 0xFE94, 1, 2, -1, {1, 0}}, // ة 90 {206, 0x06F0, 1, 2, -1, {0, 0}}, // ۰ 91 {207, 0x06F1, 0, 0, 0, {0, 0}}, // ۱ 92 {208, 0x06F2, 0, 0, 0, {0, 0}}, // ۲ 93 {209, 0x06F3, 0, 0, 0, {0, 0}}, // ۳ 94 {210, 0x06F4, 0, 0, 0, {0, 0}}, // ۴ 95 {211, 0x06F5, 0, 0, 0, {0, 0}}, // ۵ 96 {212, 0x06F6, 0, 0, 0, {0, 0}}, // ۶ 97 {213, 0x06F7, 0, 0, 0, {0, 0}}, // ۷ 98 {214, 0x06F8, 0, 0, 0, {0, 0}}, // ۸ 99 {215, 0x06F9, 0, 0, 0, {0, 0}}, // ۹ 100 LV_AP_END_CHARS_LIST 101 }; 102 /********************** 103 * MACROS 104 **********************/ 105 106 /********************** 107 * GLOBAL FUNCTIONS 108 **********************/ 109 uint32_t _lv_txt_ap_calc_bytes_cnt(const char * txt) 110 { 111 uint32_t txt_length = 0; 112 uint32_t chars_cnt = 0; 113 uint32_t current_ap_idx = 0; 114 uint32_t i, j; 115 uint32_t ch_enc; 116 117 txt_length = _lv_txt_get_encoded_length(txt); 118 119 i = 0; 120 j = 0; 121 while(i < txt_length) { 122 ch_enc = _lv_txt_encoded_next(txt, &j); 123 current_ap_idx = lv_ap_get_char_index(ch_enc); 124 125 if(current_ap_idx != LV_UNDEF_ARABIC_PERSIAN_CHARS) 126 ch_enc = ap_chars_map[current_ap_idx].char_end_form; 127 128 if(ch_enc < 0x80) 129 chars_cnt++; 130 else if(ch_enc < 0x0800) 131 chars_cnt += 2; 132 else if(ch_enc < 0x010000) 133 chars_cnt += 3; 134 else 135 chars_cnt += 4; 136 137 i++; 138 } 139 140 return chars_cnt + 1; 141 } 142 143 void _lv_txt_ap_proc(const char * txt, char * txt_out) 144 { 145 uint32_t txt_length = 0; 146 uint32_t index_current, idx_next, idx_previous, i, j; 147 uint32_t * ch_enc; 148 uint32_t * ch_fin; 149 char * txt_out_temp; 150 151 txt_length = _lv_txt_get_encoded_length(txt); 152 153 ch_enc = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1)); 154 ch_fin = (uint32_t *)lv_mem_alloc(sizeof(uint32_t) * (txt_length + 1)); 155 156 i = 0; 157 j = 0; 158 while(j < txt_length) 159 ch_enc[j++] = _lv_txt_encoded_next(txt, &i); 160 161 ch_enc[j] = 0; 162 163 i = 0; 164 j = 0; 165 idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS; 166 while(i < txt_length) { 167 index_current = lv_ap_get_char_index(ch_enc[i]); 168 idx_next = lv_ap_get_char_index(ch_enc[i + 1]); 169 170 if(lv_txt_is_arabic_vowel(ch_enc[i])) { // Current character is a vowel 171 ch_fin[j] = ch_enc[i]; 172 i++; 173 j++; 174 continue; // Skip this character 175 } 176 else if(lv_txt_is_arabic_vowel(ch_enc[i + 1])) { // Next character is a vowel 177 idx_next = lv_ap_get_char_index(ch_enc[i + 2]); // Skip the vowel character to join with the character after it 178 } 179 180 if(index_current == LV_UNDEF_ARABIC_PERSIAN_CHARS) { 181 ch_fin[j] = ch_enc[i]; 182 j++; 183 i++; 184 idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS; 185 continue; 186 } 187 188 uint8_t conjunction_to_previuse = (i == 0 || 189 idx_previous == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_previous].ap_chars_conjunction.conj_to_next; 190 uint8_t conjunction_to_next = ((i == txt_length - 1) || 191 idx_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) ? 0 : ap_chars_map[idx_next].ap_chars_conjunction.conj_to_previous; 192 193 uint32_t lam_alef = lv_txt_lam_alef(index_current, idx_next); 194 if(lam_alef) { 195 if(conjunction_to_previuse) { 196 lam_alef ++; 197 } 198 ch_fin[j] = lam_alef; 199 idx_previous = LV_UNDEF_ARABIC_PERSIAN_CHARS; 200 i += 2; 201 j++; 202 continue; 203 } 204 205 if(conjunction_to_previuse && conjunction_to_next) 206 ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_middle_form_offset; 207 else if(!conjunction_to_previuse && conjunction_to_next) 208 ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_begining_form_offset; 209 else if(conjunction_to_previuse && !conjunction_to_next) 210 ch_fin[j] = ap_chars_map[index_current].char_end_form; 211 else 212 ch_fin[j] = ap_chars_map[index_current].char_end_form + ap_chars_map[index_current].char_isolated_form_offset; 213 idx_previous = index_current; 214 i++; 215 j++; 216 } 217 ch_fin[j] = 0; 218 for(i = 0; i < txt_length; i++) 219 ch_enc[i] = 0; 220 for(i = 0; i < j; i++) 221 ch_enc[i] = ch_fin[i]; 222 lv_mem_free(ch_fin); 223 224 txt_out_temp = txt_out; 225 i = 0; 226 227 while(i < txt_length) { 228 if(ch_enc[i] < 0x80) { 229 *(txt_out_temp++) = ch_enc[i] & 0xFF; 230 } 231 else if(ch_enc[i] < 0x0800) { 232 *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x1F) | 0xC0; 233 *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80; 234 } 235 else if(ch_enc[i] < 0x010000) { 236 *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x0F) | 0xE0; 237 *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80; 238 *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80; 239 } 240 else if(ch_enc[i] < 0x110000) { 241 *(txt_out_temp++) = ((ch_enc[i] >> 18) & 0x07) | 0xF0; 242 *(txt_out_temp++) = ((ch_enc[i] >> 12) & 0x3F) | 0x80; 243 *(txt_out_temp++) = ((ch_enc[i] >> 6) & 0x3F) | 0x80; 244 *(txt_out_temp++) = ((ch_enc[i] >> 0) & 0x3F) | 0x80; 245 } 246 247 i++; 248 } 249 *(txt_out_temp) = '\0'; 250 lv_mem_free(ch_enc); 251 } 252 /********************** 253 * STATIC FUNCTIONS 254 **********************/ 255 256 static uint32_t lv_ap_get_char_index(uint16_t c) 257 { 258 for(uint8_t i = 0; ap_chars_map[i].char_end_form; i++) { 259 if(c == (ap_chars_map[i].char_offset + LV_AP_ALPHABET_BASE_CODE)) 260 return i; 261 else if(c == ap_chars_map[i].char_end_form //is it an End form 262 || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_begining_form_offset) //is it a Beginning form 263 || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_middle_form_offset) //is it a middle form 264 || c == (ap_chars_map[i].char_end_form + ap_chars_map[i].char_isolated_form_offset)) { //is it an isolated form 265 return i; 266 } 267 } 268 return LV_UNDEF_ARABIC_PERSIAN_CHARS; 269 } 270 271 static uint32_t lv_txt_lam_alef(uint32_t ch_curr, uint32_t ch_next) 272 { 273 uint32_t ch_code = 0; 274 if(ap_chars_map[ch_curr].char_offset != 34) { 275 return 0; 276 } 277 if(ch_next == LV_UNDEF_ARABIC_PERSIAN_CHARS) { 278 return 0; 279 } 280 ch_code = ap_chars_map[ch_next].char_offset + LV_AP_ALPHABET_BASE_CODE; 281 if(ch_code == 0x0622) { 282 return 0xFEF5; // (lam-alef) mad 283 } 284 if(ch_code == 0x0623) { 285 return 0xFEF7; // (lam-alef) top hamza 286 } 287 if(ch_code == 0x0625) { 288 return 0xFEF9; // (lam-alef) bot hamza 289 } 290 if(ch_code == 0x0627) { 291 return 0xFEFB; // (lam-alef) alef 292 } 293 return 0; 294 } 295 296 static bool lv_txt_is_arabic_vowel(uint16_t c) 297 { 298 return (c >= 0x064B) && (c <= 0x0652); 299 } 300 301 #endif