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