LCOV - code coverage report
Current view: top level - src/braille/internal - louis.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 167 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2023 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include <sstream>
      24              : #include <stdint.h>
      25              : #include <stdio.h>
      26              : #include <stdlib.h>
      27              : #include <string.h>
      28              : #include <vector>
      29              : 
      30              : #include <QString>
      31              : 
      32              : #include "internal.h"
      33              : #include "liblouis.h"
      34              : 
      35              : #define WIDECHARS_ARE_UCS4
      36              : 
      37              : #define FUNC u32_to_u8
      38              : #define SRC_UNIT uint32_t
      39              : #define DST_UNIT uint8_t
      40              : 
      41              : /* Type representing a Unicode character.  */
      42              : typedef uint32_t ucs4_t;
      43              : 
      44              : int
      45            0 : u8_uctomb(uint8_t* s, ucs4_t uc, int n)
      46              : {
      47            0 :     if (uc < 0x80U) {
      48            0 :         if (n > 0) {
      49            0 :             s[0] = uc;
      50            0 :             return 1;
      51              :         }
      52              :         /* else return -2, below.  */
      53              :     } else {
      54              :         int count;
      55              : 
      56            0 :         if (uc < 0x800U) {
      57            0 :             count = 2;
      58            0 :         } else if (uc < 0x10000U) {
      59            0 :             if (uc < 0xd800U || uc >= 0xe000U) {
      60            0 :                 count = 3;
      61              :             } else {
      62            0 :                 return -1;
      63              :             }
      64            0 :         } else if (uc < 0x110000U) {
      65            0 :             count = 4;
      66              :         } else {
      67            0 :             return -1;
      68              :         }
      69              : 
      70            0 :         if (n >= count) {
      71            0 :             switch (count) { /* note: code falls through cases! */
      72            0 :             case 4: s[3] = 0x80 | (uc & 0x3f);
      73            0 :                 uc = uc >> 6;
      74            0 :                 uc |= 0x10000;
      75              :             // FALLTHROUGH
      76            0 :             case 3: s[2] = 0x80 | (uc & 0x3f);
      77            0 :                 uc = uc >> 6;
      78            0 :                 uc |= 0x800;
      79              :             // FALLTHROUGH
      80            0 :             case 2: s[1] = 0x80 | (uc & 0x3f);
      81            0 :                 uc = uc >> 6;
      82            0 :                 uc |= 0xc0;
      83            0 :                 /*case 1:*/ s[0] = uc;
      84              :             }
      85            0 :             return count;
      86              :         }
      87              :     }
      88            0 :     return -2;
      89              : }
      90              : 
      91              : DST_UNIT*
      92            0 : FUNC(const SRC_UNIT* s, size_t n, DST_UNIT* resultbuf, size_t* lengthp)
      93              : {
      94            0 :     const SRC_UNIT* s_end = s + n;
      95              :     /* Output string accumulator.  */
      96              :     DST_UNIT* result;
      97              :     size_t allocated;
      98              :     size_t length;
      99              : 
     100            0 :     if (resultbuf != NULL) {
     101            0 :         result = resultbuf;
     102            0 :         allocated = *lengthp;
     103              :     } else {
     104            0 :         result = NULL;
     105            0 :         allocated = 0;
     106              :     }
     107            0 :     length = 0;
     108              :     /* Invariants:
     109              :        result is either == resultbuf or == NULL or malloc-allocated.
     110              :        If length > 0, then result != NULL.  */
     111              : 
     112            0 :     while (s < s_end)
     113              :     {
     114              :         ucs4_t uc;
     115              :         int count;
     116              : 
     117              :         /* Fetch a Unicode character from the input string.  */
     118            0 :         uc = *s++;
     119              :         /* No need to call the safe variant u32_mbtouc, because
     120              :            u8_uctomb will verify uc anyway.  */
     121              : 
     122              :         /* Store it in the output string.  */
     123            0 :         count = u8_uctomb(result + length, uc, static_cast<int>(allocated - length));
     124            0 :         if (count == -1) {
     125            0 :             if (!(result == resultbuf || result == NULL)) {
     126            0 :                 free(result);
     127              :             }
     128            0 :             errno = EILSEQ;
     129            0 :             return NULL;
     130              :         }
     131            0 :         if (count == -2) {
     132              :             DST_UNIT* memory;
     133              : 
     134            0 :             allocated = (allocated > 0U ? 2 * allocated : 12);
     135            0 :             if (length + 6 > allocated) {
     136            0 :                 allocated = length + 6;
     137              :             }
     138            0 :             if (result == resultbuf || result == NULL) {
     139            0 :                 memory = (DST_UNIT*)malloc(allocated * sizeof(DST_UNIT));
     140              :             } else {
     141              :                 memory
     142            0 :                     =(DST_UNIT*)realloc(result, allocated * sizeof(DST_UNIT));
     143              :             }
     144              : 
     145            0 :             if (memory == NULL) {
     146            0 :                 if (!(result == resultbuf || result == NULL)) {
     147            0 :                     free(result);
     148              :                 }
     149            0 :                 errno = ENOMEM;
     150            0 :                 return NULL;
     151              :             }
     152            0 :             if (result == resultbuf && length > 0) {
     153            0 :                 memcpy((char*)memory, (char*)result,
     154              :                        length * sizeof(DST_UNIT));
     155              :             }
     156            0 :             result = memory;
     157            0 :             count = u8_uctomb(result + length, uc, static_cast<int>(allocated - length));
     158            0 :             if (count < 0) {
     159            0 :                 abort();
     160              :             }
     161              :         }
     162            0 :         length += count;
     163              :     }
     164              : 
     165            0 :     if (length == 0U) {
     166            0 :         if (result == NULL) {
     167              :             /* Return a non-NULL value.  NULL means error.  */
     168            0 :             result = (DST_UNIT*)malloc(1);
     169            0 :             if (result == NULL) {
     170            0 :                 errno = ENOMEM;
     171            0 :                 return NULL;
     172              :             }
     173              :         }
     174            0 :     } else if (result != resultbuf && length < allocated) {
     175              :         /* Shrink the allocated memory if possible.  */
     176              :         DST_UNIT* memory;
     177              : 
     178            0 :         memory = (DST_UNIT*)realloc(result, length * sizeof(DST_UNIT));
     179            0 :         if (memory != NULL) {
     180            0 :             result = memory;
     181              :         }
     182              :     }
     183              : 
     184            0 :     *lengthp = length;
     185            0 :     return result;
     186              : }
     187              : 
     188              : std::string table_unicode_to_ascii = "unicode-to-ascii.dis";
     189              : std::string table_ascii_to_unicode = "ascii-to-unicode.dis";
     190              : std::string table_for_literature = "unicode.dis,en-us-g2.ctb";
     191              : std::string table_for_general = "unicode.dis,en-us-symbols.mus";
     192              : std::string tables_dir = "";
     193              : 
     194            0 : void initTables(std::string dir)
     195              : {
     196            0 :     if (dir.empty()) {
     197            0 :         table_unicode_to_ascii = "unicode-to-ascii.dis";
     198            0 :         table_ascii_to_unicode = "ascii-to-unicode.dis";
     199            0 :         table_for_literature = "unicode.dis,en-us-g2.ctb";
     200            0 :         table_for_general = "unicode.dis,en-us-symbols.mus";
     201              :     } else {
     202            0 :         table_unicode_to_ascii = dir + "/unicode-to-ascii.dis";
     203            0 :         table_ascii_to_unicode = dir + "/ascii-to-unicode.dis";
     204            0 :         table_for_literature = dir + "/unicode.dis," + dir + "/en-us-g2.ctb";
     205            0 :         table_for_general = dir + "/unicode.dis," + dir + "/en-us-symbols.mus";
     206              :     }
     207            0 :     tables_dir = dir;
     208            0 : }
     209              : 
     210            0 : void updateTableForLyrics(std::string table)
     211              : {
     212            0 :     if (tables_dir.empty()) {
     213            0 :         table_for_literature = "unicode.dis," + table;
     214              :     } else {
     215            0 :         table_for_literature = tables_dir + "/unicode.dis," + tables_dir + "/" + table;
     216              :     }
     217            0 : }
     218              : 
     219            0 : std::string braille_translate(const char* table_name, std::string txt)
     220              : {
     221            0 :     uint8_t* outputbuf = nullptr;
     222            0 :     size_t outlen = 0;
     223              :     widechar inbuf[MAXSTRING];
     224              :     widechar transbuf[MAXSTRING];
     225            0 :     int inlen = 0;
     226            0 :     int translen = 0;
     227              : 
     228            0 :     inlen = _lou_extParseChars(txt.c_str(), inbuf);
     229              : 
     230            0 :     translen = MAXSTRING;
     231            0 :     lou_translateString(
     232              :         table_name, inbuf, &inlen, transbuf, &translen, NULL, NULL, 0);
     233              : 
     234              : #ifdef WIDECHARS_ARE_UCS4
     235              :     //outputbuf = (uint8_t *) malloc (translen * sizeof(widechar) * sizeof (uint8_t));
     236            0 :     outputbuf = u32_to_u8(transbuf, translen, NULL, &outlen);
     237              : #else
     238              :     outputbuf = u16_to_u8(transbuf, translen, NULL, &outlen);
     239              : #endif
     240              : 
     241            0 :     if (!outputbuf) {
     242            0 :         return std::string();
     243              :     }
     244              : 
     245            0 :     std::string ret = std::string(outputbuf, outputbuf + outlen);
     246            0 :     free(outputbuf);
     247              : 
     248            0 :     return ret;
     249            0 : }
     250              : 
     251            0 : int check_tables(const char* tables)
     252              : {
     253            0 :     if (lou_checkTable(tables) == 0) {
     254            0 :         return -1;
     255              :     } else {
     256            0 :         return 0;
     257              :     }
     258              : }
     259              : 
     260            0 : char* setTablesDir(const char* tablesdir)
     261              : {
     262            0 :     return lou_setDataPath(tablesdir);
     263              : }
     264              : 
     265            0 : char* getTablesDir()
     266              : {
     267            0 :     return lou_getDataPath();
     268              : }
     269              : 
     270            0 : std::vector<std::string> split_string(std::string txt, int width)
     271              : {
     272            0 :     std::vector<std::string> lines;
     273              : 
     274            0 :     QString str = QString::fromStdString(txt);
     275              : 
     276            0 :     int len = str.length();
     277              : 
     278            0 :     if (len <= width) {
     279            0 :         lines.push_back(txt);
     280            0 :         return lines;
     281              :     }
     282              : 
     283            0 :     while (len > width) {
     284            0 :         int idx = width - 1;
     285            0 :         for (; idx >= 0; idx--) {
     286            0 :             QString ch = str.left(idx).right(1);
     287            0 :             if (ch == "⠀") {
     288            0 :                 break;
     289              :             }
     290            0 :         }
     291            0 :         if (idx == 0 || idx == -1) {
     292            0 :             idx = width;
     293              :         }
     294              : 
     295            0 :         QString line = str.left(idx);
     296              : 
     297            0 :         str = str.right(len - idx);
     298            0 :         len = str.length();
     299            0 :         lines.push_back(line.toStdString());
     300            0 :     }
     301            0 :     if (len > 0) {
     302            0 :         lines.push_back(str.toStdString());
     303              :     }
     304            0 :     return lines;
     305            0 : }
     306              : 
     307            0 : std::string braille_long_translate(const char* table_name, std::string txt)
     308              : {
     309            0 :     std::vector<std::string> lines = split_string(txt, 256);
     310              : 
     311            0 :     if (lines.size() == 0U) {
     312            0 :         return "";
     313              :     }
     314              : 
     315            0 :     std::string buffer = braille_translate(table_name, lines.front());
     316              : 
     317            0 :     for (size_t i = 1; i < lines.size(); i++) {
     318            0 :         std::string text = lines[i] + " ";
     319            0 :         buffer.append(braille_translate(table_name, text));
     320            0 :     }
     321            0 :     return buffer;
     322            0 : }
     323              : 
     324            0 : std::string braille_multi_line_translate(const char* table_name, std::string txt)
     325              : {
     326            0 :     std::stringstream ss(txt);
     327            0 :     std::string line;
     328              : 
     329            0 :     std::string buffer = "";
     330              : 
     331            0 :     while (std::getline(ss, line)) {
     332            0 :         if (line == "[EOP]" || line == "[NP]") {
     333            0 :             buffer.append(line).append("\n");
     334              :         } else {
     335            0 :             std::string converted = braille_translate(table_name, line);
     336            0 :             buffer.append(converted).append("\n");
     337            0 :         }
     338              :     }
     339              : 
     340            0 :     return buffer;
     341            0 : }
     342              : 
     343            0 : int get_braille_text_length(const char* table_name, std::string txt)
     344              : {
     345            0 :     std::string buffer = braille_translate(table_name, txt);
     346            0 :     return QString::fromStdString(txt).length();
     347            0 : }
        

Generated by: LCOV version 2.0-1