History

misc/codepoint_width: add unicode width detection support

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)

Kacper Michajłow committed 2 years ago

Commit 95f00461 parent fa77ad46 files · +823 −34Browse files

Unified · Split

6 files
  1. common/msg.c +2 −34
  2. meson.build +1 −0
  3. misc/codepoint_width.c +737 −0
  4. misc/codepoint_width.h +11 −0
  5. test/codepoint_width.c +67 −0
  6. test/meson.build +5 −0
common/msg.c+2−34
@@ -25,14 +25,13 @@ · 24 unmodified lines
25 25
26#include "mpv_talloc.h"26#include "mpv_talloc.h"
27 27
28#include "misc/bstr.h"
29#include "common/common.h"28#include "common/common.h"
30#include "common/global.h"29#include "common/global.h"
31#include "misc/bstr.h"30#include "misc/codepoint_width.h"
32#include "options/options.h"31#include "options/options.h"
33#include "options/path.h"32#include "options/path.h"
34#include "osdep/terminal.h"
35#include "osdep/io.h"33#include "osdep/io.h"
34#include "osdep/terminal.h"
36#include "osdep/threads.h"35#include "osdep/threads.h"
37#include "osdep/timer.h"36#include "osdep/timer.h"
38 37
@@ -374,37 +373,6 @@ static bool test_terminal_level(struct mp_log *log, int lev) · 335 unmodified lines
374 !(lev == MSGL_STATUS && terminal_in_background());373 !(lev == MSGL_STATUS && terminal_in_background());
375}374}
376 375
377// This is very basic way to infer needed width for a string.
378static int term_disp_width(bstr str)
379{
380 int width = 0;
381
382 while (str.len) {
383 if (bstr_eatstart0(&str, "\033[")) {
384 while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm'))
385 str = bstr_cut(str, 1);
386 str = bstr_cut(str, 1);
387 continue;
388 }
389
390 bstr code = bstr_split_utf8(str, &str);
391 if (code.len == 0)
392 return 0;
393
394 if (code.len == 1 && *code.start == '\n')
395 continue;
396
397 // Only single-width characters are supported
398 width++;
399
400 // Assume that everything before \r should be discarded for simplicity
401 if (code.len == 1 && *code.start == '\r')
402 width = 0;
403 }
404
405 return width;
406}
407
408static void append_terminal_line(struct mp_log *log, int lev,376static void append_terminal_line(struct mp_log *log, int lev,
409 bstr text, bstr *term_msg, int *line_w)377 bstr text, bstr *term_msg, int *line_w)
410{378{
meson.build+1−0
@@ -134,6 +134,7 @@ sources = files( · 133 unmodified lines
134 ## Misc134 ## Misc
135 'misc/bstr.c',135 'misc/bstr.c',
136 'misc/charset_conv.c',136 'misc/charset_conv.c',
137 'misc/codepoint_width.c',
137 'misc/dispatch.c',138 'misc/dispatch.c',
138 'misc/io_utils.c',139 'misc/io_utils.c',
139 'misc/json.c',140 'misc/json.c',
misc/codepoint_width.c+737−0
@@ -0,0 +1,737 @@
1#include "codepoint_width.h"
2
3#include <stdbool.h>
4#include <stdint.h>
5
6typedef uint_least32_t char32_t;
7
8// Generated by GraphemeTableGen (https://github.com/microsoft/terminal/blob/a7e47b711a2adc7b9e80eddea8168089f7d3b11e/src/tools/GraphemeTableGen/Program.cs)
9// on 2024-09-21T14:12:16Z, from Unicode 16.0.0, 9285 bytes
10// Copyright (c) Microsoft Corporation.
11// Licensed under the MIT license.
12
13// Manually adjusted for C compatibility
14// To generate:
15// 0. Install .NET 8.0
16// 1. Download the tool from: https://github.com/microsoft/terminal/tree/main/src/tools/GraphemeTableGen
17// 2. Download the Unicode data from: https://www.unicode.org/Public/UCD/latest/ucdxml/ucd.nounihan.grouped.zip
18// 3. Build the project: `dotnet build GraphemeTableGen.csproj`
19// 4. Run the tool: `./GraphemeTableGen ucd.nounihan.grouped.xml`
20// 5. Copy the generated code and adjust it for C compatibility by replacing `constexpr` and `auto` keywords.
21
22// clang-format off
23static const uint16_t s_stage0[] = {
24 0x0000, 0x0020, 0x0040, 0x0060, 0x0080, 0x009f, 0x00bf, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca,
25 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00d8, 0x00f8, 0x010a, 0x010e, 0x010b, 0x0108, 0x0113, 0x0133, 0x0153, 0x0153, 0x0153, 0x016f,
26 0x018f, 0x01a7, 0x01c7, 0x01e7, 0x0133, 0x0133, 0x0205, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0221, 0x0236, 0x00ca, 0x00ca,
27 0x0256, 0x0276, 0x0133, 0x0133, 0x0133, 0x028b, 0x02ab, 0x02b9, 0x0133, 0x02cc, 0x02ea, 0x0302, 0x0322, 0x033f, 0x035f, 0x037f,
28 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca,
29 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x039f,
30 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca,
31 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x039f,
32 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
33 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
34 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
35 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
36 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
37 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
38 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
39 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
40 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
41 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
42 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
43 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
44 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
45 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
46 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
47 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
48 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
49 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
50 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
51 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
52 0x03bf, 0x03c7, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
53 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133, 0x0133,
54 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153,
55 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x03e7,
56 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153,
57 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x0153, 0x03e7,
58};
59static const uint16_t s_stage1[] = {
60 0x0000, 0x0004, 0x000c, 0x0014, 0x001c, 0x0024, 0x002a, 0x0031, 0x002a, 0x0037, 0x002a, 0x003f, 0x0047, 0x0049, 0x004f, 0x0057, 0x005f, 0x0065, 0x006d, 0x002a, 0x002a, 0x002a, 0x0073, 0x007b, 0x0083, 0x008a, 0x002a, 0x0091, 0x0098, 0x009f, 0x00a3, 0x00aa,
61 0x00b2, 0x00b8, 0x00be, 0x00c5, 0x00cd, 0x00d5, 0x00dd, 0x00e5, 0x00ed, 0x00f5, 0x00fd, 0x0105, 0x010d, 0x0115, 0x011d, 0x0125, 0x012d, 0x0135, 0x013d, 0x0145, 0x014d, 0x0155, 0x015d, 0x0164, 0x016b, 0x0173, 0x0175, 0x017d, 0x0182, 0x018a, 0x0192, 0x019a,
62 0x019d, 0x01a5, 0x01ad, 0x002a, 0x01b5, 0x01b9, 0x01bd, 0x01c2, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x01ca, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x01d0, 0x01d7, 0x01de, 0x01e6,
63 0x01ed, 0x002a, 0x01f5, 0x002a, 0x01fb, 0x002a, 0x002a, 0x002a, 0x0203, 0x0209, 0x0211, 0x0218, 0x0220, 0x0228, 0x0230, 0x0236, 0x023d, 0x002a, 0x002a, 0x0244, 0x002a, 0x002a, 0x002a, 0x0047, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
64 0x024c, 0x0254, 0x025c, 0x0262, 0x026a, 0x0272, 0x027a, 0x0282, 0x028a, 0x0292, 0x029a, 0x002a, 0x02a2, 0x002a, 0x02a9, 0x02b0, 0x002a, 0x02b8, 0x02bc, 0x02c4, 0x002a, 0x002a, 0x02cc, 0x02d4, 0x02dc, 0x02e4, 0x02ec, 0x02f4, 0x02fc, 0x0304, 0x030c, 0x002a,
65 0x002a, 0x002a, 0x002a, 0x0314, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x031c, 0x0322, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0326, 0x002a, 0x032d, 0x002a, 0x0043, 0x002a, 0x002a, 0x0335, 0x0339, 0x0341, 0x0341, 0x0341, 0x0347, 0x034d,
66 0x0355, 0x035b, 0x0341, 0x0363, 0x0341, 0x036a, 0x036e, 0x0374, 0x037b, 0x0381, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341,
67 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0388, 0x0390, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0393, 0x039b, 0x017f, 0x002a, 0x002a, 0x002a, 0x002a, 0x03a3, 0x002a, 0x03ab, 0x03b3, 0x03bb, 0x03c3, 0x03cb, 0x03d3,
68 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x002a, 0x002a, 0x002a, 0x03f7, 0x03ff, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x03ff, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x03ff, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x03ff, 0x0400, 0x0401,
69 0x0402, 0x0403, 0x0404, 0x0405, 0x03ff, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x03ff, 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x040c, 0x0414, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
70 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc,
71 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x041c, 0x002a, 0x002a, 0x002a, 0x002a,
72 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0424, 0x042a, 0x002a, 0x0430, 0x0355, 0x0438, 0x043d, 0x0441, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0449, 0x002a, 0x002a, 0x002a, 0x0451, 0x002a, 0x0456, 0x002a, 0x002a, 0x002a,
73 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x045e, 0x002a, 0x002a, 0x01f1, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0466, 0x046b, 0x002a, 0x002a, 0x002a,
74 0x002a, 0x0471, 0x0477, 0x002a, 0x00a7, 0x047f, 0x002a, 0x0487, 0x048f, 0x0497, 0x049f, 0x04a7, 0x04af, 0x04b7, 0x04bf, 0x04c2, 0x04ca, 0x002a, 0x04cf, 0x04d7, 0x04df, 0x04e6, 0x04ee, 0x04f3, 0x04fb, 0x04ff, 0x0507, 0x002a, 0x002a, 0x050a, 0x0512, 0x0516,
75 0x051e, 0x0521, 0x002a, 0x0528, 0x002a, 0x002a, 0x002a, 0x052e, 0x002a, 0x002a, 0x002a, 0x0536, 0x053e, 0x002a, 0x0544, 0x054c, 0x0554, 0x055c, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0560, 0x002a, 0x0568, 0x002a, 0x056f, 0x0577, 0x057e, 0x002a, 0x002a,
76 0x002a, 0x002a, 0x0581, 0x0589, 0x0591, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0595, 0x059d, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
77 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x05a2, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
78 0x002a, 0x05a8, 0x05af, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x05b6, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x05bd, 0x05c4, 0x05c8, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341,
79 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x05d0, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341,
80 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x05d8, 0x05e0, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
81 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x05e2, 0x0341, 0x0341, 0x0341, 0x0341, 0x05ea, 0x05f1, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x05f7, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
82 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x05ff, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
83 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0607, 0x060f, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0613, 0x061b, 0x002a, 0x002a, 0x0623, 0x002a, 0x002a, 0x0341, 0x062b, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
84 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0633, 0x063b, 0x0643, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
85 0x002a, 0x002a, 0x064b, 0x002a, 0x0652, 0x002a, 0x05af, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0655, 0x065b, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x065b, 0x002a, 0x002a, 0x002a, 0x0661, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a,
86 0x002a, 0x002a, 0x0667, 0x002a, 0x066f, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x002a, 0x0677,
87 0x0678, 0x0678, 0x067f, 0x0687, 0x068d, 0x0695, 0x069b, 0x06a3, 0x06ab, 0x0678, 0x0678, 0x06b3, 0x06ba, 0x06c2, 0x06c9, 0x06d1, 0x06d9, 0x06da, 0x06db, 0x06e3, 0x06eb, 0x06f3, 0x06f8, 0x06da, 0x0700, 0x06da, 0x0708, 0x002a, 0x0710, 0x002a, 0x0718, 0x0720,
88 0x0727, 0x072e, 0x0678, 0x0736, 0x073e, 0x06da, 0x06da, 0x0678, 0x0746, 0x074e, 0x0756, 0x002a, 0x002a, 0x002a, 0x002a, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x0678, 0x075e, 0x0341,
89 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0341, 0x0342, 0x0766,
90 0x0047, 0x076e, 0x076e, 0x0047, 0x0047, 0x0047, 0x0776, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e,
91 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x076e, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc,
92 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x02bc, 0x077e,
93};
94static const uint16_t s_stage2[] = {
95 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0008, 0x0008, 0x0008,
96 0x0008, 0x0008, 0x0008, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000,
97 0x0011, 0x0018, 0x0020, 0x0022, 0x002a, 0x0008, 0x0029, 0x0030,
98 0x0036, 0x003e, 0x0040, 0x0047, 0x004c, 0x0008, 0x004a, 0x002d,
99 0x004e, 0x002d, 0x0053, 0x0029, 0x005b, 0x0063, 0x0034, 0x0008,
100 0x004e, 0x002d, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
101 0x0008, 0x0008, 0x002a, 0x006b, 0x0049, 0x0008, 0x0008, 0x0008,
102 0x0008, 0x004c, 0x0008, 0x004c, 0x0008, 0x0008, 0x0008, 0x0072,
103 0x005a, 0x0079, 0x0081, 0x0008, 0x0008, 0x0008, 0x0008, 0x0089,
104 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089, 0x0008,
105 0x0008, 0x0091, 0x0092, 0x0098, 0x0028, 0x0091, 0x0092, 0x0098,
106 0x0028, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x004c,
107 0x0008, 0x0092, 0x0092, 0x0092, 0x0092, 0x0092, 0x0092, 0x004c,
108 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a0, 0x00a6, 0x0008,
109 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00ad, 0x0089, 0x0089,
110 0x0089, 0x0089, 0x00af, 0x00b5, 0x0008, 0x0008, 0x0008, 0x0008,
111 0x0008, 0x0008, 0x0008, 0x00bd, 0x0008, 0x0089, 0x00c5, 0x0008,
112 0x0008, 0x0008, 0x0008, 0x00a0, 0x0089, 0x0089, 0x0008, 0x0008,
113 0x00cd, 0x0008, 0x0008, 0x00a8, 0x00d5, 0x00dc, 0x00e3, 0x0008,
114 0x0008, 0x00e9, 0x00cc, 0x0008, 0x0008, 0x0008, 0x0089, 0x0089,
115 0x00a5, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a8,
116 0x0089, 0x00cd, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a0,
117 0x00a4, 0x00f1, 0x0008, 0x0008, 0x00a8, 0x00f9, 0x00fd, 0x00a2,
118 0x0008, 0x0008, 0x0008, 0x0101, 0x0008, 0x0008, 0x0008, 0x0008,
119 0x0109, 0x0089, 0x0008, 0x0008, 0x0008, 0x0008, 0x00ac, 0x0089,
120 0x0089, 0x0110, 0x0089, 0x0089, 0x0089, 0x0115, 0x0008, 0x0119,
121 0x011e, 0x011e, 0x011e, 0x011e, 0x0124, 0x012b, 0x0132, 0x00ad,
122 0x011e, 0x013a, 0x0008, 0x0008, 0x011e, 0x0141, 0x0008, 0x0119,
123 0x011e, 0x011e, 0x0149, 0x0150, 0x0156, 0x015d, 0x0164, 0x016a,
124 0x0172, 0x013a, 0x0008, 0x0179, 0x017b, 0x0182, 0x0008, 0x0008,
125 0x0008, 0x0008, 0x0008, 0x0008, 0x0186, 0x018d, 0x0194, 0x00cc,
126 0x0008, 0x0008, 0x0008, 0x0198, 0x0008, 0x0182, 0x0008, 0x0119,
127 0x011e, 0x011e, 0x0149, 0x01a0, 0x0156, 0x01a8, 0x01af, 0x0008,
128 0x0008, 0x013a, 0x0008, 0x0008, 0x01b6, 0x0141, 0x0008, 0x0119,
129 0x011e, 0x011e, 0x0149, 0x01a0, 0x01be, 0x015d, 0x0164, 0x01c6,
130 0x0172, 0x013a, 0x0008, 0x01ce, 0x0008, 0x00cb, 0x0008, 0x0008,
131 0x0008, 0x0008, 0x0008, 0x0008, 0x01d0, 0x01d8, 0x01df, 0x016a,
132 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x01e7, 0x0008, 0x0119,
133 0x011e, 0x011e, 0x0149, 0x011e, 0x01ef, 0x01f6, 0x01fd, 0x0203,
134 0x020b, 0x013a, 0x0008, 0x0008, 0x0008, 0x0141, 0x0008, 0x0008,
135 0x0008, 0x0008, 0x0008, 0x0008, 0x020f, 0x0217, 0x021e, 0x0224,
136 0x0008, 0x013a, 0x0008, 0x016e, 0x0008, 0x022c, 0x0008, 0x0119,
137 0x011e, 0x011e, 0x011e, 0x011e, 0x0234, 0x023b, 0x0242, 0x016a,
138 0x0008, 0x013a, 0x0008, 0x0008, 0x0008, 0x0141, 0x0008, 0x0008,
139 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0249, 0x0250, 0x0258,
140 0x0008, 0x0008, 0x0260, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
141 0x0008, 0x0267, 0x00a5, 0x00ce, 0x008a, 0x0008, 0x0008, 0x0008,
142 0x0008, 0x0008, 0x0008, 0x0267, 0x00a3, 0x0008, 0x008a, 0x0008,
143 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a6, 0x0008, 0x0008,
144 0x017c, 0x024a, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
145 0x00ad, 0x012c, 0x00b0, 0x00a9, 0x0089, 0x00ad, 0x0089, 0x0089,
146 0x0089, 0x00a3, 0x017b, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
147 0x0008, 0x0008, 0x00a9, 0x026e, 0x0276, 0x0008, 0x0008, 0x01d0,
148 0x027b, 0x00cd, 0x0008, 0x00e4, 0x0008, 0x0283, 0x00f1, 0x0008,
149 0x00f1, 0x0008, 0x0008, 0x0008, 0x0008, 0x028b, 0x028b, 0x028b,
150 0x028b, 0x028b, 0x028b, 0x028b, 0x028b, 0x0293, 0x0293, 0x0293,
151 0x0293, 0x0293, 0x029b, 0x029b, 0x029b, 0x029b, 0x029b, 0x029b,
152 0x029b, 0x029b, 0x0008, 0x0008, 0x0008, 0x00a9, 0x0008, 0x0008,
153 0x0008, 0x0008, 0x02a3, 0x0008, 0x0008, 0x0008, 0x02a9, 0x0008,
154 0x0008, 0x013a, 0x0008, 0x0008, 0x0008, 0x013a, 0x0008, 0x0008,
155 0x0008, 0x0008, 0x0008, 0x0008, 0x02ae, 0x012d, 0x02b6, 0x012b,
156 0x00a4, 0x00f1, 0x0008, 0x0008, 0x0008, 0x0008, 0x02be, 0x0008,
157 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0203, 0x0008, 0x0008,
158 0x0008, 0x0008, 0x00cc, 0x0008, 0x0008, 0x0008, 0x0008, 0x02c5,
159 0x02cc, 0x02d4, 0x02db, 0x0008, 0x0008, 0x00ce, 0x02e3, 0x0008,
160 0x0008, 0x0008, 0x0008, 0x02e7, 0x008a, 0x02ef, 0x012e, 0x02f7,
161 0x00dc, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0089,
162 0x0089, 0x008a, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
163 0x0114, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x02ff, 0x0305,
164 0x01d6, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a0, 0x00a4, 0x0008,
165 0x0116, 0x0008, 0x0008, 0x0008, 0x030d, 0x0315, 0x0008, 0x0008,
166 0x0008, 0x0008, 0x031b, 0x0323, 0x022c, 0x0008, 0x0008, 0x0008,
167 0x0008, 0x032b, 0x032f, 0x030f, 0x0008, 0x0008, 0x0334, 0x0089,
168 0x026e, 0x018f, 0x033c, 0x00a6, 0x0008, 0x0344, 0x034c, 0x0351,
169 0x0022, 0x0359, 0x0361, 0x0367, 0x0008, 0x036e, 0x0008, 0x0008,
170 0x0376, 0x037c, 0x002c, 0x007a, 0x0025, 0x0008, 0x0008, 0x0008,
171 0x0008, 0x002c, 0x0008, 0x0008, 0x0089, 0x0089, 0x0089, 0x0089,
172 0x00cd, 0x0008, 0x0384, 0x004c, 0x0073, 0x0008, 0x038b, 0x002d,
173 0x0008, 0x036e, 0x0008, 0x0008, 0x0033, 0x0060, 0x0092, 0x0026,
174 0x0092, 0x0028, 0x0008, 0x004c, 0x0393, 0x0399, 0x0008, 0x03a0,
175 0x0008, 0x0028, 0x0008, 0x0008, 0x03a6, 0x0008, 0x007a, 0x0008,
176 0x0008, 0x0008, 0x0040, 0x03ae, 0x03a9, 0x03b3, 0x0068, 0x03b8,
177 0x007d, 0x0032, 0x0008, 0x03be, 0x002e, 0x0008, 0x03c6, 0x03c4,
178 0x0008, 0x0008, 0x03c4, 0x0008, 0x002b, 0x004c, 0x002b, 0x0008,
179 0x0008, 0x007a, 0x0008, 0x0008, 0x002e, 0x03ce, 0x0008, 0x03d6,
180 0x0008, 0x0008, 0x03de, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
181 0x0008, 0x03df, 0x0008, 0x0008, 0x0008, 0x03e7, 0x03ef, 0x03f7,
182 0x0008, 0x0008, 0x0008, 0x0008, 0x0092, 0x0092, 0x0092, 0x0092,
183 0x0092, 0x0092, 0x0092, 0x0092, 0x03ff, 0x0092, 0x0092, 0x0092,
184 0x0092, 0x0098, 0x0092, 0x0092, 0x0008, 0x0008, 0x0008, 0x0008,
185 0x0098, 0x0405, 0x040b, 0x0032, 0x0411, 0x0418, 0x0028, 0x0008,
186 0x034d, 0x007a, 0x0008, 0x0420, 0x0428, 0x042f, 0x0437, 0x043d,
187 0x0444, 0x0444, 0x044c, 0x0444, 0x0441, 0x044c, 0x0450, 0x0444,
188 0x0458, 0x045b, 0x0444, 0x0445, 0x0463, 0x0469, 0x0471, 0x0475,
189 0x0473, 0x047d, 0x0444, 0x0481, 0x0482, 0x0488, 0x048a, 0x048f,
190 0x045f, 0x048c, 0x0495, 0x049b, 0x04a3, 0x047d, 0x04ab, 0x03d9,
191 0x036e, 0x04b3, 0x039e, 0x002b, 0x04b7, 0x04bf, 0x04c6, 0x0008,
192 0x04ce, 0x0008, 0x004e, 0x0092, 0x0008, 0x0008, 0x04d6, 0x0008,
193 0x036e, 0x0008, 0x04b3, 0x04de, 0x0008, 0x0008, 0x0008, 0x0008,
194 0x0008, 0x0008, 0x039d, 0x0008, 0x04e6, 0x0008, 0x0008, 0x04ee,
195 0x0008, 0x0008, 0x0008, 0x0008, 0x04f2, 0x0028, 0x0008, 0x0008,
196 0x0008, 0x0008, 0x0008, 0x00ce, 0x00a6, 0x0008, 0x0008, 0x0008,
197 0x0008, 0x0008, 0x0008, 0x0008, 0x00ce, 0x04fa, 0x04fa, 0x04fa,
198 0x0500, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x0504,
199 0x0008, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa,
200 0x04fa, 0x050c, 0x0008, 0x0008, 0x0008, 0x04fa, 0x04fa, 0x04fa,
201 0x04fa, 0x04fa, 0x0514, 0x051c, 0x051f, 0x0526, 0x04fa, 0x04fa,
202 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fb, 0x052e, 0x04fa,
203 0x04fa, 0x04fa, 0x04fa, 0x0536, 0x04fa, 0x04fa, 0x04fa, 0x04fa,
204 0x04fa, 0x0526, 0x04fa, 0x04fb, 0x04fa, 0x04fa, 0x04fa, 0x04fa,
205 0x04fa, 0x04fa, 0x050c, 0x053e, 0x04fa, 0x04fa, 0x04fa, 0x04fb,
206 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x0092, 0x04fa, 0x04fa, 0x04fa,
207 0x04fa, 0x04fa, 0x04fa, 0x051d, 0x0545, 0x04fa, 0x04fa, 0x04fa,
208 0x04fa, 0x0503, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa,
209 0x04fb, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
210 0x00ce, 0x0334, 0x054d, 0x0008, 0x0008, 0x0008, 0x00a8, 0x0008,
211 0x0008, 0x0008, 0x0008, 0x0553, 0x00ca, 0x0008, 0x0008, 0x055a,
212 0x0562, 0x0008, 0x0008, 0x056a, 0x0008, 0x0008, 0x0008, 0x0008,
213 0x0008, 0x032b, 0x0258, 0x0572, 0x0008, 0x0008, 0x0008, 0x0089,
214 0x0089, 0x00a6, 0x00ce, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a8,
215 0x054d, 0x0008, 0x0008, 0x00ce, 0x0089, 0x022c, 0x0008, 0x028b,
216 0x028b, 0x028b, 0x057a, 0x0115, 0x0008, 0x0008, 0x0008, 0x0008,
217 0x0008, 0x057f, 0x0585, 0x058c, 0x0008, 0x0008, 0x0008, 0x00f1,
218 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0593, 0x059a, 0x0008,
219 0x00ca, 0x05a1, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0562,
220 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x05a9, 0x01c5,
221 0x00cc, 0x0008, 0x0008, 0x0008, 0x0008, 0x05b1, 0x05b9, 0x0008,
222 0x0008, 0x0008, 0x0008, 0x01d3, 0x05c1, 0x0008, 0x0008, 0x05c9,
223 0x05ca, 0x05ca, 0x05ce, 0x05ca, 0x05ca, 0x05ca, 0x05c9, 0x05ca,
224 0x05ca, 0x05ce, 0x05ca, 0x05ca, 0x05ca, 0x05c9, 0x05ca, 0x05ca,
225 0x05d3, 0x0008, 0x0293, 0x0293, 0x05db, 0x05e2, 0x029b, 0x029b,
226 0x029b, 0x029b, 0x029b, 0x05e6, 0x0008, 0x0008, 0x0008, 0x017b,
227 0x0008, 0x0008, 0x0008, 0x0008, 0x0089, 0x0089, 0x04fa, 0x053c,
228 0x0089, 0x0089, 0x04fa, 0x04fa, 0x04ff, 0x04fa, 0x04fb, 0x0504,
229 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x05ea,
230 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x053d, 0x0008, 0x0008, 0x0008,
231 0x01d0, 0x0008, 0x0008, 0x0008, 0x0008, 0x04fb, 0x0008, 0x0000,
232 0x05f2, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
233 0x00f1, 0x0008, 0x0008, 0x0008, 0x0008, 0x00cd, 0x0008, 0x0008,
234 0x0008, 0x0008, 0x0008, 0x0008, 0x00a8, 0x00a5, 0x05f9, 0x00aa,
235 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x02dc, 0x0008, 0x0008,
236 0x0008, 0x0008, 0x00aa, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
237 0x00a2, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0600, 0x0008,
238 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00aa, 0x0606,
239 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x060e,
240 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0089, 0x008a,
241 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0616, 0x00ce, 0x0116,
242 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x061e, 0x0625, 0x00cb,
243 0x00eb, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a5,
244 0x0008, 0x0008, 0x0008, 0x00ce, 0x026b, 0x00a3, 0x0008, 0x0224,
245 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00ca, 0x0008, 0x0116,
246 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x061b, 0x012c, 0x062d,
247 0x0634, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x063c,
248 0x0643, 0x017b, 0x00cc, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
249 0x0008, 0x0008, 0x00ce, 0x02f7, 0x00a5, 0x0008, 0x0008, 0x022c,
250 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x064b, 0x0653,
251 0x0657, 0x016a, 0x0008, 0x065d, 0x00a3, 0x00a3, 0x0008, 0x0008,
252 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x02f7, 0x0664, 0x066b,
253 0x0673, 0x0008, 0x067a, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
254 0x0008, 0x056d, 0x0089, 0x0682, 0x0008, 0x0008, 0x017b, 0x0008,
255 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x02f7, 0x068a, 0x0691,
256 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x016a,
257 0x015c, 0x0699, 0x00cd, 0x0008, 0x0008, 0x027d, 0x0008, 0x0008,
258 0x0008, 0x0008, 0x0008, 0x0008, 0x02f7, 0x06a0, 0x00cd, 0x0008,
259 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x06a8, 0x0594,
260 0x0008, 0x0008, 0x0008, 0x031c, 0x06b0, 0x00a4, 0x0008, 0x0008,
261 0x0008, 0x0008, 0x0008, 0x063c, 0x0089, 0x0221, 0x0008, 0x0008,
262 0x0008, 0x0008, 0x0008, 0x0008, 0x06b8, 0x06bf, 0x06c7, 0x0008,
263 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x061d, 0x06cd,
264 0x06d5, 0x0008, 0x0008, 0x0008, 0x00ad, 0x00a5, 0x0008, 0x0008,
265 0x0008, 0x0008, 0x00a0, 0x06dd, 0x00ce, 0x0008, 0x0593, 0x02db,
266 0x0008, 0x0008, 0x0008, 0x0008, 0x06e4, 0x06ea, 0x012c, 0x00a6,
267 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x016a, 0x008a, 0x0594,
268 0x0008, 0x0008, 0x00ac, 0x0089, 0x0089, 0x06f2, 0x06f9, 0x0008,
269 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0700, 0x0707, 0x070e,
270 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0716,
271 0x071e, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0726,
272 0x0008, 0x072e, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x024c,
273 0x0736, 0x073e, 0x0008, 0x0008, 0x00cb, 0x0008, 0x0008, 0x0008,
274 0x0008, 0x0008, 0x0008, 0x037c, 0x037c, 0x00a7, 0x0089, 0x054d,
275 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a8, 0x0089, 0x02f5,
276 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a3, 0x0008,
277 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x008a, 0x0008, 0x0008,
278 0x0008, 0x0008, 0x0743, 0x074a, 0x0008, 0x0008, 0x00ce, 0x0257,
279 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x00ce, 0x00a5, 0x0008,
280 0x0008, 0x0008, 0x0008, 0x0008, 0x0752, 0x0008, 0x075a, 0x0008,
281 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x0008,
282 0x04fa, 0x04fa, 0x050c, 0x0008, 0x0008, 0x0008, 0x0008, 0x053e,
283 0x04fa, 0x053d, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
284 0x04fe, 0x0762, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x0533, 0x0008,
285 0x0769, 0x0008, 0x0008, 0x0771, 0x0008, 0x0508, 0x0008, 0x04fa,
286 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x04fa, 0x0504, 0x0008,
287 0x0008, 0x0008, 0x0203, 0x0779, 0x0008, 0x0008, 0x0008, 0x0089,
288 0x0089, 0x0089, 0x0089, 0x0089, 0x054d, 0x0089, 0x0089, 0x008a,
289 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x01d1,
290 0x0619, 0x0781, 0x0786, 0x078b, 0x00a4, 0x0008, 0x0008, 0x0008,
291 0x0606, 0x0008, 0x0008, 0x0195, 0x0008, 0x0008, 0x0008, 0x0008,
292 0x0008, 0x0008, 0x0008, 0x04fa, 0x04fa, 0x04fb, 0x0008, 0x04fa,
293 0x04fa, 0x04fb, 0x0008, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089,
294 0x0089, 0x008a, 0x00a0, 0x0089, 0x0089, 0x0089, 0x0089, 0x0089,
295 0x00a3, 0x00f1, 0x0008, 0x0562, 0x0008, 0x0008, 0x00a0, 0x00ad,
296 0x0089, 0x0008, 0x0008, 0x008a, 0x0089, 0x0089, 0x078d, 0x00b3,
297 0x00a5, 0x0008, 0x0008, 0x00ce, 0x0008, 0x0008, 0x0008, 0x0008,
298 0x0008, 0x0008, 0x017b, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
299 0x00aa, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00a8, 0x0008,
300 0x0008, 0x008a, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x00aa,
301 0x00a5, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0795,
302 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444,
303 0x0445, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0092,
304 0x079d, 0x0092, 0x0092, 0x0092, 0x07a5, 0x0092, 0x0092, 0x0092,
305 0x0092, 0x0092, 0x07ad, 0x07b5, 0x07b7, 0x0092, 0x07bf, 0x07c6,
306 0x07cb, 0x0092, 0x07ce, 0x0444, 0x0444, 0x0444, 0x0444, 0x07d3,
307 0x07d9, 0x07d9, 0x07d9, 0x07e1, 0x0444, 0x04fa, 0x07e9, 0x04fa,
308 0x051d, 0x07ef, 0x07f4, 0x04fa, 0x07f7, 0x07ff, 0x0444, 0x044e,
309 0x0444, 0x0444, 0x0444, 0x044c, 0x044c, 0x044c, 0x044c, 0x0800,
310 0x0447, 0x0808, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c,
311 0x044c, 0x0809, 0x044c, 0x044c, 0x0450, 0x0444, 0x044c, 0x044c,
312 0x044c, 0x044c, 0x080f, 0x0450, 0x0444, 0x044c, 0x044c, 0x0816,
313 0x081e, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c,
314 0x044d, 0x0826, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c,
315 0x044c, 0x044c, 0x0829, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c,
316 0x044c, 0x044c, 0x0830, 0x039b, 0x0838, 0x044c, 0x044c, 0x044c,
317 0x0444, 0x0444, 0x0472, 0x0444, 0x0444, 0x07fa, 0x0444, 0x0795,
318 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0449,
319 0x044c, 0x044c, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
320 0x044e, 0x0795, 0x082b, 0x0448, 0x0444, 0x07fc, 0x0448, 0x044f,
321 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0840, 0x0444,
322 0x0008, 0x0008, 0x04e6, 0x0444, 0x044c, 0x0450, 0x0800, 0x0444,
323 0x0008, 0x0840, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
324 0x0444, 0x0008, 0x0842, 0x0008, 0x0008, 0x0008, 0x0008, 0x0444,
325 0x0008, 0x0008, 0x0008, 0x039b, 0x0444, 0x0444, 0x0008, 0x084a,
326 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x084f, 0x0853, 0x044c,
327 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x0444, 0x0444,
328 0x0444, 0x0444, 0x0444, 0x0444, 0x044c, 0x044f, 0x044c, 0x047f,
329 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044c, 0x044d, 0x0446,
330 0x044c, 0x0829, 0x044c, 0x07ff, 0x044c, 0x0800, 0x0444, 0x0444,
331 0x0444, 0x0444, 0x0444, 0x0444, 0x0444, 0x0463, 0x085b, 0x0000,
332 0x0000, 0x0000, 0x0089, 0x0089, 0x0089, 0x0089, 0x0000, 0x0000,
333 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0089, 0x0089,
334 0x0089, 0x0089, 0x0089, 0x0089, 0x0000, 0x0000, 0x0092, 0x0092,
335 0x0092, 0x0092, 0x0092, 0x0092, 0x0092, 0x0863,
336};
337static const uint8_t s_stage3[] = {
338 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
339 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
340 0x41, 0x40, 0xc0, 0x40, 0x40, 0xc0, 0x40, 0x40,
341 0xc0, 0x4c, 0xc0, 0x40, 0x40, 0x01, 0xcc, 0x40,
342 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0, 0xc0,
343 0xc0, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
344 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0,
345 0x40, 0x40, 0x40, 0x40, 0xc0, 0x40, 0xc0, 0xc0,
346 0xc0, 0x40, 0xc0, 0xc0, 0x40, 0x40, 0x40, 0xc0,
347 0xc0, 0xc0, 0x40, 0xc0, 0x40, 0xc0, 0x40, 0x40,
348 0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0x40,
349 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0x40, 0xc0,
350 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0x40,
351 0xc0, 0x40, 0x40, 0xc0, 0x40, 0xc0, 0x40, 0xc0,
352 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xc0, 0x40,
353 0x40, 0xc0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
354 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0, 0x40,
355 0xc0, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
356 0x02, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
357 0xc0, 0xc0, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
358 0x40, 0x40, 0x40, 0x02, 0x02, 0x02, 0x02, 0x02,
359 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02,
360 0x02, 0x02, 0x02, 0x02, 0x02, 0x40, 0x02, 0x02,
361 0x40, 0x02, 0x02, 0x40, 0x02, 0x04, 0x04, 0x04,
362 0x04, 0x04, 0x04, 0x40, 0x40, 0x02, 0x02, 0x02,
363 0x40, 0x01, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40,
364 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x02,
365 0x02, 0x02, 0x04, 0x40, 0x02, 0x02, 0x02, 0x02,
366 0x02, 0x40, 0x40, 0x02, 0x40, 0x02, 0x02, 0x02,
367 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
368 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40,
369 0x40, 0x02, 0x02, 0x40, 0x02, 0x02, 0x02, 0x02,
370 0x02, 0x40, 0x02, 0x02, 0x02, 0x40, 0x40, 0x40,
371 0x40, 0x04, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40,
372 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02,
373 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x4b,
374 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x02, 0x42,
375 0x02, 0x40, 0x42, 0x42, 0x02, 0x02, 0x02, 0x02,
376 0x02, 0x02, 0x02, 0x42, 0x42, 0x42, 0x42, 0x0a,
377 0x42, 0x42, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40,
378 0x40, 0x40, 0x02, 0x42, 0x42, 0x40, 0x40, 0x40,
379 0x40, 0x4b, 0x40, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b,
380 0x4b, 0x40, 0x4b, 0x40, 0x40, 0x40, 0x4b, 0x4b,
381 0x40, 0x40, 0x02, 0x40, 0x42, 0x42, 0x02, 0x02,
382 0x02, 0x02, 0x40, 0x40, 0x42, 0x40, 0x40, 0x42,
383 0x42, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
384 0x40, 0x42, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x4b,
385 0x40, 0x4b, 0x4b, 0x40, 0x40, 0x40, 0x40, 0x40,
386 0x40, 0x02, 0x40, 0x02, 0x02, 0x42, 0x40, 0x40,
387 0x40, 0x40, 0x02, 0x40, 0x42, 0x42, 0x02, 0x02,
388 0x40, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40, 0x02,
389 0x02, 0x02, 0x40, 0x40, 0x40, 0x02, 0x40, 0x40,
390 0x4b, 0x40, 0x4b, 0x4b, 0x40, 0x4b, 0x4b, 0x4b,
391 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40, 0x02,
392 0x42, 0x40, 0x42, 0x42, 0x0a, 0x40, 0x40, 0x4b,
393 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x4b, 0x4b,
394 0x40, 0x40, 0x02, 0x40, 0x42, 0x02, 0x40, 0x40,
395 0x40, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x4b,
396 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x42,
397 0x02, 0x42, 0x42, 0x40, 0x40, 0x40, 0x42, 0x42,
398 0x40, 0x42, 0x42, 0x42, 0x02, 0x40, 0x40, 0x02,
399 0x42, 0x42, 0x42, 0x02, 0x40, 0x40, 0x40, 0x4b,
400 0x4b, 0x40, 0x40, 0x02, 0x40, 0x02, 0x02, 0x42,
401 0x42, 0x42, 0x42, 0x40, 0x02, 0x02, 0x40, 0x02,
402 0x02, 0x02, 0x0a, 0x40, 0x40, 0x40, 0x40, 0x40,
403 0x02, 0x02, 0x40, 0x4b, 0x4b, 0x4b, 0x40, 0x40,
404 0x40, 0x40, 0x40, 0x02, 0x40, 0x42, 0x02, 0x42,
405 0x42, 0x42, 0x42, 0x42, 0x40, 0x02, 0x42, 0x40,
406 0x42, 0x42, 0x02, 0x02, 0x40, 0x40, 0x40, 0x40,
407 0x40, 0x42, 0x42, 0x40, 0x02, 0x02, 0x42, 0x42,
408 0x40, 0x40, 0x40, 0x40, 0x4b, 0x4b, 0x4b, 0x02,
409 0x02, 0x40, 0x42, 0x42, 0x02, 0x02, 0x02, 0x02,
410 0x40, 0x42, 0x42, 0x40, 0x42, 0x42, 0x42, 0x0a,
411 0x44, 0x40, 0x40, 0x02, 0x40, 0x40, 0x40, 0x40,
412 0x42, 0x42, 0x02, 0x02, 0x02, 0x40, 0x02, 0x40,
413 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
414 0x40, 0x40, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40,
415 0x02, 0x40, 0x42, 0x02, 0x02, 0x02, 0x02, 0x42,
416 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40, 0x02,
417 0x02, 0x42, 0x42, 0x02, 0x02, 0x40, 0x40, 0x40,
418 0x40, 0x02, 0x02, 0x40, 0x40, 0x02, 0x40, 0x42,
419 0x02, 0x02, 0x40, 0x85, 0x85, 0x85, 0x85, 0x85,
420 0x85, 0x85, 0x85, 0x46, 0x46, 0x46, 0x46, 0x46,
421 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47,
422 0x47, 0x47, 0x47, 0x40, 0x40, 0x02, 0x02, 0x02,
423 0x42, 0x40, 0x40, 0x02, 0x02, 0x42, 0x40, 0x40,
424 0x40, 0x40, 0x02, 0x02, 0x42, 0x02, 0x42, 0x42,
425 0x42, 0x42, 0x42, 0x42, 0x02, 0x42, 0x40, 0x40,
426 0x40, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02,
427 0x42, 0x42, 0x42, 0x42, 0x02, 0x42, 0x42, 0x42,
428 0x40, 0x40, 0x40, 0x40, 0x42, 0x42, 0x02, 0x42,
429 0x42, 0x42, 0x42, 0x42, 0x02, 0x02, 0x02, 0x40,
430 0x40, 0x40, 0x40, 0x02, 0x42, 0x42, 0x02, 0x40,
431 0x40, 0x40, 0x40, 0x40, 0x42, 0x02, 0x42, 0x02,
432 0x40, 0x02, 0x40, 0x40, 0x02, 0x02, 0x02, 0x42,
433 0x42, 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40,
434 0x40, 0x40, 0x40, 0x02, 0x42, 0x02, 0x02, 0x02,
435 0x42, 0x02, 0x42, 0x42, 0x42, 0x40, 0x42, 0x02,
436 0x02, 0x02, 0x02, 0x42, 0x42, 0x02, 0x02, 0x42,
437 0x02, 0x02, 0x02, 0x40, 0x40, 0x40, 0x40, 0x40,
438 0x40, 0x02, 0x42, 0x02, 0x02, 0x42, 0x42, 0x42,
439 0x02, 0x42, 0x02, 0x40, 0x40, 0x40, 0x40, 0x42,
440 0x42, 0x42, 0x42, 0x02, 0x02, 0x02, 0x02, 0x40,
441 0x02, 0x02, 0x02, 0x02, 0x40, 0x40, 0x40, 0x40,
442 0x02, 0x40, 0x40, 0x42, 0x40, 0x40, 0x40, 0x01,
443 0x02, 0x0d, 0x01, 0x01, 0xc0, 0x40, 0x40, 0xc0,
444 0xc0, 0xc0, 0xc0, 0x40, 0x40, 0xc0, 0xc0, 0x40,
445 0x40, 0x41, 0x41, 0x01, 0x01, 0x01, 0x01, 0x01,
446 0x40, 0xc0, 0x40, 0xc0, 0xc0, 0x40, 0xc0, 0x40,
447 0x40, 0x40, 0xc0, 0x4c, 0x40, 0xc0, 0x40, 0x4c,
448 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x01, 0x01,
449 0x01, 0x01, 0x01, 0x41, 0x01, 0x01, 0x01, 0x01,
450 0x01, 0x01, 0x01, 0x01, 0x40, 0x40, 0x40, 0xc0,
451 0x40, 0xc0, 0x40, 0x40, 0xc0, 0xcc, 0x40, 0x40,
452 0x40, 0xc0, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc,
453 0xcc, 0xcc, 0xcc, 0x40, 0x40, 0x40, 0x40, 0x40,
454 0x40, 0x4c, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40,
455 0xc0, 0x40, 0xc0, 0x40, 0x40, 0x40, 0xc0, 0x40,
456 0x40, 0xc0, 0x40, 0x40, 0x40, 0xc0, 0x40, 0x40,
457 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0, 0x40,
458 0x40, 0x40, 0xc0, 0x40, 0x40, 0x40, 0xc0, 0xc0,
459 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40,
460 0x8c, 0x8c, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x80,
461 0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40,
462 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x4c, 0x40,
463 0x8c, 0x8c, 0x8c, 0x8c, 0x4c, 0x4c, 0x4c, 0x8c,
464 0x4c, 0x4c, 0x8c, 0x40, 0x40, 0x40, 0x40, 0x4c,
465 0x4c, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0,
466 0xc0, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x4c,
467 0x4c, 0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0x40,
468 0x40, 0xcc, 0xc0, 0x40, 0x40, 0x40, 0x40, 0xc0,
469 0xc0, 0x40, 0x40, 0xc0, 0x40, 0x40, 0xc0, 0xc0,
470 0x40, 0x40, 0x40, 0x4c, 0x4c, 0x8c, 0x8c, 0x40,
471 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0xcc, 0xc0, 0x4c,
472 0xcc, 0x4c, 0x4c, 0x4c, 0x4c, 0xcc, 0xcc, 0x4c,
473 0x4c, 0x4c, 0x40, 0x8c, 0x8c, 0x4c, 0x4c, 0x4c,
474 0x4c, 0xcc, 0x4c, 0xcc, 0x4c, 0x4c, 0x4c, 0x4c,
475 0x4c, 0x4c, 0x4c, 0x4c, 0x8c, 0x8c, 0x8c, 0x8c,
476 0x8c, 0x8c, 0x8c, 0x8c, 0x4c, 0x4c, 0x4c, 0x4c,
477 0xcc, 0xcc, 0x4c, 0xcc, 0xcc, 0xcc, 0x4c, 0xcc,
478 0xcc, 0x4c, 0xcc, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
479 0x4c, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80,
480 0x80, 0x4c, 0x4c, 0x4c, 0x8c, 0x4c, 0x4c, 0x4c,
481 0x4c, 0x4c, 0x4c, 0xcc, 0xcc, 0x4c, 0x4c, 0x8c,
482 0x8c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x8c, 0x8c,
483 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x8c, 0xcc,
484 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x8c,
485 0x8c, 0xcc, 0x8c, 0xcc, 0xcc, 0x8c, 0xcc, 0xcc,
486 0x8c, 0xcc, 0xcc, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
487 0x8c, 0x40, 0x40, 0x4c, 0x4c, 0x4c, 0x40, 0x4c,
488 0x40, 0x4c, 0x40, 0x8c, 0x40, 0x40, 0x40, 0x40,
489 0x40, 0x40, 0x40, 0x4c, 0x40, 0x40, 0x4c, 0x40,
490 0x40, 0x40, 0x40, 0x8c, 0x40, 0x8c, 0x40, 0x40,
491 0x40, 0x8c, 0x8c, 0x8c, 0x40, 0x8c, 0x40, 0x40,
492 0x40, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x40, 0x40,
493 0x40, 0x40, 0x40, 0x8c, 0x8c, 0x8c, 0x40, 0x40,
494 0x40, 0x40, 0x40, 0x40, 0x40, 0x8c, 0x40, 0x40,
495 0x40, 0x40, 0x40, 0x4c, 0x4c, 0x4c, 0x40, 0x40,
496 0x40, 0x8c, 0x8c, 0x40, 0x40, 0x40, 0x40, 0x8c,
497 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
498 0x80, 0x80, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80,
499 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80,
500 0x80, 0x80, 0x40, 0x40, 0x80, 0x80, 0x02, 0x02,
501 0x02, 0x02, 0x82, 0x82, 0x8c, 0x80, 0x80, 0x80,
502 0x80, 0x80, 0x80, 0x80, 0x8c, 0x80, 0x40, 0x80,
503 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x02,
504 0x02, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0x40,
505 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x40, 0x40,
506 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x8c, 0x80,
507 0x80, 0x80, 0x80, 0x80, 0x80, 0x02, 0x02, 0x02,
508 0x02, 0x02, 0x02, 0x40, 0x40, 0x02, 0x40, 0x40,
509 0x40, 0x02, 0x40, 0x40, 0x40, 0x42, 0x42, 0x02,
510 0x02, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40,
511 0x40, 0x40, 0x42, 0x42, 0x40, 0x40, 0x40, 0x40,
512 0x40, 0x40, 0x42, 0x42, 0x42, 0x42, 0x02, 0x02,
513 0x40, 0x40, 0x85, 0x85, 0x85, 0x85, 0x85, 0x40,
514 0x40, 0x40, 0x02, 0x42, 0x42, 0x02, 0x02, 0x42,
515 0x42, 0x02, 0x02, 0x42, 0x42, 0x40, 0x40, 0x40,
516 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x02, 0x02,
517 0x02, 0x02, 0x42, 0x02, 0x02, 0x42, 0x42, 0x02,
518 0x02, 0x40, 0x40, 0x40, 0x40, 0x02, 0x42, 0x40,
519 0x40, 0x02, 0x40, 0x02, 0x02, 0x02, 0x40, 0x40,
520 0x02, 0x40, 0x40, 0x40, 0x42, 0x02, 0x02, 0x42,
521 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x42, 0x02,
522 0x40, 0x02, 0x42, 0x42, 0x40, 0x42, 0x02, 0x40,
523 0x40, 0x88, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
524 0x89, 0x89, 0x88, 0x89, 0x89, 0x89, 0x89, 0x40,
525 0x40, 0x40, 0x40, 0x46, 0x46, 0x46, 0x46, 0x46,
526 0x46, 0x46, 0x40, 0x40, 0x40, 0x47, 0x47, 0x47,
527 0x47, 0x47, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
528 0x40, 0x01, 0x41, 0x01, 0x01, 0x01, 0x40, 0xc0,
529 0x40, 0x40, 0x02, 0x02, 0x02, 0x40, 0x02, 0x02,
530 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x40,
531 0x02, 0x02, 0x02, 0x02, 0x40, 0x40, 0x42, 0x02,
532 0x42, 0x40, 0x40, 0x40, 0x40, 0x40, 0x02, 0x40,
533 0x40, 0x02, 0x02, 0x40, 0x40, 0x40, 0x42, 0x42,
534 0x42, 0x02, 0x02, 0x02, 0x02, 0x42, 0x02, 0x02,
535 0x40, 0x40, 0x04, 0x40, 0x40, 0x42, 0x40, 0x44,
536 0x44, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02, 0x02,
537 0x02, 0x40, 0x42, 0x02, 0x40, 0x40, 0x40, 0x40,
538 0x42, 0x42, 0x42, 0x02, 0x02, 0x42, 0x42, 0x02,
539 0x42, 0x02, 0x02, 0x40, 0x40, 0x40, 0x02, 0x02,
540 0x40, 0x42, 0x42, 0x02, 0x42, 0x42, 0x42, 0x42,
541 0x40, 0x40, 0x42, 0x42, 0x42, 0x40, 0x40, 0x42,
542 0x42, 0x40, 0x40, 0x02, 0x02, 0x40, 0x42, 0x40,
543 0x40, 0x42, 0x40, 0x42, 0x42, 0x42, 0x40, 0x42,
544 0x42, 0x02, 0x42, 0x02, 0x44, 0x02, 0x40, 0x40,
545 0x40, 0x40, 0x40, 0x02, 0x02, 0x40, 0x40, 0x40,
546 0x40, 0x40, 0x42, 0x42, 0x02, 0x02, 0x02, 0x42,
547 0x02, 0x40, 0x02, 0x42, 0x02, 0x42, 0x42, 0x42,
548 0x42, 0x02, 0x42, 0x02, 0x02, 0x40, 0x40, 0x40,
549 0x40, 0x42, 0x42, 0x42, 0x42, 0x02, 0x02, 0x42,
550 0x02, 0x02, 0x02, 0x42, 0x42, 0x02, 0x42, 0x02,
551 0x40, 0x40, 0x40, 0x02, 0x42, 0x02, 0x42, 0x42,
552 0x40, 0x40, 0x02, 0x02, 0x02, 0x02, 0x42, 0x02,
553 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x40, 0x42,
554 0x40, 0x40, 0x02, 0x02, 0x42, 0x02, 0x44, 0x42,
555 0x44, 0x42, 0x02, 0x40, 0x40, 0x40, 0x40, 0x02,
556 0x02, 0x42, 0x42, 0x42, 0x42, 0x02, 0x40, 0x40,
557 0x40, 0x42, 0x40, 0x40, 0x40, 0x02, 0x42, 0x44,
558 0x02, 0x02, 0x02, 0x02, 0x40, 0x40, 0x40, 0x40,
559 0x44, 0x44, 0x44, 0x44, 0x02, 0x02, 0x02, 0x02,
560 0x02, 0x02, 0x40, 0x42, 0x02, 0x02, 0x02, 0x02,
561 0x02, 0x02, 0x42, 0x02, 0x02, 0x42, 0x02, 0x02,
562 0x40, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40,
563 0x40, 0x02, 0x40, 0x02, 0x02, 0x40, 0x02, 0x02,
564 0x02, 0x02, 0x02, 0x02, 0x44, 0x02, 0x40, 0x40,
565 0x42, 0x42, 0x42, 0x42, 0x42, 0x40, 0x02, 0x02,
566 0x40, 0x42, 0x42, 0x02, 0x42, 0x02, 0x40, 0x40,
567 0x40, 0x02, 0x02, 0x42, 0x42, 0x40, 0x02, 0x02,
568 0x44, 0x42, 0x40, 0x40, 0x40, 0x40, 0x02, 0x02,
569 0x02, 0x40, 0x40, 0x40, 0x42, 0x42, 0x02, 0x42,
570 0x02, 0x40, 0x40, 0x40, 0x40, 0x40, 0x46, 0x40,
571 0x40, 0x40, 0x46, 0x46, 0x46, 0x40, 0x40, 0x40,
572 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x02, 0x40,
573 0x40, 0x40, 0x82, 0x82, 0x40, 0x40, 0x40, 0x40,
574 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40, 0x80,
575 0x80, 0x40, 0x40, 0x80, 0x40, 0x40, 0x40, 0x40,
576 0x40, 0x80, 0x80, 0x80, 0x40, 0x40, 0x80, 0x40,
577 0x40, 0x01, 0x01, 0x01, 0x01, 0x40, 0x40, 0x40,
578 0x40, 0x42, 0x42, 0x42, 0x01, 0x01, 0x01, 0x01,
579 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x40, 0x40,
580 0x02, 0x02, 0x02, 0x02, 0x02, 0x4c, 0x4c, 0x4c,
581 0x4c, 0x8c, 0x4c, 0x4c, 0x4c, 0xc0, 0xc0, 0xc0,
582 0x40, 0x40, 0x4c, 0x4c, 0x4c, 0xc0, 0xc0, 0xc0,
583 0xc0, 0xc0, 0xc0, 0x40, 0x4c, 0xc0, 0xc0, 0x40,
584 0x40, 0x4c, 0x4c, 0x4c, 0x4c, 0xcc, 0xcc, 0xc0,
585 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcc, 0xcc, 0xc0,
586 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x8c, 0xc0, 0x8c,
587 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0xc0, 0xc0,
588 0xc0, 0xc0, 0xc0, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
589 0x4c, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43,
590 0x43, 0x80, 0x8c, 0x8c, 0x4c, 0x4c, 0x4c, 0x4c,
591 0x4c, 0x80, 0x80, 0x8c, 0x80, 0x80, 0x80, 0x80,
592 0x80, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x80,
593 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x8c,
594 0x8c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
595 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x4c, 0x8c,
596 0x8c, 0x8c, 0x4c, 0x4c, 0x4c, 0x4c, 0x8c, 0x4c,
597 0x4c, 0x4c, 0x8c, 0x4c, 0x4c, 0x4c, 0x8c, 0x8c,
598 0x8c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x8c, 0x4c,
599 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x4c, 0x4c,
600 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x40, 0x40,
601 0x4c, 0x4c, 0x4c, 0x8c, 0x8c, 0x8c, 0x8c, 0x4c,
602 0x40, 0x40, 0x40, 0x40, 0x4c, 0x4c, 0x4c, 0x4c,
603 0x4c, 0x4c, 0x40, 0x40, 0x40, 0x40, 0x8c, 0x8c,
604 0x8c, 0x8c, 0x40, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
605 0x8c, 0x40, 0x8c, 0x41, 0x01, 0x41, 0x41, 0x41,
606 0x41, 0x41, 0x41, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
607 0xc0, 0x40, 0x40,
608};
609static const uint32_t s_joinRules[2][16] = {
610 {
611 0x03cfffcf, 0x0fffffff, 0x03cfffcf, 0x03cfff4f,
612 0x0000000c, 0x03c0c3cf, 0x03cf0fcf, 0x03cf3fcf,
613 0x03cf0fcf, 0x03cf3fcf, 0x030fffcf, 0x03cfffcf,
614 0x03cfffcf, 0x00cfffcf, 0x00000000, 0x00000000,
615 },
616 {
617 0x03cfffcf, 0x0fffffff, 0x03cfffcf, 0x03cfffcf,
618 0x0000000c, 0x03c0c3cf, 0x03cf0fcf, 0x03cf3fcf,
619 0x03cf0fcf, 0x03cf3fcf, 0x030fffcf, 0x03cfffcf,
620 0x03cfffcf, 0x00cfffcf, 0x00000000, 0x00000000,
621 },
622};
623static int ucdLookup(const char32_t cp)
624{
625 const uint16_t s0 = s_stage0[cp >> 11];
626 const uint16_t s1 = s_stage1[s0 + ((cp >> 6) & 31)];
627 const uint16_t s2 = s_stage2[s1 + ((cp >> 3) & 7)];
628 const uint8_t s3 = s_stage3[s2 + ((cp >> 0) & 7)];
629 return s3;
630}
631static int ucdGraphemeJoins(const int state, const int lead, const int trail)
632{
633 const int l = lead & 15;
634 const int t = trail & 15;
635 return (s_joinRules[state][l] >> (t * 2)) & 3;
636}
637static bool ucdGraphemeDone(const int state)
638{
639 return state == 3;
640}
641static int ucdToCharacterWidth(const int val)
642{
643 return val >> 6;
644}
645// clang-format on
646// End of generated code
647
648/*
649 * This file is part of mpv.
650 *
651 * mpv is free software; you can redistribute it and/or
652 * modify it under the terms of the GNU Lesser General Public
653 * License as published by the Free Software Foundation; either
654 * version 2.1 of the License, or (at your option) any later version.
655 *
656 * mpv is distributed in the hope that it will be useful,
657 * but WITHOUT ANY WARRANTY; without even the implied warranty of
658 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
659 * GNU Lesser General Public License for more details.
660 *
661 * You should have received a copy of the GNU Lesser General Public
662 * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
663 */
664
665int term_disp_width(bstr str)
666{
667 static const int ambiguous_width = 1;
668
669 int width = 0;
670
671 while (str.len) {
672 if (bstr_eatstart0(&str, "\033[")) {
673 while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm'))
674 str = bstr_cut(str, 1);
675 str = bstr_cut(str, 1);
676 continue;
677 }
678
679 int cp = bstr_decode_utf8(str, &str);
680
681 // Stop processing on any invalid input
682 if (cp < 0)
683 return 0;
684
685 if (cp == '\r') {
686 width = 0;
687 continue;
688 }
689
690 if (cp < 0x20)
691 continue;
692
693 if (cp <= 0x7E) {
694 width++;
695 continue;
696 }
697
698 int grapheme_width = 0;
699 int state = 0;
700
701 while (true) {
702 int lead = ucdLookup(cp);
703 int w = ucdToCharacterWidth(lead);
704 if (w == 3)
705 w = ambiguous_width;
706
707 // U+FE0F Variation Selector-16 is used to turn unqualified Emojis into qualified ones.
708 // By convention, this turns them from being ambiguous width (= narrow) into wide ones.
709 // We achieve this here by explicitly giving this codepoint a wide width.
710 // Later down below we'll clamp width back to <= 2.
711 if (cp == 0xFE0F)
712 w = 2;
713
714 grapheme_width += w;
715
716 if (!str.len)
717 break;
718
719 // Fetch next codepoint in grapheme cluster
720 bstr cluster_end;
721 cp = bstr_decode_utf8(str, &cluster_end);
722 // Stop processing on any invalid input
723 if (cp < 0)
724 return 0;
725 int trail = ucdLookup(cp);
726
727 state = ucdGraphemeJoins(state, lead, trail);
728 if (ucdGraphemeDone(state))
729 break;
730
731 str = cluster_end;
732 }
733 width += grapheme_width > 2 ? 2 : grapheme_width;
734 }
735
736 return width;
737}
misc/codepoint_width.h+11−0
@@ -0,0 +1,11 @@
1#pragma once
2
3#include "misc/bstr.h"
4
5/**
6 * @brief Determines the number of columns required to display a given string.
7 *
8 * @param str Sequence of UTF-8 chars
9 * @return int width of the string
10 */
11int term_disp_width(bstr str);
test/codepoint_width.c+67−0
@@ -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
24int 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}
test/meson.build+5−0
@@ -105,6 +105,11 @@ test('format', format) · 104 unmodified lines
105language = executable('language', files('language.c'), include_directories: incdir, link_with: test_utils)105language = executable('language', files('language.c'), include_directories: incdir, link_with: test_utils)
106test('language', language)106test('language', language)
107 107
108codepoint_width = executable('codepoint-width', files('codepoint_width.c'),
109 objects: libmpv.extract_objects('misc/codepoint_width.c'),
110 include_directories: incdir, link_with: test_utils)
111test('codepoint-width', codepoint_width)
112
108paths_objects = libmpv.extract_objects('options/path.c', path_source)113paths_objects = libmpv.extract_objects('options/path.c', path_source)
109paths = executable('paths', 'paths.c', include_directories: incdir,114paths = executable('paths', 'paths.c', include_directories: incdir,
110 objects: paths_objects, link_with: test_utils)115 objects: paths_objects, link_with: test_utils)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t