Add 4 stage trie to lookup unicode codepoint width and grapheme join rules. Generated by GraphemeTableGen from Microsoft Terminal (MIT Licence): https://github.com/microsoft/terminal/blob/a7e47b711a2adc7b9e80eddea8168089f7d3b11e/src/tools/GraphemeTableGen/Program.cs With minor adjustment to use it in C codebase. - Replaced constexpr with static - Replaced auto with explicit types Generated from Unicode 16.0.0: ucd.nounihan.grouped.xml: sha256(b11c2d23673bae660fff8ddcd3c1de4d54bdf6c60188a07696b010282f515fcf)
Showing the changes to test/codepoint_width.c (1 of 6 files). Show all
Unified · Split
| @@ -0,0 +1,67 @@ | ||
| 1 | +/* | |
| 2 | + * This file is part of mpv. | |
| 3 | + * | |
| 4 | + * mpv is free software; you can redistribute it and/or | |
| 5 | + * modify it under the terms of the GNU Lesser General Public | |
| 6 | + * License as published by the Free Software Foundation; either | |
| 7 | + * version 2.1 of the License, or (at your option) any later version. | |
| 8 | + * | |
| 9 | + * mpv is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU Lesser General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU Lesser General Public | |
| 15 | + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | + */ | |
| 17 | + | |
| 18 | +#include "test_utils.h" | |
| 19 | + | |
| 20 | +#include "misc/codepoint_width.h" | |
| 21 | + | |
| 22 | +#define W(s) term_disp_width((bstr)bstr0_lit(s)) | |
| 23 | + | |
| 24 | +int main(void) { | |
| 25 | + assert_int_equal(W("A"), 1); // Single ASCII character | |
| 26 | + assert_int_equal(W("ABC"), 3); // Multiple ASCII characters | |
| 27 | + | |
| 28 | + assert_int_equal(W("\u3042"), 2); // Full-width Japanese Hiragana 'あ' (U+3042) | |
| 29 | + assert_int_equal(W("\u4F60"), 2); // Full-width Chinese character '你' (U+4F60) | |
| 30 | + assert_int_equal(W("\u4F60\u597D"), 4); // Two full-width Chinese characters '你好' (U+4F60 U+597D) | |
| 31 | + | |
| 32 | + assert_int_equal(W("a\u0301"), 1); // 'a' + combining acute accent '́' (U+0301) | |
| 33 | + assert_int_equal(W("e\u0301"), 1); // 'e' + combining acute accent '́' (U+0301) | |
| 34 | + assert_int_equal(W("a\u0308"), 1); // 'a' + combining diaeresis '̈' (U+0308) | |
| 35 | + | |
| 36 | + // Family emoji: 👩❤️👩 (Woman + ZWJ + Heart + ZWJ + Woman; | |
| 37 | + // Code points: U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469) | |
| 38 | + assert_int_equal(W("\U0001F469\u200D\u2764\uFE0F\u200D\U0001F469"), 2); | |
| 39 | + // Man emoji with skin tone modifier | |
| 40 | + assert_int_equal(W("\U0001F468\U0001F3FE"), 2); | |
| 41 | + // Person Shrugging + skin tone modifier + ZWJ + woman sign + variant selector | |
| 42 | + assert_int_equal(W("\U0001F937\U0001F3FE\u200D\U00002640\U0000FE0F"), 2); | |
| 43 | + // Regional indicator symbols forming the flag of Poland | |
| 44 | + assert_int_equal(W("\U0001F1F5\U0001F1F1"), 2); | |
| 45 | + | |
| 46 | + assert_int_equal(W("\n"), 0); // Newline (should not take up any visual space) | |
| 47 | + assert_int_equal(W("\t"), 0); // Tab (no visual width itself) | |
| 48 | + assert_int_equal(W("\0"), 0); // Null character (non-visible) | |
| 49 | + | |
| 50 | + assert_int_equal(W("A\u3042"), 3); // ASCII 'A' + full-width Japanese Hiragana 'あ' (U+3042) | |
| 51 | + assert_int_equal(W("a\u0301A"), 2); // Combining character 'á' (a + U+0301) and ASCII 'A' | |
| 52 | + | |
| 53 | + // Grapheme cluster + ASCII 'A' + full-width Japanese Hiragana 'あ' (U+3042) | |
| 54 | + assert_int_equal(W("\U0001F469\u200D\u2764\uFE0F\u200D\U0001F469A\u3042"), 5); | |
| 55 | + | |
| 56 | + assert_int_equal(W("A\nB"), 2); // ASCII characters with newline (newline should not affect width) | |
| 57 | + assert_int_equal(W("ABC\tDEF"), 6); // Tab inside a string (no visual width for '\t') | |
| 58 | + | |
| 59 | + // ASCII characters with color | |
| 60 | + assert_int_equal(W("\033[31mABC\033[0m\033[32mDEF\033[0m"), 6); | |
| 61 | + | |
| 62 | + // ASCII characters with color and a newline | |
| 63 | + assert_int_equal(W("\033[31mABC\033[0m\033[32mDEF\033[0m\n"), 6); | |
| 64 | + | |
| 65 | + // ASCII characters with carriage return | |
| 66 | + assert_int_equal(W("ABC\rDEF"), 3); | |
| 67 | +} | |