Remove old docs directory

This commit is contained in:
00JCIV00 2024-04-04 17:15:04 -04:00 committed by Tim Culverhouse
parent ee13f32b17
commit d117a5f5fa
119 changed files with 0 additions and 100351 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
var guideSections =[{"name":"","guides":[]}];

View file

@ -1 +0,0 @@
var modules =[{"name":"vaxis","file":0,"main":66,"table":{"ziglyph":4,"vaxis":0,"zigimg":2,"builtin":1}},{"name":"builtin","file":0,"main":462,"table":{}},{"name":"zigimg","file":0,"main":32363,"table":{"builtin":3}},{"name":"builtin","file":0,"main":32577,"table":{}},{"name":"ziglyph","file":0,"main":33845,"table":{}}];

View file

@ -1 +0,0 @@
var rootMod =0;

View file

@ -1 +0,0 @@
var typeKinds =["Unanalyzed","Type","Void","Bool","NoReturn","Int","Float","Pointer","Array","Struct","ComptimeExpr","ComptimeFloat","ComptimeInt","Undefined","Null","Optional","ErrorUnion","InferredErrorUnion","ErrorSet","Enum","Union","Fn","Opaque","Frame","AnyFrame","Vector","EnumLiteral"];

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,233 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>builtin.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-comment">/// Zig version. When writing code that supports multiple versions of Zig, prefer</span></span>
<span class="line" id="L3"><span class="tok-comment">/// feature detection (i.e. with `@hasDecl` or `@hasField`) over version checks.</span></span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_version = std.SemanticVersion.parse(zig_version_string) <span class="tok-kw">catch</span> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_version_string = <span class="tok-str">&quot;0.12.0-dev.2824+0b7af2563&quot;</span>;</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> zig_backend = std.builtin.CompilerBackend.stage2_llvm;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> output_mode = std.builtin.OutputMode.Exe;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_mode = std.builtin.LinkMode.Static;</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> is_test = <span class="tok-null">true</span>;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> single_threaded = <span class="tok-null">false</span>;</span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> abi = std.Target.Abi.gnu;</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> cpu: std.Target.Cpu = .{</span>
<span class="line" id="L14"> .arch = .x86_64,</span>
<span class="line" id="L15"> .model = &amp;std.Target.x86.cpu.x86_64,</span>
<span class="line" id="L16"> .features = std.Target.x86.featureSet(&amp;[_]std.Target.x86.Feature{</span>
<span class="line" id="L17"> .@&quot;64bit&quot;,</span>
<span class="line" id="L18"> .adx,</span>
<span class="line" id="L19"> .aes,</span>
<span class="line" id="L20"> .avx,</span>
<span class="line" id="L21"> .avx2,</span>
<span class="line" id="L22"> .bmi,</span>
<span class="line" id="L23"> .bmi2,</span>
<span class="line" id="L24"> .clflushopt,</span>
<span class="line" id="L25"> .clwb,</span>
<span class="line" id="L26"> .cmov,</span>
<span class="line" id="L27"> .cx16,</span>
<span class="line" id="L28"> .cx8,</span>
<span class="line" id="L29"> .f16c,</span>
<span class="line" id="L30"> .fma,</span>
<span class="line" id="L31"> .fsgsbase,</span>
<span class="line" id="L32"> .fxsr,</span>
<span class="line" id="L33"> .gfni,</span>
<span class="line" id="L34"> .idivq_to_divl,</span>
<span class="line" id="L35"> .invpcid,</span>
<span class="line" id="L36"> .lzcnt,</span>
<span class="line" id="L37"> .macrofusion,</span>
<span class="line" id="L38"> .mmx,</span>
<span class="line" id="L39"> .movbe,</span>
<span class="line" id="L40"> .movdir64b,</span>
<span class="line" id="L41"> .movdiri,</span>
<span class="line" id="L42"> .nopl,</span>
<span class="line" id="L43"> .pclmul,</span>
<span class="line" id="L44"> .pconfig,</span>
<span class="line" id="L45"> .pku,</span>
<span class="line" id="L46"> .popcnt,</span>
<span class="line" id="L47"> .prfchw,</span>
<span class="line" id="L48"> .ptwrite,</span>
<span class="line" id="L49"> .rdpid,</span>
<span class="line" id="L50"> .rdrnd,</span>
<span class="line" id="L51"> .rdseed,</span>
<span class="line" id="L52"> .sahf,</span>
<span class="line" id="L53"> .sha,</span>
<span class="line" id="L54"> .shstk,</span>
<span class="line" id="L55"> .slow_3ops_lea,</span>
<span class="line" id="L56"> .slow_incdec,</span>
<span class="line" id="L57"> .sse,</span>
<span class="line" id="L58"> .sse2,</span>
<span class="line" id="L59"> .sse3,</span>
<span class="line" id="L60"> .sse4_1,</span>
<span class="line" id="L61"> .sse4_2,</span>
<span class="line" id="L62"> .ssse3,</span>
<span class="line" id="L63"> .vaes,</span>
<span class="line" id="L64"> .vpclmulqdq,</span>
<span class="line" id="L65"> .vzeroupper,</span>
<span class="line" id="L66"> .waitpkg,</span>
<span class="line" id="L67"> .x87,</span>
<span class="line" id="L68"> .xsave,</span>
<span class="line" id="L69"> .xsavec,</span>
<span class="line" id="L70"> .xsaveopt,</span>
<span class="line" id="L71"> .xsaves,</span>
<span class="line" id="L72"> }),</span>
<span class="line" id="L73">};</span>
<span class="line" id="L74"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> os = std.Target.Os{</span>
<span class="line" id="L75"> .tag = .linux,</span>
<span class="line" id="L76"> .version_range = .{ .linux = .{</span>
<span class="line" id="L77"> .range = .{</span>
<span class="line" id="L78"> .min = .{</span>
<span class="line" id="L79"> .major = <span class="tok-number">5</span>,</span>
<span class="line" id="L80"> .minor = <span class="tok-number">15</span>,</span>
<span class="line" id="L81"> .patch = <span class="tok-number">0</span>,</span>
<span class="line" id="L82"> },</span>
<span class="line" id="L83"> .max = .{</span>
<span class="line" id="L84"> .major = <span class="tok-number">5</span>,</span>
<span class="line" id="L85"> .minor = <span class="tok-number">15</span>,</span>
<span class="line" id="L86"> .patch = <span class="tok-number">0</span>,</span>
<span class="line" id="L87"> },</span>
<span class="line" id="L88"> },</span>
<span class="line" id="L89"> .glibc = .{</span>
<span class="line" id="L90"> .major = <span class="tok-number">2</span>,</span>
<span class="line" id="L91"> .minor = <span class="tok-number">35</span>,</span>
<span class="line" id="L92"> .patch = <span class="tok-number">0</span>,</span>
<span class="line" id="L93"> },</span>
<span class="line" id="L94"> }},</span>
<span class="line" id="L95">};</span>
<span class="line" id="L96"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> target: std.Target = .{</span>
<span class="line" id="L97"> .cpu = cpu,</span>
<span class="line" id="L98"> .os = os,</span>
<span class="line" id="L99"> .abi = abi,</span>
<span class="line" id="L100"> .ofmt = object_format,</span>
<span class="line" id="L101"> .dynamic_linker = std.Target.DynamicLinker.init(<span class="tok-str">&quot;/lib64/ld-linux-x86-64.so.2&quot;</span>),</span>
<span class="line" id="L102">};</span>
<span class="line" id="L103"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> object_format = std.Target.ObjectFormat.elf;</span>
<span class="line" id="L104"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mode = std.builtin.OptimizeMode.Debug;</span>
<span class="line" id="L105"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_libc = <span class="tok-null">false</span>;</span>
<span class="line" id="L106"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> link_libcpp = <span class="tok-null">false</span>;</span>
<span class="line" id="L107"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> have_error_return_tracing = <span class="tok-null">true</span>;</span>
<span class="line" id="L108"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> valgrind_support = <span class="tok-null">true</span>;</span>
<span class="line" id="L109"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sanitize_thread = <span class="tok-null">false</span>;</span>
<span class="line" id="L110"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> position_independent_code = <span class="tok-null">false</span>;</span>
<span class="line" id="L111"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> position_independent_executable = <span class="tok-null">false</span>;</span>
<span class="line" id="L112"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strip_debug_info = <span class="tok-null">false</span>;</span>
<span class="line" id="L113"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> code_model = std.builtin.CodeModel.default;</span>
<span class="line" id="L114"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> omit_frame_pointer = <span class="tok-null">false</span>;</span>
<span class="line" id="L115"><span class="tok-kw">pub</span> <span class="tok-kw">var</span> test_functions: []<span class="tok-kw">const</span> std.builtin.TestFn = <span class="tok-null">undefined</span>; <span class="tok-comment">// overwritten later</span>
</span>
<span class="line" id="L116"></span>
</code></pre></body>
</html>

View file

@ -1,175 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cell.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3">char: Character = .{},</span>
<span class="line" id="L4">style: Style = .{},</span>
<span class="line" id="L5">link: Hyperlink = .{},</span>
<span class="line" id="L6">image: ?Image.Placement = <span class="tok-null">null</span>,</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Segment is a contiguous run of text that has a constant style</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Segment = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L10"> text: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L11"> style: Style = .{},</span>
<span class="line" id="L12"> link: Hyperlink = .{},</span>
<span class="line" id="L13">};</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Character = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L16"> grapheme: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot; &quot;</span>,</span>
<span class="line" id="L17"> <span class="tok-comment">/// width should only be provided when the application is sure the terminal</span></span>
<span class="line" id="L18"> <span class="tok-comment">/// will measure the same width. This can be ensure by using the gwidth method</span></span>
<span class="line" id="L19"> <span class="tok-comment">/// included in libvaxis. If width is 0, libvaxis will measure the glyph at</span></span>
<span class="line" id="L20"> <span class="tok-comment">/// render time</span></span>
<span class="line" id="L21"> width: <span class="tok-type">usize</span> = <span class="tok-number">1</span>,</span>
<span class="line" id="L22">};</span>
<span class="line" id="L23"></span>
<span class="line" id="L24"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Hyperlink = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L25"> uri: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot;&quot;</span>,</span>
<span class="line" id="L26"> <span class="tok-comment">/// ie &quot;id=app-1234&quot;</span></span>
<span class="line" id="L27"> params: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot;&quot;</span>,</span>
<span class="line" id="L28">};</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Style = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L31"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Underline = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L32"> off,</span>
<span class="line" id="L33"> single,</span>
<span class="line" id="L34"> double,</span>
<span class="line" id="L35"> curly,</span>
<span class="line" id="L36"> dotted,</span>
<span class="line" id="L37"> dashed,</span>
<span class="line" id="L38"> };</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"> fg: Color = .default,</span>
<span class="line" id="L41"> bg: Color = .default,</span>
<span class="line" id="L42"> ul: Color = .default,</span>
<span class="line" id="L43"> ul_style: Underline = .off,</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> bold: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L46"> dim: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L47"> italic: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L48"> blink: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L49"> reverse: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L50"> invisible: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L51"> strikethrough: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L52">};</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Color = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L55"> default,</span>
<span class="line" id="L56"> index: <span class="tok-type">u8</span>,</span>
<span class="line" id="L57"> rgb: [<span class="tok-number">3</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L58">};</span>
<span class="line" id="L59"></span>
</code></pre></body>
</html>

View file

@ -1,142 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>GraphemeCache.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> GraphemeCache = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// the underlying storage for graphemes. Right now 8kb</span></span>
<span class="line" id="L7">buf: [<span class="tok-number">1024</span> * <span class="tok-number">8</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">// the start index of the next grapheme</span>
</span>
<span class="line" id="L10">idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-comment">/// put a slice of bytes in the cache as a grapheme</span></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">put</span>(self: *GraphemeCache, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) []<span class="tok-type">u8</span> {</span>
<span class="line" id="L14"> <span class="tok-comment">// reset the idx to 0 if we would overflow</span>
</span>
<span class="line" id="L15"> <span class="tok-kw">if</span> (self.idx + bytes.len &gt; self.buf.len) self.idx = <span class="tok-number">0</span>;</span>
<span class="line" id="L16"> <span class="tok-kw">defer</span> self.idx += bytes.len;</span>
<span class="line" id="L17"> <span class="tok-comment">// copy the grapheme to our storage</span>
</span>
<span class="line" id="L18"> <span class="tok-builtin">@memcpy</span>(self.buf[self.idx .. self.idx + bytes.len], bytes);</span>
<span class="line" id="L19"> <span class="tok-comment">// return the slice</span>
</span>
<span class="line" id="L20"> <span class="tok-kw">return</span> self.buf[self.idx .. self.idx + bytes.len];</span>
<span class="line" id="L21">}</span>
<span class="line" id="L22"></span>
</code></pre></body>
</html>

View file

@ -1,191 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Image.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> fmt = std.fmt;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> math = std.math;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> base64 = std.base64.standard.Encoder;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> zigimg = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zigimg&quot;</span>);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Window.zig&quot;</span>);</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">const</span> log = std.log.scoped(.image);</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> transmit_opener = <span class="tok-str">&quot;\x1b_Gf=32,i={d},s={d},v={d},m={d};&quot;</span>;</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Source = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L17"> path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L18"> mem: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Placement = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L22"> img_id: <span class="tok-type">u32</span>,</span>
<span class="line" id="L23"> z_index: <span class="tok-type">i32</span>,</span>
<span class="line" id="L24"> size: ?CellSize = <span class="tok-null">null</span>,</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CellSize = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L28"> rows: <span class="tok-type">usize</span>,</span>
<span class="line" id="L29"> cols: <span class="tok-type">usize</span>,</span>
<span class="line" id="L30">};</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"><span class="tok-comment">/// unique identifier for this image. This will be managed by the screen.</span></span>
<span class="line" id="L33">id: <span class="tok-type">u32</span>,</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-comment">// width in pixels</span>
</span>
<span class="line" id="L36">width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L37"><span class="tok-comment">// height in pixels</span>
</span>
<span class="line" id="L38">height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">draw</span>(self: Image, win: Window, scale: <span class="tok-type">bool</span>, z_index: <span class="tok-type">i32</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">const</span> p = Placement{</span>
<span class="line" id="L42"> .img_id = self.id,</span>
<span class="line" id="L43"> .z_index = z_index,</span>
<span class="line" id="L44"> .size = sz: {</span>
<span class="line" id="L45"> <span class="tok-kw">if</span> (!scale) <span class="tok-kw">break</span> :sz <span class="tok-null">null</span>;</span>
<span class="line" id="L46"> <span class="tok-kw">break</span> :sz CellSize{</span>
<span class="line" id="L47"> .rows = win.height,</span>
<span class="line" id="L48"> .cols = win.width,</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50"> },</span>
<span class="line" id="L51"> };</span>
<span class="line" id="L52"> win.writeCell(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .image = p });</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">cellSize</span>(self: Image, win: Window) !CellSize {</span>
<span class="line" id="L56"> <span class="tok-comment">// cell geometry</span>
</span>
<span class="line" id="L57"> <span class="tok-kw">const</span> x_pix = win.screen.width_pix;</span>
<span class="line" id="L58"> <span class="tok-kw">const</span> y_pix = win.screen.height_pix;</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> w = win.screen.width;</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> h = win.screen.height;</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> <span class="tok-kw">const</span> pix_per_col = <span class="tok-kw">try</span> std.math.divCeil(<span class="tok-type">usize</span>, x_pix, w);</span>
<span class="line" id="L63"> <span class="tok-kw">const</span> pix_per_row = <span class="tok-kw">try</span> std.math.divCeil(<span class="tok-type">usize</span>, y_pix, h);</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> <span class="tok-kw">const</span> cell_width = std.math.divCeil(<span class="tok-type">usize</span>, self.width, pix_per_col) <span class="tok-kw">catch</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L66"> <span class="tok-kw">const</span> cell_height = std.math.divCeil(<span class="tok-type">usize</span>, self.height, pix_per_row) <span class="tok-kw">catch</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L67"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L68"> .rows = cell_height,</span>
<span class="line" id="L69"> .cols = cell_width,</span>
<span class="line" id="L70"> };</span>
<span class="line" id="L71">}</span>
<span class="line" id="L72"></span>
</code></pre></body>
</html>

View file

@ -1,215 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>InternalScreen.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Style = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Style;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Shape = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>).Shape;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> log = std.log.scoped(.internal_screen);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> InternalScreen = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> InternalCell = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L12"> char: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L13"> style: Style = .{},</span>
<span class="line" id="L14"> uri: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L15"> uri_id: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L16"> <span class="tok-comment">// if we got skipped because of a wide character</span>
</span>
<span class="line" id="L17"> skipped: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">eql</span>(self: InternalCell, cell: Cell) <span class="tok-type">bool</span> {</span>
<span class="line" id="L20"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, self.char.items, cell.char.grapheme) <span class="tok-kw">and</span></span>
<span class="line" id="L21"> std.meta.eql(self.style, cell.style) <span class="tok-kw">and</span></span>
<span class="line" id="L22"> std.mem.eql(<span class="tok-type">u8</span>, self.uri.items, cell.link.uri) <span class="tok-kw">and</span></span>
<span class="line" id="L23"> std.mem.eql(<span class="tok-type">u8</span>, self.uri_id.items, cell.link.params);</span>
<span class="line" id="L24"> }</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"></span>
<span class="line" id="L27">width: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L28">height: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L29"></span>
<span class="line" id="L30">buf: []InternalCell = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L31"></span>
<span class="line" id="L32">cursor_row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L33">cursor_col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L34">cursor_vis: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L35"></span>
<span class="line" id="L36">mouse_shape: Shape = .default,</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-comment">/// sets each cell to the default cell</span></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator, w: <span class="tok-type">usize</span>, h: <span class="tok-type">usize</span>) !InternalScreen {</span>
<span class="line" id="L40"> <span class="tok-kw">var</span> screen = InternalScreen{</span>
<span class="line" id="L41"> .buf = <span class="tok-kw">try</span> alloc.alloc(InternalCell, w * h),</span>
<span class="line" id="L42"> };</span>
<span class="line" id="L43"> <span class="tok-kw">for</span> (screen.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L44"> screen.buf[i] = .{</span>
<span class="line" id="L45"> .char = <span class="tok-kw">try</span> std.ArrayList(<span class="tok-type">u8</span>).initCapacity(alloc, <span class="tok-number">1</span>),</span>
<span class="line" id="L46"> .uri = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L47"> .uri_id = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L48"> };</span>
<span class="line" id="L49"> }</span>
<span class="line" id="L50"> screen.width = w;</span>
<span class="line" id="L51"> screen.height = h;</span>
<span class="line" id="L52"> <span class="tok-kw">return</span> screen;</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *InternalScreen, alloc: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L56"> <span class="tok-kw">for</span> (self.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L57"> self.buf[i].char.deinit();</span>
<span class="line" id="L58"> self.buf[i].uri.deinit();</span>
<span class="line" id="L59"> self.buf[i].uri_id.deinit();</span>
<span class="line" id="L60"> }</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> alloc.free(self.buf);</span>
<span class="line" id="L63">}</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"><span class="tok-comment">/// writes a cell to a location. 0 indexed</span></span>
<span class="line" id="L66"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(</span>
<span class="line" id="L67"> self: *InternalScreen,</span>
<span class="line" id="L68"> col: <span class="tok-type">usize</span>,</span>
<span class="line" id="L69"> row: <span class="tok-type">usize</span>,</span>
<span class="line" id="L70"> cell: Cell,</span>
<span class="line" id="L71">) <span class="tok-type">void</span> {</span>
<span class="line" id="L72"> <span class="tok-kw">if</span> (self.width &lt; col) {</span>
<span class="line" id="L73"> <span class="tok-comment">// column out of bounds</span>
</span>
<span class="line" id="L74"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L75"> }</span>
<span class="line" id="L76"> <span class="tok-kw">if</span> (self.height &lt; row) {</span>
<span class="line" id="L77"> <span class="tok-comment">// height out of bounds</span>
</span>
<span class="line" id="L78"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L79"> }</span>
<span class="line" id="L80"> <span class="tok-kw">const</span> i = (row * self.width) + col;</span>
<span class="line" id="L81"> assert(i &lt; self.buf.len);</span>
<span class="line" id="L82"> self.buf[i].char.clearRetainingCapacity();</span>
<span class="line" id="L83"> self.buf[i].char.appendSlice(cell.char.grapheme) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L84"> log.warn(<span class="tok-str">&quot;couldn't write grapheme&quot;</span>, .{});</span>
<span class="line" id="L85"> };</span>
<span class="line" id="L86"> self.buf[i].uri.clearRetainingCapacity();</span>
<span class="line" id="L87"> self.buf[i].uri.appendSlice(cell.link.uri) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L88"> log.warn(<span class="tok-str">&quot;couldn't write uri&quot;</span>, .{});</span>
<span class="line" id="L89"> };</span>
<span class="line" id="L90"> self.buf[i].uri.clearRetainingCapacity();</span>
<span class="line" id="L91"> self.buf[i].uri_id.appendSlice(cell.link.params) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L92"> log.warn(<span class="tok-str">&quot;couldn't write uri_id&quot;</span>, .{});</span>
<span class="line" id="L93"> };</span>
<span class="line" id="L94"> self.buf[i].style = cell.style;</span>
<span class="line" id="L95">}</span>
<span class="line" id="L96"></span>
</code></pre></body>
</html>

View file

@ -1,427 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Key.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> Key = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Modifiers = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L8"> shift: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L9"> alt: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L10"> ctrl: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L11"> super: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L12"> hyper: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L13"> meta: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L14"> caps_lock: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L15"> num_lock: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L16">};</span>
<span class="line" id="L17"></span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> KittyFlags = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u5</span>) {</span>
<span class="line" id="L19"> disambiguate: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L20"> report_events: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L21"> report_alternate_keys: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L22"> report_all_as_ctl_seqs: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L23"> report_text: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L24">};</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"><span class="tok-comment">/// the unicode codepoint of the key event.</span></span>
<span class="line" id="L27">codepoint: <span class="tok-type">u21</span>,</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-comment">/// the text generated from the key event. The underlying slice has a limited</span></span>
<span class="line" id="L30"><span class="tok-comment">/// lifetime. Vaxis maintains an internal ring buffer to temporarily store text.</span></span>
<span class="line" id="L31"><span class="tok-comment">/// If the application needs these values longer than the lifetime of the event</span></span>
<span class="line" id="L32"><span class="tok-comment">/// it must copy the data.</span></span>
<span class="line" id="L33">text: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-comment">/// the shifted codepoint of this key event. This will only be present if the</span></span>
<span class="line" id="L36"><span class="tok-comment">/// Shift modifier was used to generate the event</span></span>
<span class="line" id="L37">shifted_codepoint: ?<span class="tok-type">u21</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-comment">/// the key that would have been pressed on a standard keyboard layout. This is</span></span>
<span class="line" id="L40"><span class="tok-comment">/// useful for shortcut matching</span></span>
<span class="line" id="L41">base_layout_codepoint: ?<span class="tok-type">u21</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L42"></span>
<span class="line" id="L43">mods: Modifiers = .{},</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"><span class="tok-comment">// matches follows a loose matching algorithm for key matches.</span>
</span>
<span class="line" id="L46"><span class="tok-comment">// 1. If the codepoint and modifiers are exact matches</span>
</span>
<span class="line" id="L47"><span class="tok-comment">// 2. If the utf8 encoding of the codepoint matches the text</span>
</span>
<span class="line" id="L48"><span class="tok-comment">// 3. If there is a shifted codepoint and it matches after removing the shift</span>
</span>
<span class="line" id="L49"><span class="tok-comment">// modifier from self</span>
</span>
<span class="line" id="L50"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matches</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L51"> <span class="tok-comment">// rule 1</span>
</span>
<span class="line" id="L52"> <span class="tok-kw">if</span> (self.matchExact(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-comment">// rule 2</span>
</span>
<span class="line" id="L55"> <span class="tok-kw">if</span> (self.matchText(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-comment">// rule 3</span>
</span>
<span class="line" id="L58"> <span class="tok-kw">if</span> (self.matchShiftedCodepoint(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L59"></span>
<span class="line" id="L60"> <span class="tok-comment">// rule 4</span>
</span>
<span class="line" id="L61"> <span class="tok-kw">if</span> (self.matchShiftedCodepoint(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L62"></span>
<span class="line" id="L63"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L64">}</span>
<span class="line" id="L65"></span>
<span class="line" id="L66"><span class="tok-comment">// matches base layout codes, useful for shortcut matching when an alternate key</span>
</span>
<span class="line" id="L67"><span class="tok-comment">// layout is used</span>
</span>
<span class="line" id="L68"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchShortcut</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (self.base_layout_codepoint == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L70"> <span class="tok-kw">return</span> cp == self.base_layout_codepoint.? <span class="tok-kw">and</span> std.meta.eql(self.mods, mods);</span>
<span class="line" id="L71">}</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"><span class="tok-comment">// matches keys that aren't upper case versions when shifted. For example, shift</span>
</span>
<span class="line" id="L74"><span class="tok-comment">// + semicolon produces a colon. The key can be matched against shift +</span>
</span>
<span class="line" id="L75"><span class="tok-comment">// semicolon or just colon...or shift + ctrl + ; or just ctrl + :</span>
</span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchShiftedCodepoint</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L77"> <span class="tok-kw">if</span> (self.shifted_codepoint == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L78"> <span class="tok-kw">if</span> (!self.mods.shift) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L79"> <span class="tok-kw">var</span> self_mods = self.mods;</span>
<span class="line" id="L80"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L81"> <span class="tok-kw">return</span> cp == self.shifted_codepoint.? <span class="tok-kw">and</span> std.meta.eql(self_mods, mods);</span>
<span class="line" id="L82">}</span>
<span class="line" id="L83"></span>
<span class="line" id="L84"><span class="tok-comment">// matches when the utf8 encoding of the codepoint and relevant mods matches the</span>
</span>
<span class="line" id="L85"><span class="tok-comment">// text of the key. This function will consume Shift and Caps Lock when matching</span>
</span>
<span class="line" id="L86"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchText</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L87"> <span class="tok-comment">// return early if we have no text</span>
</span>
<span class="line" id="L88"> <span class="tok-kw">if</span> (self.text == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> <span class="tok-kw">var</span> self_mods = self.mods;</span>
<span class="line" id="L91"> <span class="tok-kw">var</span> arg_mods = mods;</span>
<span class="line" id="L92"> <span class="tok-kw">var</span> code = cp;</span>
<span class="line" id="L93"> <span class="tok-comment">// if the passed codepoint is upper, we consume all shift and caps mods for</span>
</span>
<span class="line" id="L94"> <span class="tok-comment">// checking</span>
</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (ziglyph.isUpper(cp)) {</span>
<span class="line" id="L96"> <span class="tok-comment">// consume mods</span>
</span>
<span class="line" id="L97"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L98"> self_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L99"> arg_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L100"> arg_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L101"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (mods.shift <span class="tok-kw">or</span> mods.caps_lock) {</span>
<span class="line" id="L102"> <span class="tok-comment">// uppercase the cp and consume all mods</span>
</span>
<span class="line" id="L103"> code = ziglyph.toUpper(cp);</span>
<span class="line" id="L104"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L105"> self_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L106"> arg_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L107"> arg_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-kw">var</span> buf: [<span class="tok-number">4</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L111"> <span class="tok-kw">const</span> n = std.unicode.utf8Encode(cp, buf[<span class="tok-number">0</span>..]) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L112"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, self.text.?, buf[<span class="tok-number">0</span>..n]) <span class="tok-kw">and</span> std.meta.eql(self_mods, arg_mods);</span>
<span class="line" id="L113">}</span>
<span class="line" id="L114"></span>
<span class="line" id="L115"><span class="tok-comment">// The key must exactly match the codepoint and modifiers</span>
</span>
<span class="line" id="L116"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchExact</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L117"> <span class="tok-kw">return</span> self.codepoint == cp <span class="tok-kw">and</span> std.meta.eql(self.mods, mods);</span>
<span class="line" id="L118">}</span>
<span class="line" id="L119"></span>
<span class="line" id="L120"><span class="tok-comment">// a few special keys that we encode as their actual ascii value</span>
</span>
<span class="line" id="L121"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> enter: <span class="tok-type">u21</span> = <span class="tok-number">0x0D</span>;</span>
<span class="line" id="L122"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> tab: <span class="tok-type">u21</span> = <span class="tok-number">0x09</span>;</span>
<span class="line" id="L123"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> escape: <span class="tok-type">u21</span> = <span class="tok-number">0x1B</span>;</span>
<span class="line" id="L124"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> space: <span class="tok-type">u21</span> = <span class="tok-number">0x20</span>;</span>
<span class="line" id="L125"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> backspace: <span class="tok-type">u21</span> = <span class="tok-number">0x7F</span>;</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"><span class="tok-comment">// multicodepoint is a key which generated text but cannot be expressed as a</span>
</span>
<span class="line" id="L128"><span class="tok-comment">// single codepoint. The value is the maximum unicode codepoint + 1</span>
</span>
<span class="line" id="L129"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> multicodepoint: <span class="tok-type">u21</span> = <span class="tok-number">1_114_112</span> + <span class="tok-number">1</span>;</span>
<span class="line" id="L130"></span>
<span class="line" id="L131"><span class="tok-comment">// kitty encodes these keys directly in the private use area. We reuse those</span>
</span>
<span class="line" id="L132"><span class="tok-comment">// mappings</span>
</span>
<span class="line" id="L133"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> insert: <span class="tok-type">u21</span> = <span class="tok-number">57348</span>;</span>
<span class="line" id="L134"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> delete: <span class="tok-type">u21</span> = <span class="tok-number">57349</span>;</span>
<span class="line" id="L135"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left: <span class="tok-type">u21</span> = <span class="tok-number">57350</span>;</span>
<span class="line" id="L136"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right: <span class="tok-type">u21</span> = <span class="tok-number">57351</span>;</span>
<span class="line" id="L137"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> up: <span class="tok-type">u21</span> = <span class="tok-number">57352</span>;</span>
<span class="line" id="L138"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> down: <span class="tok-type">u21</span> = <span class="tok-number">57353</span>;</span>
<span class="line" id="L139"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> page_up: <span class="tok-type">u21</span> = <span class="tok-number">57354</span>;</span>
<span class="line" id="L140"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> page_down: <span class="tok-type">u21</span> = <span class="tok-number">57355</span>;</span>
<span class="line" id="L141"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> home: <span class="tok-type">u21</span> = <span class="tok-number">57356</span>;</span>
<span class="line" id="L142"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> end: <span class="tok-type">u21</span> = <span class="tok-number">57357</span>;</span>
<span class="line" id="L143"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> caps_lock: <span class="tok-type">u21</span> = <span class="tok-number">57358</span>;</span>
<span class="line" id="L144"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> scroll_lock: <span class="tok-type">u21</span> = <span class="tok-number">57359</span>;</span>
<span class="line" id="L145"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> num_lock: <span class="tok-type">u21</span> = <span class="tok-number">57360</span>;</span>
<span class="line" id="L146"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> print_screen: <span class="tok-type">u21</span> = <span class="tok-number">57361</span>;</span>
<span class="line" id="L147"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> pause: <span class="tok-type">u21</span> = <span class="tok-number">57362</span>;</span>
<span class="line" id="L148"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> menu: <span class="tok-type">u21</span> = <span class="tok-number">57363</span>;</span>
<span class="line" id="L149"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f1: <span class="tok-type">u21</span> = <span class="tok-number">57364</span>;</span>
<span class="line" id="L150"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f2: <span class="tok-type">u21</span> = <span class="tok-number">57365</span>;</span>
<span class="line" id="L151"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f3: <span class="tok-type">u21</span> = <span class="tok-number">57366</span>;</span>
<span class="line" id="L152"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f4: <span class="tok-type">u21</span> = <span class="tok-number">57367</span>;</span>
<span class="line" id="L153"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f5: <span class="tok-type">u21</span> = <span class="tok-number">57368</span>;</span>
<span class="line" id="L154"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f6: <span class="tok-type">u21</span> = <span class="tok-number">57369</span>;</span>
<span class="line" id="L155"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f7: <span class="tok-type">u21</span> = <span class="tok-number">57370</span>;</span>
<span class="line" id="L156"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f8: <span class="tok-type">u21</span> = <span class="tok-number">57371</span>;</span>
<span class="line" id="L157"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f9: <span class="tok-type">u21</span> = <span class="tok-number">57372</span>;</span>
<span class="line" id="L158"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f10: <span class="tok-type">u21</span> = <span class="tok-number">57373</span>;</span>
<span class="line" id="L159"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f11: <span class="tok-type">u21</span> = <span class="tok-number">57374</span>;</span>
<span class="line" id="L160"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f12: <span class="tok-type">u21</span> = <span class="tok-number">57375</span>;</span>
<span class="line" id="L161"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f13: <span class="tok-type">u21</span> = <span class="tok-number">57376</span>;</span>
<span class="line" id="L162"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f14: <span class="tok-type">u21</span> = <span class="tok-number">57377</span>;</span>
<span class="line" id="L163"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f15: <span class="tok-type">u21</span> = <span class="tok-number">57378</span>;</span>
<span class="line" id="L164"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> @&quot;f16&quot;: <span class="tok-type">u21</span> = <span class="tok-number">57379</span>;</span>
<span class="line" id="L165"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f17: <span class="tok-type">u21</span> = <span class="tok-number">57380</span>;</span>
<span class="line" id="L166"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f18: <span class="tok-type">u21</span> = <span class="tok-number">57381</span>;</span>
<span class="line" id="L167"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f19: <span class="tok-type">u21</span> = <span class="tok-number">57382</span>;</span>
<span class="line" id="L168"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f20: <span class="tok-type">u21</span> = <span class="tok-number">57383</span>;</span>
<span class="line" id="L169"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f21: <span class="tok-type">u21</span> = <span class="tok-number">57384</span>;</span>
<span class="line" id="L170"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f22: <span class="tok-type">u21</span> = <span class="tok-number">57385</span>;</span>
<span class="line" id="L171"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f23: <span class="tok-type">u21</span> = <span class="tok-number">57386</span>;</span>
<span class="line" id="L172"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f24: <span class="tok-type">u21</span> = <span class="tok-number">57387</span>;</span>
<span class="line" id="L173"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f25: <span class="tok-type">u21</span> = <span class="tok-number">57388</span>;</span>
<span class="line" id="L174"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f26: <span class="tok-type">u21</span> = <span class="tok-number">57389</span>;</span>
<span class="line" id="L175"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f27: <span class="tok-type">u21</span> = <span class="tok-number">57390</span>;</span>
<span class="line" id="L176"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f28: <span class="tok-type">u21</span> = <span class="tok-number">57391</span>;</span>
<span class="line" id="L177"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f29: <span class="tok-type">u21</span> = <span class="tok-number">57392</span>;</span>
<span class="line" id="L178"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f30: <span class="tok-type">u21</span> = <span class="tok-number">57393</span>;</span>
<span class="line" id="L179"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f31: <span class="tok-type">u21</span> = <span class="tok-number">57394</span>;</span>
<span class="line" id="L180"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> @&quot;f32&quot;: <span class="tok-type">u21</span> = <span class="tok-number">57395</span>;</span>
<span class="line" id="L181"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f33: <span class="tok-type">u21</span> = <span class="tok-number">57396</span>;</span>
<span class="line" id="L182"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f34: <span class="tok-type">u21</span> = <span class="tok-number">57397</span>;</span>
<span class="line" id="L183"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f35: <span class="tok-type">u21</span> = <span class="tok-number">57398</span>;</span>
<span class="line" id="L184"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_0: <span class="tok-type">u21</span> = <span class="tok-number">57399</span>;</span>
<span class="line" id="L185"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_1: <span class="tok-type">u21</span> = <span class="tok-number">57400</span>;</span>
<span class="line" id="L186"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_2: <span class="tok-type">u21</span> = <span class="tok-number">57401</span>;</span>
<span class="line" id="L187"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_3: <span class="tok-type">u21</span> = <span class="tok-number">57402</span>;</span>
<span class="line" id="L188"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_4: <span class="tok-type">u21</span> = <span class="tok-number">57403</span>;</span>
<span class="line" id="L189"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_5: <span class="tok-type">u21</span> = <span class="tok-number">57404</span>;</span>
<span class="line" id="L190"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_6: <span class="tok-type">u21</span> = <span class="tok-number">57405</span>;</span>
<span class="line" id="L191"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_7: <span class="tok-type">u21</span> = <span class="tok-number">57406</span>;</span>
<span class="line" id="L192"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_8: <span class="tok-type">u21</span> = <span class="tok-number">57407</span>;</span>
<span class="line" id="L193"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_9: <span class="tok-type">u21</span> = <span class="tok-number">57408</span>;</span>
<span class="line" id="L194"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_decimal: <span class="tok-type">u21</span> = <span class="tok-number">57409</span>;</span>
<span class="line" id="L195"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_divide: <span class="tok-type">u21</span> = <span class="tok-number">57410</span>;</span>
<span class="line" id="L196"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_multiply: <span class="tok-type">u21</span> = <span class="tok-number">57411</span>;</span>
<span class="line" id="L197"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_subtract: <span class="tok-type">u21</span> = <span class="tok-number">57412</span>;</span>
<span class="line" id="L198"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_add: <span class="tok-type">u21</span> = <span class="tok-number">57413</span>;</span>
<span class="line" id="L199"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_enter: <span class="tok-type">u21</span> = <span class="tok-number">57414</span>;</span>
<span class="line" id="L200"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_equal: <span class="tok-type">u21</span> = <span class="tok-number">57415</span>;</span>
<span class="line" id="L201"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_separator: <span class="tok-type">u21</span> = <span class="tok-number">57416</span>;</span>
<span class="line" id="L202"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_left: <span class="tok-type">u21</span> = <span class="tok-number">57417</span>;</span>
<span class="line" id="L203"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_right: <span class="tok-type">u21</span> = <span class="tok-number">57418</span>;</span>
<span class="line" id="L204"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_up: <span class="tok-type">u21</span> = <span class="tok-number">57419</span>;</span>
<span class="line" id="L205"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_down: <span class="tok-type">u21</span> = <span class="tok-number">57420</span>;</span>
<span class="line" id="L206"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_page_up: <span class="tok-type">u21</span> = <span class="tok-number">57421</span>;</span>
<span class="line" id="L207"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_page_down: <span class="tok-type">u21</span> = <span class="tok-number">57422</span>;</span>
<span class="line" id="L208"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_home: <span class="tok-type">u21</span> = <span class="tok-number">57423</span>;</span>
<span class="line" id="L209"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_end: <span class="tok-type">u21</span> = <span class="tok-number">57424</span>;</span>
<span class="line" id="L210"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_insert: <span class="tok-type">u21</span> = <span class="tok-number">57425</span>;</span>
<span class="line" id="L211"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_delete: <span class="tok-type">u21</span> = <span class="tok-number">57426</span>;</span>
<span class="line" id="L212"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_begin: <span class="tok-type">u21</span> = <span class="tok-number">57427</span>;</span>
<span class="line" id="L213"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_play: <span class="tok-type">u21</span> = <span class="tok-number">57428</span>;</span>
<span class="line" id="L214"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_pause: <span class="tok-type">u21</span> = <span class="tok-number">57429</span>;</span>
<span class="line" id="L215"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_play_pause: <span class="tok-type">u21</span> = <span class="tok-number">57430</span>;</span>
<span class="line" id="L216"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_reverse: <span class="tok-type">u21</span> = <span class="tok-number">57431</span>;</span>
<span class="line" id="L217"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_stop: <span class="tok-type">u21</span> = <span class="tok-number">57432</span>;</span>
<span class="line" id="L218"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_fast_forward: <span class="tok-type">u21</span> = <span class="tok-number">57433</span>;</span>
<span class="line" id="L219"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_rewind: <span class="tok-type">u21</span> = <span class="tok-number">57434</span>;</span>
<span class="line" id="L220"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_track_next: <span class="tok-type">u21</span> = <span class="tok-number">57435</span>;</span>
<span class="line" id="L221"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_track_previous: <span class="tok-type">u21</span> = <span class="tok-number">57436</span>;</span>
<span class="line" id="L222"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_record: <span class="tok-type">u21</span> = <span class="tok-number">57437</span>;</span>
<span class="line" id="L223"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> lower_volume: <span class="tok-type">u21</span> = <span class="tok-number">57438</span>;</span>
<span class="line" id="L224"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> raise_volume: <span class="tok-type">u21</span> = <span class="tok-number">57439</span>;</span>
<span class="line" id="L225"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mute_volume: <span class="tok-type">u21</span> = <span class="tok-number">57440</span>;</span>
<span class="line" id="L226"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_shift: <span class="tok-type">u21</span> = <span class="tok-number">57441</span>;</span>
<span class="line" id="L227"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_control: <span class="tok-type">u21</span> = <span class="tok-number">57442</span>;</span>
<span class="line" id="L228"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_alt: <span class="tok-type">u21</span> = <span class="tok-number">57443</span>;</span>
<span class="line" id="L229"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_super: <span class="tok-type">u21</span> = <span class="tok-number">57444</span>;</span>
<span class="line" id="L230"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_hyper: <span class="tok-type">u21</span> = <span class="tok-number">57445</span>;</span>
<span class="line" id="L231"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_meta: <span class="tok-type">u21</span> = <span class="tok-number">57446</span>;</span>
<span class="line" id="L232"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_shift: <span class="tok-type">u21</span> = <span class="tok-number">57447</span>;</span>
<span class="line" id="L233"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_control: <span class="tok-type">u21</span> = <span class="tok-number">57448</span>;</span>
<span class="line" id="L234"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_alt: <span class="tok-type">u21</span> = <span class="tok-number">57449</span>;</span>
<span class="line" id="L235"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_super: <span class="tok-type">u21</span> = <span class="tok-number">57450</span>;</span>
<span class="line" id="L236"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_hyper: <span class="tok-type">u21</span> = <span class="tok-number">57451</span>;</span>
<span class="line" id="L237"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_meta: <span class="tok-type">u21</span> = <span class="tok-number">57452</span>;</span>
<span class="line" id="L238"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> iso_level_3_shift: <span class="tok-type">u21</span> = <span class="tok-number">57453</span>;</span>
<span class="line" id="L239"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> iso_level_5_shift: <span class="tok-type">u21</span> = <span class="tok-number">57454</span>;</span>
<span class="line" id="L240"></span>
<span class="line" id="L241"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'a'&quot;</span> {</span>
<span class="line" id="L242"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L243"> .codepoint = <span class="tok-str">'a'</span>,</span>
<span class="line" id="L244"> };</span>
<span class="line" id="L245"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'a'</span>, .{}));</span>
<span class="line" id="L246">}</span>
<span class="line" id="L247"></span>
<span class="line" id="L248"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+a'&quot;</span> {</span>
<span class="line" id="L249"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L250"> .codepoint = <span class="tok-str">'a'</span>,</span>
<span class="line" id="L251"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L252"> .text = <span class="tok-str">&quot;A&quot;</span>,</span>
<span class="line" id="L253"> };</span>
<span class="line" id="L254"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'a'</span>, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L255"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'A'</span>, .{}));</span>
<span class="line" id="L256"> <span class="tok-kw">try</span> testing.expect(!key.matches(<span class="tok-str">'A'</span>, .{ .ctrl = <span class="tok-null">true</span> }));</span>
<span class="line" id="L257">}</span>
<span class="line" id="L258"></span>
<span class="line" id="L259"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+tab'&quot;</span> {</span>
<span class="line" id="L260"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L261"> .codepoint = Key.tab,</span>
<span class="line" id="L262"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L263"> };</span>
<span class="line" id="L264"> <span class="tok-kw">try</span> testing.expect(key.matches(Key.tab, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L265"> <span class="tok-kw">try</span> testing.expect(!key.matches(Key.tab, .{}));</span>
<span class="line" id="L266">}</span>
<span class="line" id="L267"></span>
<span class="line" id="L268"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+;'&quot;</span> {</span>
<span class="line" id="L269"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L270"> .codepoint = <span class="tok-str">';'</span>,</span>
<span class="line" id="L271"> .shifted_codepoint = <span class="tok-str">':'</span>,</span>
<span class="line" id="L272"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L273"> .text = <span class="tok-str">&quot;:&quot;</span>,</span>
<span class="line" id="L274"> };</span>
<span class="line" id="L275"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">';'</span>, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L276"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">':'</span>, .{}));</span>
<span class="line" id="L277"></span>
<span class="line" id="L278"> <span class="tok-kw">const</span> colon: Key = .{</span>
<span class="line" id="L279"> .codepoint = <span class="tok-str">':'</span>,</span>
<span class="line" id="L280"> .mods = .{},</span>
<span class="line" id="L281"> };</span>
<span class="line" id="L282"> <span class="tok-kw">try</span> testing.expect(colon.matches(<span class="tok-str">':'</span>, .{}));</span>
<span class="line" id="L283">}</span>
<span class="line" id="L284"></span>
</code></pre></body>
</html>

View file

@ -1,163 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mouse.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">/// A mouse event</span></span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Shape = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L5"> default,</span>
<span class="line" id="L6"> text,</span>
<span class="line" id="L7"> pointer,</span>
<span class="line" id="L8"> help,</span>
<span class="line" id="L9"> progress,</span>
<span class="line" id="L10"> wait,</span>
<span class="line" id="L11"> @&quot;ew-resize&quot;,</span>
<span class="line" id="L12"> @&quot;ns-resize&quot;,</span>
<span class="line" id="L13"> cell,</span>
<span class="line" id="L14">};</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Button = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L17"> left,</span>
<span class="line" id="L18"> middle,</span>
<span class="line" id="L19"> right,</span>
<span class="line" id="L20"> none,</span>
<span class="line" id="L21"> wheel_up = <span class="tok-number">64</span>,</span>
<span class="line" id="L22"> wheel_down = <span class="tok-number">65</span>,</span>
<span class="line" id="L23"> button_8 = <span class="tok-number">128</span>,</span>
<span class="line" id="L24"> button_9 = <span class="tok-number">129</span>,</span>
<span class="line" id="L25"> button_10 = <span class="tok-number">130</span>,</span>
<span class="line" id="L26"> button_11 = <span class="tok-number">131</span>,</span>
<span class="line" id="L27">};</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Modifiers = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u3</span>) {</span>
<span class="line" id="L30"> shift: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L31"> alt: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L32"> ctrl: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L33">};</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Type = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L36"> press,</span>
<span class="line" id="L37"> release,</span>
<span class="line" id="L38"> motion,</span>
<span class="line" id="L39"> drag,</span>
<span class="line" id="L40">};</span>
<span class="line" id="L41"></span>
<span class="line" id="L42">col: <span class="tok-type">usize</span>,</span>
<span class="line" id="L43">row: <span class="tok-type">usize</span>,</span>
<span class="line" id="L44">button: Button,</span>
<span class="line" id="L45">mods: Modifiers,</span>
<span class="line" id="L46"><span class="tok-type">type</span>: Type,</span>
<span class="line" id="L47"></span>
</code></pre></body>
</html>

View file

@ -1,119 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Options.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">/// Runtime options</span></span>
<span class="line" id="L2"><span class="tok-kw">const</span> Options = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L3"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,181 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Screen.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Shape = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>).Shape;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Winsize = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Tty.zig&quot;</span>).Winsize;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> log = std.log.scoped(.screen);</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> Screen = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L12"></span>
<span class="line" id="L13">width: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L14">height: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L15"></span>
<span class="line" id="L16">width_pix: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17">height_pix: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19">buf: []Cell = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L20"></span>
<span class="line" id="L21">cursor_row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L22">cursor_col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L23">cursor_vis: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-comment">/// true when we measure cells with unicode</span></span>
<span class="line" id="L26">unicode: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28">mouse_shape: Shape = .default,</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator, winsize: Winsize) !Screen {</span>
<span class="line" id="L31"> <span class="tok-kw">const</span> w = winsize.cols;</span>
<span class="line" id="L32"> <span class="tok-kw">const</span> h = winsize.rows;</span>
<span class="line" id="L33"> <span class="tok-kw">var</span> self = Screen{</span>
<span class="line" id="L34"> .buf = <span class="tok-kw">try</span> alloc.alloc(Cell, w * h),</span>
<span class="line" id="L35"> .width = w,</span>
<span class="line" id="L36"> .height = h,</span>
<span class="line" id="L37"> .width_pix = winsize.x_pixel,</span>
<span class="line" id="L38"> .height_pix = winsize.y_pixel,</span>
<span class="line" id="L39"> };</span>
<span class="line" id="L40"> <span class="tok-kw">for</span> (self.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L41"> self.buf[i] = .{};</span>
<span class="line" id="L42"> }</span>
<span class="line" id="L43"> <span class="tok-kw">return</span> self;</span>
<span class="line" id="L44">}</span>
<span class="line" id="L45"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Screen, alloc: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L46"> alloc.free(self.buf);</span>
<span class="line" id="L47">}</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"><span class="tok-comment">/// writes a cell to a location. 0 indexed</span></span>
<span class="line" id="L50"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(self: *Screen, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L51"> <span class="tok-kw">if</span> (self.width &lt; col) {</span>
<span class="line" id="L52"> <span class="tok-comment">// column out of bounds</span>
</span>
<span class="line" id="L53"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L54"> }</span>
<span class="line" id="L55"> <span class="tok-kw">if</span> (self.height &lt; row) {</span>
<span class="line" id="L56"> <span class="tok-comment">// height out of bounds</span>
</span>
<span class="line" id="L57"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L58"> }</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> i = (row * self.width) + col;</span>
<span class="line" id="L60"> assert(i &lt; self.buf.len);</span>
<span class="line" id="L61"> self.buf[i] = cell;</span>
<span class="line" id="L62">}</span>
<span class="line" id="L63"></span>
</code></pre></body>
</html>

View file

@ -1,410 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tty.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> builtin = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;builtin&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> os = std.os;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Vaxis = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;vaxis.zig&quot;</span>).Vaxis;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Parser = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Parser.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> GraphemeCache = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;GraphemeCache.zig&quot;</span>);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> log = std.log.scoped(.tty);</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">const</span> Tty = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> Writer = std.io.Writer(os.fd_t, os.WriteError, os.write);</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> BufferedWriter = std.io.BufferedWriter(<span class="tok-number">4096</span>, Writer);</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-comment">/// the original state of the terminal, prior to calling makeRaw</span></span>
<span class="line" id="L17">termios: os.termios,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-comment">/// The file descriptor we are using for I/O</span></span>
<span class="line" id="L20">fd: os.fd_t,</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-comment">/// the write end of a pipe to signal the tty should exit it's run loop</span></span>
<span class="line" id="L23">quit_fd: ?os.fd_t = <span class="tok-null">null</span>,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25">buffered_writer: BufferedWriter,</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"><span class="tok-comment">/// initializes a Tty instance by opening /dev/tty and &quot;making it raw&quot;</span></span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>() !Tty {</span>
<span class="line" id="L29"> <span class="tok-comment">// Open our tty</span>
</span>
<span class="line" id="L30"> <span class="tok-kw">const</span> fd = <span class="tok-kw">try</span> os.open(<span class="tok-str">&quot;/dev/tty&quot;</span>, .{ .ACCMODE = .RDWR }, <span class="tok-number">0</span>);</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"> <span class="tok-comment">// Set the termios of the tty</span>
</span>
<span class="line" id="L33"> <span class="tok-kw">const</span> termios = <span class="tok-kw">try</span> makeRaw(fd);</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"> <span class="tok-kw">return</span> Tty{</span>
<span class="line" id="L36"> .fd = fd,</span>
<span class="line" id="L37"> .termios = termios,</span>
<span class="line" id="L38"> .buffered_writer = std.io.bufferedWriter(Writer{ .context = fd }),</span>
<span class="line" id="L39"> };</span>
<span class="line" id="L40">}</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"><span class="tok-comment">/// release resources associated with the Tty return it to it's original state</span></span>
<span class="line" id="L43"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Tty) <span class="tok-type">void</span> {</span>
<span class="line" id="L44"> os.tcsetattr(self.fd, .FLUSH, self.termios) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L45"> log.err(<span class="tok-str">&quot;couldn't restore terminal: {}&quot;</span>, .{err});</span>
<span class="line" id="L46"> };</span>
<span class="line" id="L47"> os.close(self.fd);</span>
<span class="line" id="L48">}</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"><span class="tok-comment">/// stops the run loop</span></span>
<span class="line" id="L51"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stop</span>(self: *Tty) <span class="tok-type">void</span> {</span>
<span class="line" id="L52"> <span class="tok-kw">if</span> (self.quit_fd) |fd| {</span>
<span class="line" id="L53"> _ = std.os.write(fd, <span class="tok-str">&quot;q&quot;</span>) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L54"> }</span>
<span class="line" id="L55">}</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"><span class="tok-comment">/// read input from the tty</span></span>
<span class="line" id="L58"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">run</span>(</span>
<span class="line" id="L59"> self: *Tty,</span>
<span class="line" id="L60"> <span class="tok-kw">comptime</span> Event: <span class="tok-type">type</span>,</span>
<span class="line" id="L61"> vx: *Vaxis(Event),</span>
<span class="line" id="L62">) !<span class="tok-type">void</span> {</span>
<span class="line" id="L63"> <span class="tok-comment">// create a pipe so we can signal to exit the run loop</span>
</span>
<span class="line" id="L64"> <span class="tok-kw">const</span> pipe = <span class="tok-kw">try</span> os.pipe();</span>
<span class="line" id="L65"> <span class="tok-kw">defer</span> os.close(pipe[<span class="tok-number">0</span>]);</span>
<span class="line" id="L66"> <span class="tok-kw">defer</span> os.close(pipe[<span class="tok-number">1</span>]);</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> <span class="tok-comment">// get our initial winsize</span>
</span>
<span class="line" id="L69"> <span class="tok-kw">const</span> winsize = <span class="tok-kw">try</span> getWinsize(self.fd);</span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;winsize&quot;</span>)) {</span>
<span class="line" id="L71"> vx.postEvent(.{ .winsize = winsize });</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"> <span class="tok-comment">// assign the write end of the pipe to our quit_fd</span>
</span>
<span class="line" id="L75"> self.quit_fd = pipe[<span class="tok-number">1</span>];</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"> <span class="tok-comment">// Build a winch handler. We need build this struct to get an anonymous</span>
</span>
<span class="line" id="L78"> <span class="tok-comment">// function which can post the winsize event</span>
</span>
<span class="line" id="L79"> <span class="tok-comment">// TODO: more signals, move this outside of this function?</span>
</span>
<span class="line" id="L80"> <span class="tok-kw">const</span> WinchHandler = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L81"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"> <span class="tok-kw">var</span> vx_winch: *Vaxis(Event) = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L84"> <span class="tok-kw">var</span> fd: os.fd_t = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L85"></span>
<span class="line" id="L86"> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(vx_arg: *Vaxis(Event), fd_arg: os.fd_t) !<span class="tok-type">void</span> {</span>
<span class="line" id="L87"> vx_winch = vx_arg;</span>
<span class="line" id="L88"> fd = fd_arg;</span>
<span class="line" id="L89"> <span class="tok-kw">var</span> act = os.Sigaction{</span>
<span class="line" id="L90"> .handler = .{ .handler = Self.handleWinch },</span>
<span class="line" id="L91"> .mask = <span class="tok-kw">switch</span> (builtin.os.tag) {</span>
<span class="line" id="L92"> .macos =&gt; <span class="tok-number">0</span>,</span>
<span class="line" id="L93"> .linux =&gt; std.os.empty_sigset,</span>
<span class="line" id="L94"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;os not supported&quot;</span>),</span>
<span class="line" id="L95"> },</span>
<span class="line" id="L96"> .flags = <span class="tok-number">0</span>,</span>
<span class="line" id="L97"> };</span>
<span class="line" id="L98"></span>
<span class="line" id="L99"> <span class="tok-kw">try</span> os.sigaction(os.SIG.WINCH, &amp;act, <span class="tok-null">null</span>);</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"> <span class="tok-kw">fn</span> <span class="tok-fn">handleWinch</span>(_: <span class="tok-type">c_int</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L103"> <span class="tok-kw">const</span> ws = getWinsize(fd) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L105"> };</span>
<span class="line" id="L106"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;winsize&quot;</span>)) {</span>
<span class="line" id="L107"> vx_winch.postEvent(.{ .winsize = ws });</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"> };</span>
<span class="line" id="L111"> <span class="tok-kw">try</span> WinchHandler.init(vx, self.fd);</span>
<span class="line" id="L112"></span>
<span class="line" id="L113"> <span class="tok-comment">// initialize a grapheme cache</span>
</span>
<span class="line" id="L114"> <span class="tok-kw">var</span> cache: GraphemeCache = .{};</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-comment">// Set up fds for polling</span>
</span>
<span class="line" id="L117"> <span class="tok-kw">var</span> pollfds: [<span class="tok-number">2</span>]std.os.pollfd = .{</span>
<span class="line" id="L118"> .{ .fd = self.fd, .events = std.os.POLL.IN, .revents = <span class="tok-null">undefined</span> },</span>
<span class="line" id="L119"> .{ .fd = pipe[<span class="tok-number">0</span>], .events = std.os.POLL.IN, .revents = <span class="tok-null">undefined</span> },</span>
<span class="line" id="L120"> };</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"> <span class="tok-kw">var</span> parser: Parser = .{};</span>
<span class="line" id="L123"></span>
<span class="line" id="L124"> <span class="tok-comment">// initialize the read buffer</span>
</span>
<span class="line" id="L125"> <span class="tok-kw">var</span> buf: [<span class="tok-number">1024</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L126"> <span class="tok-comment">// read loop</span>
</span>
<span class="line" id="L127"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L128"> _ = <span class="tok-kw">try</span> std.os.poll(&amp;pollfds, -<span class="tok-number">1</span>);</span>
<span class="line" id="L129"> <span class="tok-kw">if</span> (pollfds[<span class="tok-number">1</span>].revents &amp; std.os.POLL.IN != <span class="tok-number">0</span>) {</span>
<span class="line" id="L130"> log.info(<span class="tok-str">&quot;quitting read thread&quot;</span>, .{});</span>
<span class="line" id="L131"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L132"> }</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> <span class="tok-kw">const</span> n = <span class="tok-kw">try</span> os.read(self.fd, &amp;buf);</span>
<span class="line" id="L135"> <span class="tok-kw">var</span> start: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L136"> <span class="tok-kw">while</span> (start &lt; n) {</span>
<span class="line" id="L137"> <span class="tok-kw">const</span> result = <span class="tok-kw">try</span> parser.parse(buf[start..n]);</span>
<span class="line" id="L138"> start += result.n;</span>
<span class="line" id="L139"> <span class="tok-comment">// TODO: if we get 0 byte read, copy the remaining bytes to the</span>
</span>
<span class="line" id="L140"> <span class="tok-comment">// beginning of the buffer and read mmore? this should only happen</span>
</span>
<span class="line" id="L141"> <span class="tok-comment">// if we are in the middle of a grapheme at and filled our</span>
</span>
<span class="line" id="L142"> <span class="tok-comment">// buffer. Probably can happen on large pastes so needs to be</span>
</span>
<span class="line" id="L143"> <span class="tok-comment">// implemented but low priority</span>
</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"> <span class="tok-kw">const</span> event = result.event <span class="tok-kw">orelse</span> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L146"> <span class="tok-kw">switch</span> (event) {</span>
<span class="line" id="L147"> .key_press =&gt; |key| {</span>
<span class="line" id="L148"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;key_press&quot;</span>)) {</span>
<span class="line" id="L149"> <span class="tok-comment">// HACK: yuck. there has to be a better way</span>
</span>
<span class="line" id="L150"> <span class="tok-kw">var</span> mut_key = key;</span>
<span class="line" id="L151"> <span class="tok-kw">if</span> (key.text) |text| {</span>
<span class="line" id="L152"> mut_key.text = cache.put(text);</span>
<span class="line" id="L153"> }</span>
<span class="line" id="L154"> vx.postEvent(.{ .key_press = mut_key });</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156"> },</span>
<span class="line" id="L157"> .mouse =&gt; |mouse| {</span>
<span class="line" id="L158"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;mouse&quot;</span>)) {</span>
<span class="line" id="L159"> vx.postEvent(.{ .mouse = mouse });</span>
<span class="line" id="L160"> }</span>
<span class="line" id="L161"> },</span>
<span class="line" id="L162"> .focus_in =&gt; {</span>
<span class="line" id="L163"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;focus_in&quot;</span>)) {</span>
<span class="line" id="L164"> vx.postEvent(.focus_in);</span>
<span class="line" id="L165"> }</span>
<span class="line" id="L166"> },</span>
<span class="line" id="L167"> .focus_out =&gt; {</span>
<span class="line" id="L168"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;focus_out&quot;</span>)) {</span>
<span class="line" id="L169"> vx.postEvent(.focus_out);</span>
<span class="line" id="L170"> }</span>
<span class="line" id="L171"> },</span>
<span class="line" id="L172"> .paste_start =&gt; {</span>
<span class="line" id="L173"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;paste_start&quot;</span>)) {</span>
<span class="line" id="L174"> vx.postEvent(.paste_start);</span>
<span class="line" id="L175"> }</span>
<span class="line" id="L176"> },</span>
<span class="line" id="L177"> .paste_end =&gt; {</span>
<span class="line" id="L178"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;paste_end&quot;</span>)) {</span>
<span class="line" id="L179"> vx.postEvent(.paste_end);</span>
<span class="line" id="L180"> }</span>
<span class="line" id="L181"> },</span>
<span class="line" id="L182"> .cap_kitty_keyboard =&gt; {</span>
<span class="line" id="L183"> log.info(<span class="tok-str">&quot;kitty keyboard capability detected&quot;</span>, .{});</span>
<span class="line" id="L184"> vx.caps.kitty_keyboard = <span class="tok-null">true</span>;</span>
<span class="line" id="L185"> },</span>
<span class="line" id="L186"> .cap_kitty_graphics =&gt; {</span>
<span class="line" id="L187"> <span class="tok-kw">if</span> (!vx.caps.kitty_graphics) {</span>
<span class="line" id="L188"> log.info(<span class="tok-str">&quot;kitty graphics capability detected&quot;</span>, .{});</span>
<span class="line" id="L189"> vx.caps.kitty_graphics = <span class="tok-null">true</span>;</span>
<span class="line" id="L190"> }</span>
<span class="line" id="L191"> },</span>
<span class="line" id="L192"> .cap_rgb =&gt; {</span>
<span class="line" id="L193"> log.info(<span class="tok-str">&quot;rgb capability detected&quot;</span>, .{});</span>
<span class="line" id="L194"> vx.caps.rgb = <span class="tok-null">true</span>;</span>
<span class="line" id="L195"> },</span>
<span class="line" id="L196"> .cap_unicode =&gt; {</span>
<span class="line" id="L197"> log.info(<span class="tok-str">&quot;unicode capability detected&quot;</span>, .{});</span>
<span class="line" id="L198"> vx.caps.unicode = <span class="tok-null">true</span>;</span>
<span class="line" id="L199"> vx.screen.unicode = <span class="tok-null">true</span>;</span>
<span class="line" id="L200"> },</span>
<span class="line" id="L201"> .cap_da1 =&gt; {</span>
<span class="line" id="L202"> std.Thread.Futex.wake(&amp;vx.query_futex, <span class="tok-number">10</span>);</span>
<span class="line" id="L203"> },</span>
<span class="line" id="L204"> }</span>
<span class="line" id="L205"> }</span>
<span class="line" id="L206"> }</span>
<span class="line" id="L207">}</span>
<span class="line" id="L208"></span>
<span class="line" id="L209"><span class="tok-comment">/// write to the tty. These writes are buffered and require calling flush to</span></span>
<span class="line" id="L210"><span class="tok-comment">/// flush writes to the tty</span></span>
<span class="line" id="L211"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Tty, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">usize</span> {</span>
<span class="line" id="L212"> <span class="tok-kw">return</span> self.buffered_writer.write(bytes);</span>
<span class="line" id="L213">}</span>
<span class="line" id="L214"></span>
<span class="line" id="L215"><span class="tok-comment">/// flushes the write buffer to the tty</span></span>
<span class="line" id="L216"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">flush</span>(self: *Tty) !<span class="tok-type">void</span> {</span>
<span class="line" id="L217"> <span class="tok-kw">try</span> self.buffered_writer.flush();</span>
<span class="line" id="L218">}</span>
<span class="line" id="L219"></span>
<span class="line" id="L220"><span class="tok-comment">/// makeRaw enters the raw state for the terminal.</span></span>
<span class="line" id="L221"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">makeRaw</span>(fd: os.fd_t) !os.termios {</span>
<span class="line" id="L222"> <span class="tok-kw">const</span> state = <span class="tok-kw">try</span> os.tcgetattr(fd);</span>
<span class="line" id="L223"> <span class="tok-kw">var</span> raw = state;</span>
<span class="line" id="L224"> <span class="tok-comment">// see termios(3)</span>
</span>
<span class="line" id="L225"> raw.iflag.IGNBRK = <span class="tok-null">false</span>;</span>
<span class="line" id="L226"> raw.iflag.BRKINT = <span class="tok-null">false</span>;</span>
<span class="line" id="L227"> raw.iflag.ISTRIP = <span class="tok-null">false</span>;</span>
<span class="line" id="L228"> raw.iflag.INLCR = <span class="tok-null">false</span>;</span>
<span class="line" id="L229"> raw.iflag.IGNCR = <span class="tok-null">false</span>;</span>
<span class="line" id="L230"> raw.iflag.ICRNL = <span class="tok-null">false</span>;</span>
<span class="line" id="L231"> raw.iflag.IXON = <span class="tok-null">false</span>;</span>
<span class="line" id="L232"></span>
<span class="line" id="L233"> raw.oflag.OPOST = <span class="tok-null">false</span>;</span>
<span class="line" id="L234"></span>
<span class="line" id="L235"> raw.lflag.ECHO = <span class="tok-null">false</span>;</span>
<span class="line" id="L236"> raw.lflag.ECHONL = <span class="tok-null">false</span>;</span>
<span class="line" id="L237"> raw.lflag.ICANON = <span class="tok-null">false</span>;</span>
<span class="line" id="L238"> raw.lflag.IEXTEN = <span class="tok-null">false</span>;</span>
<span class="line" id="L239"></span>
<span class="line" id="L240"> raw.cflag.CSIZE = .CS8;</span>
<span class="line" id="L241"> raw.cflag.PARENB = <span class="tok-null">false</span>;</span>
<span class="line" id="L242"></span>
<span class="line" id="L243"> raw.cc[<span class="tok-builtin">@intFromEnum</span>(std.posix.V.MIN)] = <span class="tok-number">1</span>;</span>
<span class="line" id="L244"> raw.cc[<span class="tok-builtin">@intFromEnum</span>(std.posix.V.TIME)] = <span class="tok-number">0</span>;</span>
<span class="line" id="L245"> <span class="tok-kw">try</span> os.tcsetattr(fd, .FLUSH, raw);</span>
<span class="line" id="L246"> <span class="tok-kw">return</span> state;</span>
<span class="line" id="L247">}</span>
<span class="line" id="L248"></span>
<span class="line" id="L249"><span class="tok-comment">/// The size of the terminal screen</span></span>
<span class="line" id="L250"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Winsize = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L251"> rows: <span class="tok-type">usize</span>,</span>
<span class="line" id="L252"> cols: <span class="tok-type">usize</span>,</span>
<span class="line" id="L253"> x_pixel: <span class="tok-type">usize</span>,</span>
<span class="line" id="L254"> y_pixel: <span class="tok-type">usize</span>,</span>
<span class="line" id="L255">};</span>
<span class="line" id="L256"></span>
<span class="line" id="L257"><span class="tok-kw">fn</span> <span class="tok-fn">getWinsize</span>(fd: os.fd_t) !Winsize {</span>
<span class="line" id="L258"> <span class="tok-kw">var</span> winsize = os.winsize{</span>
<span class="line" id="L259"> .ws_row = <span class="tok-number">0</span>,</span>
<span class="line" id="L260"> .ws_col = <span class="tok-number">0</span>,</span>
<span class="line" id="L261"> .ws_xpixel = <span class="tok-number">0</span>,</span>
<span class="line" id="L262"> .ws_ypixel = <span class="tok-number">0</span>,</span>
<span class="line" id="L263"> };</span>
<span class="line" id="L264"></span>
<span class="line" id="L265"> <span class="tok-kw">const</span> err = os.system.ioctl(fd, os.T.IOCGWINSZ, <span class="tok-builtin">@intFromPtr</span>(&amp;winsize));</span>
<span class="line" id="L266"> <span class="tok-kw">if</span> (os.errno(err) == .SUCCESS)</span>
<span class="line" id="L267"> <span class="tok-kw">return</span> Winsize{</span>
<span class="line" id="L268"> .rows = winsize.ws_row,</span>
<span class="line" id="L269"> .cols = winsize.ws_col,</span>
<span class="line" id="L270"> .x_pixel = winsize.ws_xpixel,</span>
<span class="line" id="L271"> .y_pixel = winsize.ws_ypixel,</span>
<span class="line" id="L272"> };</span>
<span class="line" id="L273"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.IoctlError;</span>
<span class="line" id="L274">}</span>
<span class="line" id="L275"></span>
</code></pre></body>
</html>

View file

@ -1,338 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Window.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> WordIterator = ziglyph.WordIterator;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> GraphemeIterator = ziglyph.GraphemeIterator;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> Screen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Screen.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Segment = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Segment;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> gw = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;gwidth.zig&quot;</span>);</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> log = std.log.scoped(.window);</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Size = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L16"> expand,</span>
<span class="line" id="L17"> limit: <span class="tok-type">usize</span>,</span>
<span class="line" id="L18">};</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// horizontal offset from the screen</span></span>
<span class="line" id="L21">x_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L22"><span class="tok-comment">/// vertical offset from the screen</span></span>
<span class="line" id="L23">y_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L24"><span class="tok-comment">/// width of the window. This can't be larger than the terminal screen</span></span>
<span class="line" id="L25">width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L26"><span class="tok-comment">/// height of the window. This can't be larger than the terminal screen</span></span>
<span class="line" id="L27">height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L28"></span>
<span class="line" id="L29">screen: *Screen,</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-comment">/// Creates a new window with offset relative to parent and size clamped to the</span></span>
<span class="line" id="L32"><span class="tok-comment">/// parent's size. Windows do not retain a reference to their parent and are</span></span>
<span class="line" id="L33"><span class="tok-comment">/// unaware of resizes.</span></span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">initChild</span>(</span>
<span class="line" id="L35"> self: Window,</span>
<span class="line" id="L36"> x_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L37"> y_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L38"> width: Size,</span>
<span class="line" id="L39"> height: Size,</span>
<span class="line" id="L40">) Window {</span>
<span class="line" id="L41"> <span class="tok-kw">const</span> resolved_width = <span class="tok-kw">switch</span> (width) {</span>
<span class="line" id="L42"> .expand =&gt; self.width - x_off,</span>
<span class="line" id="L43"> .limit =&gt; |w| blk: {</span>
<span class="line" id="L44"> <span class="tok-kw">if</span> (w + x_off &gt; self.width) {</span>
<span class="line" id="L45"> <span class="tok-kw">break</span> :blk self.width - x_off;</span>
<span class="line" id="L46"> }</span>
<span class="line" id="L47"> <span class="tok-kw">break</span> :blk w;</span>
<span class="line" id="L48"> },</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50"> <span class="tok-kw">const</span> resolved_height = <span class="tok-kw">switch</span> (height) {</span>
<span class="line" id="L51"> .expand =&gt; self.height - y_off,</span>
<span class="line" id="L52"> .limit =&gt; |h| blk: {</span>
<span class="line" id="L53"> <span class="tok-kw">if</span> (h + y_off &gt; self.height) {</span>
<span class="line" id="L54"> <span class="tok-kw">break</span> :blk self.height - y_off;</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> <span class="tok-kw">break</span> :blk h;</span>
<span class="line" id="L57"> },</span>
<span class="line" id="L58"> };</span>
<span class="line" id="L59"> <span class="tok-kw">return</span> Window{</span>
<span class="line" id="L60"> .x_off = x_off + self.x_off,</span>
<span class="line" id="L61"> .y_off = y_off + self.y_off,</span>
<span class="line" id="L62"> .width = resolved_width,</span>
<span class="line" id="L63"> .height = resolved_height,</span>
<span class="line" id="L64"> .screen = self.screen,</span>
<span class="line" id="L65"> };</span>
<span class="line" id="L66">}</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"><span class="tok-comment">/// writes a cell to the location in the window</span></span>
<span class="line" id="L69"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(self: Window, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (self.height == <span class="tok-number">0</span> <span class="tok-kw">or</span> self.width == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L71"> <span class="tok-kw">if</span> (self.height &lt;= row <span class="tok-kw">or</span> self.width &lt;= col) <span class="tok-kw">return</span>;</span>
<span class="line" id="L72"> self.screen.writeCell(col + self.x_off, row + self.y_off, cell);</span>
<span class="line" id="L73">}</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"><span class="tok-comment">/// fills the window with the default cell</span></span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">clear</span>(self: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L77"> self.fill(.{});</span>
<span class="line" id="L78">}</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"><span class="tok-comment">/// returns the width of the grapheme. This depends on the terminal capabilities</span></span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">gwidth</span>(self: Window, str: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">const</span> m: gw.Method = <span class="tok-kw">if</span> (self.screen.unicode) .unicode <span class="tok-kw">else</span> .wcwidth;</span>
<span class="line" id="L83"> <span class="tok-kw">return</span> gw.gwidth(str, m) <span class="tok-kw">catch</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L84">}</span>
<span class="line" id="L85"></span>
<span class="line" id="L86"><span class="tok-comment">/// fills the window with the provided cell</span></span>
<span class="line" id="L87"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fill</span>(self: Window, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L88"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = self.y_off;</span>
<span class="line" id="L89"> <span class="tok-kw">while</span> (row &lt; (self.height + self.y_off)) : (row += <span class="tok-number">1</span>) {</span>
<span class="line" id="L90"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = self.x_off;</span>
<span class="line" id="L91"> <span class="tok-kw">while</span> (col &lt; (self.width + self.x_off)) : (col += <span class="tok-number">1</span>) {</span>
<span class="line" id="L92"> self.screen.writeCell(col, row, cell);</span>
<span class="line" id="L93"> }</span>
<span class="line" id="L94"> }</span>
<span class="line" id="L95">}</span>
<span class="line" id="L96"></span>
<span class="line" id="L97"><span class="tok-comment">/// hide the cursor</span></span>
<span class="line" id="L98"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">hideCursor</span>(self: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L99"> self.screen.cursor_vis = <span class="tok-null">false</span>;</span>
<span class="line" id="L100">}</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"><span class="tok-comment">/// show the cursor at the given coordinates, 0 indexed</span></span>
<span class="line" id="L103"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">showCursor</span>(self: Window, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">if</span> (self.height == <span class="tok-number">0</span> <span class="tok-kw">or</span> self.width == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L105"> <span class="tok-kw">if</span> (self.height &lt;= row <span class="tok-kw">or</span> self.width &lt;= col) <span class="tok-kw">return</span>;</span>
<span class="line" id="L106"> self.screen.cursor_vis = <span class="tok-null">true</span>;</span>
<span class="line" id="L107"> self.screen.cursor_row = row + self.y_off;</span>
<span class="line" id="L108"> self.screen.cursor_col = col + self.x_off;</span>
<span class="line" id="L109">}</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"><span class="tok-comment">/// prints text in the window with simple word wrapping.</span></span>
<span class="line" id="L112"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">wrap</span>(self: Window, segments: []Segment) !<span class="tok-type">void</span> {</span>
<span class="line" id="L113"> <span class="tok-comment">// pub fn wrap(self: Window, str: []const u8) !void {</span>
</span>
<span class="line" id="L114"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L115"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L116"> <span class="tok-kw">var</span> wrapped: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L117"> <span class="tok-kw">for</span> (segments) |segment| {</span>
<span class="line" id="L118"> <span class="tok-kw">var</span> word_iter = <span class="tok-kw">try</span> WordIterator.init(segment.text);</span>
<span class="line" id="L119"> <span class="tok-kw">while</span> (word_iter.next()) |word| {</span>
<span class="line" id="L120"> <span class="tok-comment">// break lines when we need</span>
</span>
<span class="line" id="L121"> <span class="tok-kw">if</span> (word.bytes[<span class="tok-number">0</span>] == <span class="tok-str">'\r'</span> <span class="tok-kw">or</span> word.bytes[<span class="tok-number">0</span>] == <span class="tok-str">'\n'</span>) {</span>
<span class="line" id="L122"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L123"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L124"> wrapped = <span class="tok-null">false</span>;</span>
<span class="line" id="L125"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L126"> }</span>
<span class="line" id="L127"> <span class="tok-comment">// break lines when we can't fit this word, and the word isn't longer</span>
</span>
<span class="line" id="L128"> <span class="tok-comment">// than our width</span>
</span>
<span class="line" id="L129"> <span class="tok-kw">const</span> word_width = self.gwidth(word.bytes);</span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (word_width + col &gt;= self.width <span class="tok-kw">and</span> word_width &lt; self.width) {</span>
<span class="line" id="L131"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L132"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L133"> wrapped = <span class="tok-null">true</span>;</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> <span class="tok-comment">// don't print whitespace in the first column, unless we had a hard</span>
</span>
<span class="line" id="L136"> <span class="tok-comment">// break</span>
</span>
<span class="line" id="L137"> <span class="tok-kw">if</span> (col == <span class="tok-number">0</span> <span class="tok-kw">and</span> std.mem.eql(<span class="tok-type">u8</span>, word.bytes, <span class="tok-str">&quot; &quot;</span>) <span class="tok-kw">and</span> wrapped) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(word.bytes);</span>
<span class="line" id="L139"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L140"> <span class="tok-kw">if</span> (col &gt;= self.width) {</span>
<span class="line" id="L141"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L142"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L143"> wrapped = <span class="tok-null">true</span>;</span>
<span class="line" id="L144"> }</span>
<span class="line" id="L145"> <span class="tok-kw">const</span> s = grapheme.slice(word.bytes);</span>
<span class="line" id="L146"> <span class="tok-kw">const</span> w = self.gwidth(s);</span>
<span class="line" id="L147"> self.writeCell(col, row, .{</span>
<span class="line" id="L148"> .char = .{</span>
<span class="line" id="L149"> .grapheme = s,</span>
<span class="line" id="L150"> .width = w,</span>
<span class="line" id="L151"> },</span>
<span class="line" id="L152"> .style = segment.style,</span>
<span class="line" id="L153"> .link = segment.link,</span>
<span class="line" id="L154"> });</span>
<span class="line" id="L155"> col += w;</span>
<span class="line" id="L156"> }</span>
<span class="line" id="L157"> }</span>
<span class="line" id="L158"> }</span>
<span class="line" id="L159">}</span>
<span class="line" id="L160"></span>
<span class="line" id="L161"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set&quot;</span> {</span>
<span class="line" id="L162"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L163"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L164"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L165"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L166"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L167"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L168"> };</span>
<span class="line" id="L169"></span>
<span class="line" id="L170"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">1</span>, <span class="tok-number">1</span>, .expand, .expand);</span>
<span class="line" id="L171"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">19</span>, child.width);</span>
<span class="line" id="L172"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">19</span>, child.height);</span>
<span class="line" id="L173">}</span>
<span class="line" id="L174"></span>
<span class="line" id="L175"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set too big&quot;</span> {</span>
<span class="line" id="L176"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L177"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L178"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L179"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L180"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L181"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L182"> };</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L185"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">20</span>, child.width);</span>
<span class="line" id="L186"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">20</span>, child.height);</span>
<span class="line" id="L187">}</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set too big with offset&quot;</span> {</span>
<span class="line" id="L190"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L191"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L192"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L193"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L194"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L195"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L196"> };</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">10</span>, <span class="tok-number">10</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L199"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">10</span>, child.width);</span>
<span class="line" id="L200"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">10</span>, child.height);</span>
<span class="line" id="L201">}</span>
<span class="line" id="L202"></span>
<span class="line" id="L203"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size nested offsets&quot;</span> {</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L205"> .x_off = <span class="tok-number">1</span>,</span>
<span class="line" id="L206"> .y_off = <span class="tok-number">1</span>,</span>
<span class="line" id="L207"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L208"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L209"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L210"> };</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">10</span>, <span class="tok-number">10</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L213"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">11</span>, child.x_off);</span>
<span class="line" id="L214"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">11</span>, child.y_off);</span>
<span class="line" id="L215">}</span>
<span class="line" id="L216"></span>
</code></pre></body>
</html>

View file

@ -1,228 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ctlseqs.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Queries</span>
</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> primary_device_attrs = <span class="tok-str">&quot;\x1b[c&quot;</span>;</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> tertiary_device_attrs = <span class="tok-str">&quot;\x1b[=c&quot;</span>;</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> xtversion = <span class="tok-str">&quot;\x1b[&gt;0q&quot;</span>;</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_focus = <span class="tok-str">&quot;\x1b[?1004$p&quot;</span>;</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_sync = <span class="tok-str">&quot;\x1b[?2026$p&quot;</span>;</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_unicode = <span class="tok-str">&quot;\x1b[?2027$p&quot;</span>;</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_color_theme = <span class="tok-str">&quot;\x1b[?2031$p&quot;</span>;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_query = <span class="tok-str">&quot;\x1b[?u&quot;</span>;</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_query = <span class="tok-str">&quot;\x1b_Gi=1,a=q\x1b\\&quot;</span>;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sixel_geometry_query = <span class="tok-str">&quot;\x1b[?2;1;0S&quot;</span>;</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-comment">// mouse</span>
</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mouse_set = <span class="tok-str">&quot;\x1b[?1003;1004;1006h&quot;</span>;</span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mouse_reset = <span class="tok-str">&quot;\x1b[?1003;1004;1006l&quot;</span>;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-comment">// sync</span>
</span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sync_set = <span class="tok-str">&quot;\x1b[?2026h&quot;</span>;</span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sync_reset = <span class="tok-str">&quot;\x1b[?2026l&quot;</span>;</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-comment">// unicode</span>
</span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> unicode_set = <span class="tok-str">&quot;\x1b[?2027h&quot;</span>;</span>
<span class="line" id="L23"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> unicode_reset = <span class="tok-str">&quot;\x1b[?2027l&quot;</span>;</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-comment">// bracketed paste</span>
</span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bp_set = <span class="tok-str">&quot;\x1b[?2004h&quot;</span>;</span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bp_reset = <span class="tok-str">&quot;\x1b[?2004l&quot;</span>;</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-comment">// Key encoding</span>
</span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_push = <span class="tok-str">&quot;\x1b[&gt;{d}u&quot;</span>;</span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_pop = <span class="tok-str">&quot;\x1b[&lt;u&quot;</span>;</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"><span class="tok-comment">// Cursor</span>
</span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> home = <span class="tok-str">&quot;\x1b[H&quot;</span>;</span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> cup = <span class="tok-str">&quot;\x1b[{d};{d}H&quot;</span>;</span>
<span class="line" id="L36"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> hide_cursor = <span class="tok-str">&quot;\x1b[?25l&quot;</span>;</span>
<span class="line" id="L37"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> show_cursor = <span class="tok-str">&quot;\x1b[?25h&quot;</span>;</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-comment">// alt screen</span>
</span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> smcup = <span class="tok-str">&quot;\x1b[?1049h&quot;</span>;</span>
<span class="line" id="L41"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> rmcup = <span class="tok-str">&quot;\x1b[?1049l&quot;</span>;</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"><span class="tok-comment">// sgr reset all</span>
</span>
<span class="line" id="L44"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sgr_reset = <span class="tok-str">&quot;\x1b[m&quot;</span>;</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"><span class="tok-comment">// colors</span>
</span>
<span class="line" id="L47"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_base = <span class="tok-str">&quot;\x1b[3{d}m&quot;</span>;</span>
<span class="line" id="L48"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_bright = <span class="tok-str">&quot;\x1b[9{d}m&quot;</span>;</span>
<span class="line" id="L49"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_base = <span class="tok-str">&quot;\x1b[4{d}m&quot;</span>;</span>
<span class="line" id="L50"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_bright = <span class="tok-str">&quot;\x1b[10{d}m&quot;</span>;</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_reset = <span class="tok-str">&quot;\x1b[39m&quot;</span>;</span>
<span class="line" id="L53"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_reset = <span class="tok-str">&quot;\x1b[49m&quot;</span>;</span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_reset = <span class="tok-str">&quot;\x1b[59m&quot;</span>;</span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_indexed = <span class="tok-str">&quot;\x1b[38:5:{d}m&quot;</span>;</span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_indexed = <span class="tok-str">&quot;\x1b[48:5:{d}m&quot;</span>;</span>
<span class="line" id="L57"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_indexed = <span class="tok-str">&quot;\x1b[58:5:{d}m&quot;</span>;</span>
<span class="line" id="L58"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_rgb = <span class="tok-str">&quot;\x1b[38:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L59"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_rgb = <span class="tok-str">&quot;\x1b[48:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L60"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_rgb = <span class="tok-str">&quot;\x1b[58:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"><span class="tok-comment">// Underlines</span>
</span>
<span class="line" id="L63"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_off = <span class="tok-str">&quot;\x1b[24m&quot;</span>; <span class="tok-comment">// NOTE: this could be \x1b[4:0m but is not as widely supported</span>
</span>
<span class="line" id="L64"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_single = <span class="tok-str">&quot;\x1b[4m&quot;</span>;</span>
<span class="line" id="L65"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_double = <span class="tok-str">&quot;\x1b[4:2m&quot;</span>;</span>
<span class="line" id="L66"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_curly = <span class="tok-str">&quot;\x1b[4:3m&quot;</span>;</span>
<span class="line" id="L67"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_dotted = <span class="tok-str">&quot;\x1b[4:4m&quot;</span>;</span>
<span class="line" id="L68"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_dashed = <span class="tok-str">&quot;\x1b[4:5m&quot;</span>;</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"><span class="tok-comment">// Attributes</span>
</span>
<span class="line" id="L71"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bold_set = <span class="tok-str">&quot;\x1b[1m&quot;</span>;</span>
<span class="line" id="L72"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> dim_set = <span class="tok-str">&quot;\x1b[2m&quot;</span>;</span>
<span class="line" id="L73"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> italic_set = <span class="tok-str">&quot;\x1b[3m&quot;</span>;</span>
<span class="line" id="L74"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> blink_set = <span class="tok-str">&quot;\x1b[5m&quot;</span>;</span>
<span class="line" id="L75"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> reverse_set = <span class="tok-str">&quot;\x1b[7m&quot;</span>;</span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> invisible_set = <span class="tok-str">&quot;\x1b[8m&quot;</span>;</span>
<span class="line" id="L77"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strikethrough_set = <span class="tok-str">&quot;\x1b[9m&quot;</span>;</span>
<span class="line" id="L78"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bold_dim_reset = <span class="tok-str">&quot;\x1b[22m&quot;</span>;</span>
<span class="line" id="L79"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> italic_reset = <span class="tok-str">&quot;\x1b[23m&quot;</span>;</span>
<span class="line" id="L80"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> blink_reset = <span class="tok-str">&quot;\x1b[25m&quot;</span>;</span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> reverse_reset = <span class="tok-str">&quot;\x1b[27m&quot;</span>;</span>
<span class="line" id="L82"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> invisible_reset = <span class="tok-str">&quot;\x1b[28m&quot;</span>;</span>
<span class="line" id="L83"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strikethrough_reset = <span class="tok-str">&quot;\x1b[29m&quot;</span>;</span>
<span class="line" id="L84"></span>
<span class="line" id="L85"><span class="tok-comment">// OSC sequences</span>
</span>
<span class="line" id="L86"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc2_set_title = <span class="tok-str">&quot;\x1b]2;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L87"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc8 = <span class="tok-str">&quot;\x1b]8;{s};{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L88"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc8_clear = <span class="tok-str">&quot;\x1b]8;;\x1b\\&quot;</span>;</span>
<span class="line" id="L89"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc9_notify = <span class="tok-str">&quot;\x1b]9;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L90"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc777_notify = <span class="tok-str">&quot;\x1b]777;notify;{s};{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L91"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc22_mouse_shape = <span class="tok-str">&quot;\x1b]22;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L92"></span>
<span class="line" id="L93"><span class="tok-comment">// Kitty graphics</span>
</span>
<span class="line" id="L94"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_clear = <span class="tok-str">&quot;\x1b_Ga=d\x1b\\&quot;</span>;</span>
<span class="line" id="L95"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_place = <span class="tok-str">&quot;\x1b_Ga=p,i={d},z={d},C=1\x1b\\&quot;</span>;</span>
<span class="line" id="L96"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_scale = <span class="tok-str">&quot;\x1b_Ga=p,i={d},z={d},c={d},r={d},C=1\x1b\\&quot;</span>;</span>
<span class="line" id="L97"></span>
</code></pre></body>
</html>

View file

@ -1,137 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>event.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Key.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">/// The events that Vaxis emits internally</span></span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L6"> key_press: Key,</span>
<span class="line" id="L7"> mouse: Mouse,</span>
<span class="line" id="L8"> focus_in,</span>
<span class="line" id="L9"> focus_out,</span>
<span class="line" id="L10"> paste_start,</span>
<span class="line" id="L11"> paste_end,</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"> <span class="tok-comment">// these are delivered as discovered terminal capabilities</span>
</span>
<span class="line" id="L14"> cap_kitty_keyboard,</span>
<span class="line" id="L15"> cap_kitty_graphics,</span>
<span class="line" id="L16"> cap_rgb,</span>
<span class="line" id="L17"> cap_unicode,</span>
<span class="line" id="L18"> cap_da1,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
</code></pre></body>
</html>

View file

@ -1,185 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>gwidth.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> unicode = std.unicode;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// the method to use when calculating the width of a grapheme</span></span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Method = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L8"> unicode,</span>
<span class="line" id="L9"> wcwidth,</span>
<span class="line" id="L10"> no_zwj,</span>
<span class="line" id="L11">};</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-comment">/// returns the width of the provided string, as measured by the method chosen</span></span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">gwidth</span>(str: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, method: Method) !<span class="tok-type">usize</span> {</span>
<span class="line" id="L15"> <span class="tok-kw">switch</span> (method) {</span>
<span class="line" id="L16"> .unicode =&gt; {</span>
<span class="line" id="L17"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> ziglyph.display_width.strWidth(str, .half);</span>
<span class="line" id="L18"> },</span>
<span class="line" id="L19"> .wcwidth =&gt; {</span>
<span class="line" id="L20"> <span class="tok-kw">var</span> total: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L21"> <span class="tok-kw">const</span> utf8 = <span class="tok-kw">try</span> unicode.Utf8View.init(str);</span>
<span class="line" id="L22"> <span class="tok-kw">var</span> iter = utf8.iterator();</span>
<span class="line" id="L23"></span>
<span class="line" id="L24"> <span class="tok-kw">while</span> (iter.nextCodepoint()) |cp| {</span>
<span class="line" id="L25"> <span class="tok-kw">const</span> w = ziglyph.display_width.codePointWidth(cp, .half);</span>
<span class="line" id="L26"> <span class="tok-kw">if</span> (w &lt; <span class="tok-number">0</span>) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L27"> total += <span class="tok-builtin">@intCast</span>(w);</span>
<span class="line" id="L28"> }</span>
<span class="line" id="L29"> <span class="tok-kw">return</span> total;</span>
<span class="line" id="L30"> },</span>
<span class="line" id="L31"> .no_zwj =&gt; {</span>
<span class="line" id="L32"> <span class="tok-kw">var</span> out: [<span class="tok-number">256</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L33"> <span class="tok-kw">if</span> (str.len &gt; out.len) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.OutOfMemory;</span>
<span class="line" id="L34"> <span class="tok-kw">const</span> n = std.mem.replace(<span class="tok-type">u8</span>, str, <span class="tok-str">&quot;\u{200D}&quot;</span>, <span class="tok-str">&quot;&quot;</span>, &amp;out);</span>
<span class="line" id="L35"> <span class="tok-kw">return</span> gwidth(out[<span class="tok-number">0</span>..n], .unicode);</span>
<span class="line" id="L36"> },</span>
<span class="line" id="L37"> }</span>
<span class="line" id="L38">}</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: a&quot;</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .unicode));</span>
<span class="line" id="L42"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .wcwidth));</span>
<span class="line" id="L43"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .no_zwj));</span>
<span class="line" id="L44">}</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with ZWJ&quot;</span> {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .unicode));</span>
<span class="line" id="L48"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .wcwidth));</span>
<span class="line" id="L49"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .no_zwj));</span>
<span class="line" id="L50">}</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with VS16 selector&quot;</span> {</span>
<span class="line" id="L53"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .unicode));</span>
<span class="line" id="L54"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .wcwidth));</span>
<span class="line" id="L55"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .no_zwj));</span>
<span class="line" id="L56">}</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with skin tone selector&quot;</span> {</span>
<span class="line" id="L59"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .unicode));</span>
<span class="line" id="L60"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .wcwidth));</span>
<span class="line" id="L61"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .no_zwj));</span>
<span class="line" id="L62">}</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: invalid string&quot;</span> {</span>
<span class="line" id="L65"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .unicode));</span>
<span class="line" id="L66"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .wcwidth));</span>
<span class="line" id="L67"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .no_zwj));</span>
<span class="line" id="L68">}</span>
<span class="line" id="L69"></span>
</code></pre></body>
</html>

View file

@ -1,139 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>main.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Vaxis = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;vaxis.zig&quot;</span>).Vaxis;</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Options = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Options.zig&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Key.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Style = Cell.Style;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>);</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Winsize = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Tty.zig&quot;</span>).Winsize;</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> widgets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets.zig&quot;</span>);</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-comment">/// Initialize a Vaxis application.</span></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(<span class="tok-kw">comptime</span> Event: <span class="tok-type">type</span>, opts: Options) !Vaxis(Event) {</span>
<span class="line" id="L17"> <span class="tok-kw">return</span> Vaxis(Event).init(opts);</span>
<span class="line" id="L18">}</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-kw">test</span> {</span>
<span class="line" id="L21"> std.testing.refAllDecls(<span class="tok-builtin">@This</span>());</span>
<span class="line" id="L22">}</span>
<span class="line" id="L23"></span>
</code></pre></body>
</html>

View file

@ -1,244 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>queue.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> atomic = std.atomic;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Futex = std.Thread.Futex;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> log = std.log.scoped(.queue);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Thread safe. Fixed size. Blocking push and pop.</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Queue</span>(</span>
<span class="line" id="L10"> <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>,</span>
<span class="line" id="L11"> <span class="tok-kw">comptime</span> size: <span class="tok-type">usize</span>,</span>
<span class="line" id="L12">) <span class="tok-type">type</span> {</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L14"> buf: [size]T = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> read_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17"> write_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> mutex: std.Thread.Mutex = .{},</span>
<span class="line" id="L20"> <span class="tok-comment">// blocks when the buffer is full or empty</span>
</span>
<span class="line" id="L21"> futex: atomic.Value(<span class="tok-type">u32</span>) = atomic.Value(<span class="tok-type">u32</span>).init(<span class="tok-number">0</span>),</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> <span class="tok-comment">/// pop an item from the queue. Blocks until an item is available</span></span>
<span class="line" id="L26"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pop</span>(self: *Self) T {</span>
<span class="line" id="L27"> self.mutex.lock();</span>
<span class="line" id="L28"> <span class="tok-kw">defer</span> self.mutex.unlock();</span>
<span class="line" id="L29"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L30"> <span class="tok-comment">// If we don't have any items, we unlock and wait</span>
</span>
<span class="line" id="L31"> self.mutex.unlock();</span>
<span class="line" id="L32"> Futex.wait(&amp;self.futex, <span class="tok-number">0</span>);</span>
<span class="line" id="L33"> <span class="tok-comment">// regain our lock</span>
</span>
<span class="line" id="L34"> self.mutex.lock();</span>
<span class="line" id="L35"> }</span>
<span class="line" id="L36"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L37"> <span class="tok-comment">// If we are full, wake up the push</span>
</span>
<span class="line" id="L38"> Futex.wake(&amp;self.futex, <span class="tok-number">1</span>);</span>
<span class="line" id="L39"> }</span>
<span class="line" id="L40"> <span class="tok-kw">const</span> i = self.read_index;</span>
<span class="line" id="L41"> self.read_index += <span class="tok-number">1</span>;</span>
<span class="line" id="L42"> self.read_index = self.read_index % self.buf.len;</span>
<span class="line" id="L43"> <span class="tok-kw">return</span> self.buf[i];</span>
<span class="line" id="L44"> }</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-comment">/// push an item into the queue. Blocks until the item has been put in</span></span>
<span class="line" id="L47"> <span class="tok-comment">/// the queue</span></span>
<span class="line" id="L48"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">push</span>(self: *Self, item: T) <span class="tok-type">void</span> {</span>
<span class="line" id="L49"> self.mutex.lock();</span>
<span class="line" id="L50"> <span class="tok-kw">defer</span> self.mutex.unlock();</span>
<span class="line" id="L51"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L52"> self.mutex.unlock();</span>
<span class="line" id="L53"> Futex.wait(&amp;self.futex, <span class="tok-number">0</span>);</span>
<span class="line" id="L54"> self.mutex.lock();</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L57"> Futex.wake(&amp;self.futex, <span class="tok-number">1</span>);</span>
<span class="line" id="L58"> }</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> i = self.write_index;</span>
<span class="line" id="L60"> self.write_index += <span class="tok-number">1</span>;</span>
<span class="line" id="L61"> self.write_index = self.write_index % self.buf.len;</span>
<span class="line" id="L62"> self.buf[i] = item;</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> <span class="tok-comment">/// push an item into the queue. Returns true when the item was</span></span>
<span class="line" id="L66"> <span class="tok-comment">/// successfully placed in the queue</span></span>
<span class="line" id="L67"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">tryPush</span>(self: *Self, item: T) <span class="tok-type">bool</span> {</span>
<span class="line" id="L68"> self.mutex.lock();</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L70"> self.mutex.unlock();</span>
<span class="line" id="L71"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"> self.mutex.unlock();</span>
<span class="line" id="L74"> self.push(item);</span>
<span class="line" id="L75"> <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L76"> }</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-comment">/// pop an item from the queue. Returns null when no item is available</span></span>
<span class="line" id="L79"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">tryPop</span>(self: *Self) ?T {</span>
<span class="line" id="L80"> self.mutex.lock();</span>
<span class="line" id="L81"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L82"> self.mutex.unlock();</span>
<span class="line" id="L83"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L84"> }</span>
<span class="line" id="L85"> self.mutex.unlock();</span>
<span class="line" id="L86"> <span class="tok-kw">return</span> self.pop();</span>
<span class="line" id="L87"> }</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"> <span class="tok-comment">/// Returns `true` if the ring buffer is empty and `false` otherwise.</span></span>
<span class="line" id="L90"> <span class="tok-kw">fn</span> <span class="tok-fn">isEmpty</span>(self: Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L91"> <span class="tok-kw">return</span> self.write_index == self.read_index;</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-comment">/// Returns `true` if the ring buffer is full and `false` otherwise.</span></span>
<span class="line" id="L95"> <span class="tok-kw">fn</span> <span class="tok-fn">isFull</span>(self: Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> self.mask2(self.write_index + self.buf.len) == self.read_index;</span>
<span class="line" id="L97"> }</span>
<span class="line" id="L98"></span>
<span class="line" id="L99"> <span class="tok-comment">/// Returns the length</span></span>
<span class="line" id="L100"> <span class="tok-kw">fn</span> <span class="tok-fn">len</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L101"> <span class="tok-kw">const</span> wrap_offset = <span class="tok-number">2</span> * self.buf.len * <span class="tok-builtin">@intFromBool</span>(self.write_index &lt; self.read_index);</span>
<span class="line" id="L102"> <span class="tok-kw">const</span> adjusted_write_index = self.write_index + wrap_offset;</span>
<span class="line" id="L103"> <span class="tok-kw">return</span> adjusted_write_index - self.read_index;</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"> <span class="tok-comment">/// Returns `index` modulo the length of the backing slice.</span></span>
<span class="line" id="L107"> <span class="tok-kw">fn</span> <span class="tok-fn">mask</span>(self: Self, index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L108"> <span class="tok-kw">return</span> index % self.buf.len;</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-comment">/// Returns `index` modulo twice the length of the backing slice.</span></span>
<span class="line" id="L112"> <span class="tok-kw">fn</span> <span class="tok-fn">mask2</span>(self: Self, index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L113"> <span class="tok-kw">return</span> index % (<span class="tok-number">2</span> * self.buf.len);</span>
<span class="line" id="L114"> }</span>
<span class="line" id="L115"> };</span>
<span class="line" id="L116">}</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"><span class="tok-kw">test</span> <span class="tok-str">&quot;Queue: simple push / pop&quot;</span> {</span>
<span class="line" id="L119"> <span class="tok-kw">var</span> queue: Queue(<span class="tok-type">u8</span>, <span class="tok-number">16</span>) = .{};</span>
<span class="line" id="L120"> queue.push(<span class="tok-number">1</span>);</span>
<span class="line" id="L121"> <span class="tok-kw">const</span> pop = queue.pop();</span>
<span class="line" id="L122"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">1</span>, pop);</span>
<span class="line" id="L123">}</span>
<span class="line" id="L124"></span>
</code></pre></body>
</html>

View file

@ -1,851 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>vaxis.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> atomic = std.atomic;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> base64 = std.base64.standard.Encoder;</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> Queue = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;queue.zig&quot;</span>).Queue;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> ctlseqs = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ctlseqs.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Tty = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Tty.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Winsize = Tty.Winsize;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Key.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> Screen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Screen.zig&quot;</span>);</span>
<span class="line" id="L11"><span class="tok-kw">const</span> InternalScreen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;InternalScreen.zig&quot;</span>);</span>
<span class="line" id="L12"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Window.zig&quot;</span>);</span>
<span class="line" id="L13"><span class="tok-kw">const</span> Options = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Options.zig&quot;</span>);</span>
<span class="line" id="L14"><span class="tok-kw">const</span> Style = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Style;</span>
<span class="line" id="L15"><span class="tok-kw">const</span> Hyperlink = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Hyperlink;</span>
<span class="line" id="L16"><span class="tok-kw">const</span> gwidth = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;gwidth.zig&quot;</span>);</span>
<span class="line" id="L17"><span class="tok-kw">const</span> Shape = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>).Shape;</span>
<span class="line" id="L18"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L19"><span class="tok-kw">const</span> zigimg = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zigimg&quot;</span>);</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-comment">/// Vaxis is the entrypoint for a Vaxis application. The provided type T should</span></span>
<span class="line" id="L22"><span class="tok-comment">/// be a tagged union which contains all of the events the application will</span></span>
<span class="line" id="L23"><span class="tok-comment">/// handle. Vaxis will look for the following fields on the union and, if</span></span>
<span class="line" id="L24"><span class="tok-comment">/// found, emit them via the &quot;nextEvent&quot; method</span></span>
<span class="line" id="L25"><span class="tok-comment">///</span></span>
<span class="line" id="L26"><span class="tok-comment">/// The following events are available:</span></span>
<span class="line" id="L27"><span class="tok-comment">/// - `key_press: Key`, for key press events</span></span>
<span class="line" id="L28"><span class="tok-comment">/// - `winsize: Winsize`, for resize events. Must call app.resize when receiving</span></span>
<span class="line" id="L29"><span class="tok-comment">/// this event</span></span>
<span class="line" id="L30"><span class="tok-comment">/// - `focus_in` and `focus_out` for focus events</span></span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Vaxis</span>(<span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L32"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L33"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"> <span class="tok-kw">const</span> log = std.log.scoped(.vaxis);</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Event = T;</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Capabilities = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L40"> kitty_keyboard: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L41"> kitty_graphics: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L42"> rgb: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L43"> unicode: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L44"> };</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-comment">/// the event queue for Vaxis</span></span>
<span class="line" id="L47"> <span class="tok-comment">//</span>
</span>
<span class="line" id="L48"> <span class="tok-comment">// TODO: is 512 ok?</span>
</span>
<span class="line" id="L49"> queue: Queue(T, <span class="tok-number">512</span>),</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"> tty: ?Tty,</span>
<span class="line" id="L52"></span>
<span class="line" id="L53"> <span class="tok-comment">/// the screen we write to</span></span>
<span class="line" id="L54"> screen: Screen,</span>
<span class="line" id="L55"> <span class="tok-comment">/// The last screen we drew. We keep this so we can efficiently update on</span></span>
<span class="line" id="L56"> <span class="tok-comment">/// the next render</span></span>
<span class="line" id="L57"> screen_last: InternalScreen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"> state: <span class="tok-kw">struct</span> {</span>
<span class="line" id="L60"> <span class="tok-comment">/// if we are in the alt screen</span></span>
<span class="line" id="L61"> alt_screen: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L62"> <span class="tok-comment">/// if we have entered kitty keyboard</span></span>
<span class="line" id="L63"> kitty_keyboard: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L64"> bracketed_paste: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L65"> mouse: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L66"> } = .{},</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> caps: Capabilities = .{},</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-comment">/// if we should redraw the entire screen on the next render</span></span>
<span class="line" id="L71"> refresh: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"> <span class="tok-comment">/// blocks the main thread until a DA1 query has been received, or the</span></span>
<span class="line" id="L74"> <span class="tok-comment">/// futex times out</span></span>
<span class="line" id="L75"> query_futex: atomic.Value(<span class="tok-type">u32</span>) = atomic.Value(<span class="tok-type">u32</span>).init(<span class="tok-number">0</span>),</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"> <span class="tok-comment">// images</span>
</span>
<span class="line" id="L78"> next_img_id: <span class="tok-type">u32</span> = <span class="tok-number">1</span>,</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"> <span class="tok-comment">// statistics</span>
</span>
<span class="line" id="L81"> renders: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L82"> render_dur: <span class="tok-type">i128</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L83"></span>
<span class="line" id="L84"> <span class="tok-comment">/// Initialize Vaxis with runtime options</span></span>
<span class="line" id="L85"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(_: Options) !Self {</span>
<span class="line" id="L86"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L87"> .queue = .{},</span>
<span class="line" id="L88"> .tty = <span class="tok-null">null</span>,</span>
<span class="line" id="L89"> .screen = .{},</span>
<span class="line" id="L90"> .screen_last = .{},</span>
<span class="line" id="L91"> };</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-comment">/// Resets the terminal to it's original state. If an allocator is</span></span>
<span class="line" id="L95"> <span class="tok-comment">/// passed, this will free resources associated with Vaxis. This is left as an</span></span>
<span class="line" id="L96"> <span class="tok-comment">/// optional so applications can choose to not free resources when the</span></span>
<span class="line" id="L97"> <span class="tok-comment">/// application will be exiting anyways</span></span>
<span class="line" id="L98"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self, alloc: ?std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L99"> <span class="tok-kw">if</span> (self.tty) |_| {</span>
<span class="line" id="L100"> <span class="tok-kw">var</span> tty = &amp;self.tty.?;</span>
<span class="line" id="L101"> <span class="tok-kw">if</span> (self.state.kitty_keyboard) {</span>
<span class="line" id="L102"> _ = tty.write(ctlseqs.csi_u_pop) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L103"> }</span>
<span class="line" id="L104"> <span class="tok-kw">if</span> (self.state.mouse) {</span>
<span class="line" id="L105"> _ = tty.write(ctlseqs.mouse_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L106"> }</span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (self.state.bracketed_paste) {</span>
<span class="line" id="L108"> _ = tty.write(ctlseqs.bp_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"> <span class="tok-kw">if</span> (self.state.alt_screen) {</span>
<span class="line" id="L111"> _ = tty.write(ctlseqs.rmcup) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L112"> }</span>
<span class="line" id="L113"> tty.flush() <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L114"> tty.deinit();</span>
<span class="line" id="L115"> }</span>
<span class="line" id="L116"> <span class="tok-kw">if</span> (alloc) |a| {</span>
<span class="line" id="L117"> self.screen.deinit(a);</span>
<span class="line" id="L118"> self.screen_last.deinit(a);</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (self.renders &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L121"> <span class="tok-kw">const</span> tpr = <span class="tok-builtin">@divTrunc</span>(self.render_dur, self.renders);</span>
<span class="line" id="L122"> log.info(<span class="tok-str">&quot;total renders = {d}&quot;</span>, .{self.renders});</span>
<span class="line" id="L123"> log.info(<span class="tok-str">&quot;microseconds per render = {d}&quot;</span>, .{tpr});</span>
<span class="line" id="L124"> }</span>
<span class="line" id="L125"> }</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"> <span class="tok-comment">/// spawns the input thread to start listening to the tty for input</span></span>
<span class="line" id="L128"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">startReadThread</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L129"> self.tty = <span class="tok-kw">try</span> Tty.init();</span>
<span class="line" id="L130"> <span class="tok-comment">// run our tty read loop in it's own thread</span>
</span>
<span class="line" id="L131"> <span class="tok-kw">const</span> read_thread = <span class="tok-kw">try</span> std.Thread.spawn(.{}, Tty.run, .{ &amp;self.tty.?, T, self });</span>
<span class="line" id="L132"> <span class="tok-kw">try</span> read_thread.setName(<span class="tok-str">&quot;tty&quot;</span>);</span>
<span class="line" id="L133"> }</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"> <span class="tok-comment">/// stops reading from the tty</span></span>
<span class="line" id="L136"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stopReadThread</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L137"> <span class="tok-kw">if</span> (self.tty) |_| {</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> tty = &amp;self.tty.?;</span>
<span class="line" id="L139"> tty.stop();</span>
<span class="line" id="L140"> }</span>
<span class="line" id="L141"> }</span>
<span class="line" id="L142"></span>
<span class="line" id="L143"> <span class="tok-comment">/// returns the next available event, blocking until one is available</span></span>
<span class="line" id="L144"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">nextEvent</span>(self: *Self) T {</span>
<span class="line" id="L145"> <span class="tok-kw">return</span> self.queue.pop();</span>
<span class="line" id="L146"> }</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> <span class="tok-comment">/// posts an event into the event queue. Will block if there is not</span></span>
<span class="line" id="L149"> <span class="tok-comment">/// capacity for the event</span></span>
<span class="line" id="L150"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">postEvent</span>(self: *Self, event: T) <span class="tok-type">void</span> {</span>
<span class="line" id="L151"> self.queue.push(event);</span>
<span class="line" id="L152"> }</span>
<span class="line" id="L153"></span>
<span class="line" id="L154"> <span class="tok-comment">/// resize allocates a slice of cells equal to the number of cells</span></span>
<span class="line" id="L155"> <span class="tok-comment">/// required to display the screen (ie width x height). Any previous screen is</span></span>
<span class="line" id="L156"> <span class="tok-comment">/// freed when resizing</span></span>
<span class="line" id="L157"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">resize</span>(self: *Self, alloc: std.mem.Allocator, winsize: Winsize) !<span class="tok-type">void</span> {</span>
<span class="line" id="L158"> log.debug(<span class="tok-str">&quot;resizing screen: width={d} height={d}&quot;</span>, .{ winsize.cols, winsize.rows });</span>
<span class="line" id="L159"> self.screen.deinit(alloc);</span>
<span class="line" id="L160"> self.screen = <span class="tok-kw">try</span> Screen.init(alloc, winsize);</span>
<span class="line" id="L161"> self.screen.unicode = self.caps.unicode;</span>
<span class="line" id="L162"> <span class="tok-comment">// try self.screen.int(alloc, winsize.cols, winsize.rows);</span>
</span>
<span class="line" id="L163"> <span class="tok-comment">// we only init our current screen. This has the effect of redrawing</span>
</span>
<span class="line" id="L164"> <span class="tok-comment">// every cell</span>
</span>
<span class="line" id="L165"> self.screen_last.deinit(alloc);</span>
<span class="line" id="L166"> self.screen_last = <span class="tok-kw">try</span> InternalScreen.init(alloc, winsize.cols, winsize.rows);</span>
<span class="line" id="L167"> <span class="tok-comment">// try self.screen_last.resize(alloc, winsize.cols, winsize.rows);</span>
</span>
<span class="line" id="L168"> }</span>
<span class="line" id="L169"></span>
<span class="line" id="L170"> <span class="tok-comment">/// returns a Window comprising of the entire terminal screen</span></span>
<span class="line" id="L171"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">window</span>(self: *Self) Window {</span>
<span class="line" id="L172"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L173"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L174"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L175"> .width = self.screen.width,</span>
<span class="line" id="L176"> .height = self.screen.height,</span>
<span class="line" id="L177"> .screen = &amp;self.screen,</span>
<span class="line" id="L178"> };</span>
<span class="line" id="L179"> }</span>
<span class="line" id="L180"></span>
<span class="line" id="L181"> <span class="tok-comment">/// enter the alternate screen. The alternate screen will automatically</span></span>
<span class="line" id="L182"> <span class="tok-comment">/// be exited if calling deinit while in the alt screen</span></span>
<span class="line" id="L183"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">enterAltScreen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L184"> <span class="tok-kw">if</span> (self.state.alt_screen) <span class="tok-kw">return</span>;</span>
<span class="line" id="L185"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L186"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.smcup);</span>
<span class="line" id="L187"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L188"> self.state.alt_screen = <span class="tok-null">true</span>;</span>
<span class="line" id="L189"> }</span>
<span class="line" id="L190"></span>
<span class="line" id="L191"> <span class="tok-comment">/// exit the alternate screen</span></span>
<span class="line" id="L192"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">exitAltScreen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L193"> <span class="tok-kw">if</span> (!self.state.alt_screen) <span class="tok-kw">return</span>;</span>
<span class="line" id="L194"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L195"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.rmcup);</span>
<span class="line" id="L196"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L197"> self.state.alt_screen = <span class="tok-null">false</span>;</span>
<span class="line" id="L198"> }</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"> <span class="tok-comment">/// write queries to the terminal to determine capabilities. Individual</span></span>
<span class="line" id="L201"> <span class="tok-comment">/// capabilities will be delivered to the client and possibly intercepted by</span></span>
<span class="line" id="L202"> <span class="tok-comment">/// Vaxis to enable features</span></span>
<span class="line" id="L203"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">queryTerminal</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L205"></span>
<span class="line" id="L206"> <span class="tok-kw">const</span> colorterm = std.os.getenv(<span class="tok-str">&quot;COLORTERM&quot;</span>) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;&quot;</span>;</span>
<span class="line" id="L207"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, colorterm, <span class="tok-str">&quot;truecolor&quot;</span>) <span class="tok-kw">or</span></span>
<span class="line" id="L208"> std.mem.eql(<span class="tok-type">u8</span>, colorterm, <span class="tok-str">&quot;24bit&quot;</span>))</span>
<span class="line" id="L209"> {</span>
<span class="line" id="L210"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;cap_rgb&quot;</span>)) {</span>
<span class="line" id="L211"> self.postEvent(.cap_rgb);</span>
<span class="line" id="L212"> }</span>
<span class="line" id="L213"> }</span>
<span class="line" id="L214"></span>
<span class="line" id="L215"> <span class="tok-comment">// TODO: decide if we actually want to query for focus and sync. It</span>
</span>
<span class="line" id="L216"> <span class="tok-comment">// doesn't hurt to blindly use them</span>
</span>
<span class="line" id="L217"> <span class="tok-comment">// _ = try tty.write(ctlseqs.decrqm_focus);</span>
</span>
<span class="line" id="L218"> <span class="tok-comment">// _ = try tty.write(ctlseqs.decrqm_sync);</span>
</span>
<span class="line" id="L219"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.decrqm_unicode);</span>
<span class="line" id="L220"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.decrqm_color_theme);</span>
<span class="line" id="L221"> <span class="tok-comment">// TODO: XTVERSION has a DCS response. uncomment when we can parse</span>
</span>
<span class="line" id="L222"> <span class="tok-comment">// that</span>
</span>
<span class="line" id="L223"> <span class="tok-comment">// _ = try tty.write(ctlseqs.xtversion);</span>
</span>
<span class="line" id="L224"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.csi_u_query);</span>
<span class="line" id="L225"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.kitty_graphics_query);</span>
<span class="line" id="L226"> <span class="tok-comment">// TODO: sixel geometry query interferes with F4 keys.</span>
</span>
<span class="line" id="L227"> <span class="tok-comment">// _ = try tty.write(ctlseqs.sixel_geometry_query);</span>
</span>
<span class="line" id="L228"></span>
<span class="line" id="L229"> <span class="tok-comment">// TODO: XTGETTCAP queries (&quot;RGB&quot;, &quot;Smulx&quot;)</span>
</span>
<span class="line" id="L230"></span>
<span class="line" id="L231"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.primary_device_attrs);</span>
<span class="line" id="L232"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L233"></span>
<span class="line" id="L234"> <span class="tok-comment">// 1 second timeout</span>
</span>
<span class="line" id="L235"> std.Thread.Futex.timedWait(&amp;self.query_futex, <span class="tok-number">0</span>, <span class="tok-number">1</span> * std.time.ns_per_s) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L236"></span>
<span class="line" id="L237"> <span class="tok-comment">// enable detected features</span>
</span>
<span class="line" id="L238"> <span class="tok-kw">if</span> (self.caps.kitty_keyboard) {</span>
<span class="line" id="L239"> <span class="tok-kw">try</span> self.enableKittyKeyboard(.{});</span>
<span class="line" id="L240"> }</span>
<span class="line" id="L241"> <span class="tok-kw">if</span> (self.caps.unicode) {</span>
<span class="line" id="L242"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.unicode_set);</span>
<span class="line" id="L243"> }</span>
<span class="line" id="L244"> }</span>
<span class="line" id="L245"></span>
<span class="line" id="L246"> <span class="tok-comment">// the next render call will refresh the entire screen</span>
</span>
<span class="line" id="L247"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">queueRefresh</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L248"> self.refresh = <span class="tok-null">true</span>;</span>
<span class="line" id="L249"> }</span>
<span class="line" id="L250"></span>
<span class="line" id="L251"> <span class="tok-comment">/// draws the screen to the terminal</span></span>
<span class="line" id="L252"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">render</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L253"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L254"> self.renders += <span class="tok-number">1</span>;</span>
<span class="line" id="L255"> <span class="tok-kw">const</span> timer_start = std.time.microTimestamp();</span>
<span class="line" id="L256"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L257"> self.render_dur += std.time.microTimestamp() - timer_start;</span>
<span class="line" id="L258"> }</span>
<span class="line" id="L259"></span>
<span class="line" id="L260"> <span class="tok-kw">defer</span> self.refresh = <span class="tok-null">false</span>;</span>
<span class="line" id="L261"> <span class="tok-kw">defer</span> tty.flush() <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L262"></span>
<span class="line" id="L263"> <span class="tok-comment">// Set up sync before we write anything</span>
</span>
<span class="line" id="L264"> <span class="tok-comment">// TODO: optimize sync so we only sync _when we have changes_. This</span>
</span>
<span class="line" id="L265"> <span class="tok-comment">// requires a smarter buffered writer, we'll probably have to write</span>
</span>
<span class="line" id="L266"> <span class="tok-comment">// our own</span>
</span>
<span class="line" id="L267"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.sync_set);</span>
<span class="line" id="L268"> <span class="tok-kw">defer</span> _ = tty.write(ctlseqs.sync_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L269"></span>
<span class="line" id="L270"> <span class="tok-comment">// Send the cursor to 0,0</span>
</span>
<span class="line" id="L271"> <span class="tok-comment">// TODO: this needs to move after we optimize writes. We only do</span>
</span>
<span class="line" id="L272"> <span class="tok-comment">// this if we have an update to make. We also need to hide cursor</span>
</span>
<span class="line" id="L273"> <span class="tok-comment">// and then reshow it if needed</span>
</span>
<span class="line" id="L274"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.hide_cursor);</span>
<span class="line" id="L275"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.home);</span>
<span class="line" id="L276"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.sgr_reset);</span>
<span class="line" id="L277"></span>
<span class="line" id="L278"> <span class="tok-comment">// initialize some variables</span>
</span>
<span class="line" id="L279"> <span class="tok-kw">var</span> reposition: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L280"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L281"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L282"> <span class="tok-kw">var</span> cursor: Style = .{};</span>
<span class="line" id="L283"> <span class="tok-kw">var</span> link: Hyperlink = .{};</span>
<span class="line" id="L284"></span>
<span class="line" id="L285"> <span class="tok-comment">// Clear all images</span>
</span>
<span class="line" id="L286"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.kitty_graphics_clear);</span>
<span class="line" id="L287"></span>
<span class="line" id="L288"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L289"> <span class="tok-kw">while</span> (i &lt; self.screen.buf.len) {</span>
<span class="line" id="L290"> <span class="tok-kw">const</span> cell = self.screen.buf[i];</span>
<span class="line" id="L291"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L292"> <span class="tok-comment">// advance by the width of this char mod 1</span>
</span>
<span class="line" id="L293"> <span class="tok-kw">const</span> w = blk: {</span>
<span class="line" id="L294"> <span class="tok-kw">if</span> (cell.char.width != <span class="tok-number">0</span>) <span class="tok-kw">break</span> :blk cell.char.width;</span>
<span class="line" id="L295"></span>
<span class="line" id="L296"> <span class="tok-kw">const</span> method: gwidth.Method = <span class="tok-kw">if</span> (self.caps.unicode) .unicode <span class="tok-kw">else</span> .wcwidth;</span>
<span class="line" id="L297"> <span class="tok-kw">break</span> :blk gwidth.gwidth(cell.char.grapheme, method) <span class="tok-kw">catch</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L298"> };</span>
<span class="line" id="L299"> <span class="tok-kw">var</span> j = i + <span class="tok-number">1</span>;</span>
<span class="line" id="L300"> <span class="tok-kw">while</span> (j &lt; i + w) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L301"> self.screen_last.buf[j].skipped = <span class="tok-null">true</span>;</span>
<span class="line" id="L302"> }</span>
<span class="line" id="L303"> col += w;</span>
<span class="line" id="L304"> i += w;</span>
<span class="line" id="L305"> }</span>
<span class="line" id="L306"> <span class="tok-kw">if</span> (col &gt;= self.screen.width) {</span>
<span class="line" id="L307"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L308"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L309"> }</span>
<span class="line" id="L310"> <span class="tok-comment">// If cell is the same as our last frame, we don't need to do</span>
</span>
<span class="line" id="L311"> <span class="tok-comment">// anything</span>
</span>
<span class="line" id="L312"> <span class="tok-kw">const</span> last = self.screen_last.buf[i];</span>
<span class="line" id="L313"> <span class="tok-kw">if</span> (!self.refresh <span class="tok-kw">and</span> last.eql(cell) <span class="tok-kw">and</span> !last.skipped <span class="tok-kw">and</span> cell.image == <span class="tok-null">null</span>) {</span>
<span class="line" id="L314"> reposition = <span class="tok-null">true</span>;</span>
<span class="line" id="L315"> <span class="tok-comment">// Close any osc8 sequence we might be in before</span>
</span>
<span class="line" id="L316"> <span class="tok-comment">// repositioning</span>
</span>
<span class="line" id="L317"> <span class="tok-kw">if</span> (link.uri.len &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L318"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.osc8_clear);</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L321"> }</span>
<span class="line" id="L322"> self.screen_last.buf[i].skipped = <span class="tok-null">false</span>;</span>
<span class="line" id="L323"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L324"> cursor = cell.style;</span>
<span class="line" id="L325"> link = cell.link;</span>
<span class="line" id="L326"> }</span>
<span class="line" id="L327"> <span class="tok-comment">// Set this cell in the last frame</span>
</span>
<span class="line" id="L328"> self.screen_last.writeCell(col, row, cell);</span>
<span class="line" id="L329"></span>
<span class="line" id="L330"> <span class="tok-comment">// reposition the cursor, if needed</span>
</span>
<span class="line" id="L331"> <span class="tok-kw">if</span> (reposition) {</span>
<span class="line" id="L332"> <span class="tok-kw">try</span> std.fmt.format(tty.buffered_writer.writer(), ctlseqs.cup, .{ row + <span class="tok-number">1</span>, col + <span class="tok-number">1</span> });</span>
<span class="line" id="L333"> }</span>
<span class="line" id="L334"></span>
<span class="line" id="L335"> <span class="tok-kw">if</span> (cell.image) |img| {</span>
<span class="line" id="L336"> <span class="tok-kw">if</span> (img.size) |size| {</span>
<span class="line" id="L337"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L338"> tty.buffered_writer.writer(),</span>
<span class="line" id="L339"> ctlseqs.kitty_graphics_scale,</span>
<span class="line" id="L340"> .{ img.img_id, img.z_index, size.cols, size.rows },</span>
<span class="line" id="L341"> );</span>
<span class="line" id="L342"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L343"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L344"> tty.buffered_writer.writer(),</span>
<span class="line" id="L345"> ctlseqs.kitty_graphics_place,</span>
<span class="line" id="L346"> .{ img.img_id, img.z_index },</span>
<span class="line" id="L347"> );</span>
<span class="line" id="L348"> }</span>
<span class="line" id="L349"> }</span>
<span class="line" id="L350"></span>
<span class="line" id="L351"> <span class="tok-comment">// something is different, so let's loop through everything and</span>
</span>
<span class="line" id="L352"> <span class="tok-comment">// find out what</span>
</span>
<span class="line" id="L353"></span>
<span class="line" id="L354"> <span class="tok-comment">// foreground</span>
</span>
<span class="line" id="L355"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.fg, cell.style.fg)) {</span>
<span class="line" id="L356"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L357"> <span class="tok-kw">switch</span> (cell.style.fg) {</span>
<span class="line" id="L358"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.fg_reset),</span>
<span class="line" id="L359"> .index =&gt; |idx| {</span>
<span class="line" id="L360"> <span class="tok-kw">switch</span> (idx) {</span>
<span class="line" id="L361"> <span class="tok-number">0</span>...<span class="tok-number">7</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_base, .{idx}),</span>
<span class="line" id="L362"> <span class="tok-number">8</span>...<span class="tok-number">15</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_bright, .{idx - <span class="tok-number">8</span>}),</span>
<span class="line" id="L363"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_indexed, .{idx}),</span>
<span class="line" id="L364"> }</span>
<span class="line" id="L365"> },</span>
<span class="line" id="L366"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L367"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L368"> },</span>
<span class="line" id="L369"> }</span>
<span class="line" id="L370"> }</span>
<span class="line" id="L371"> <span class="tok-comment">// background</span>
</span>
<span class="line" id="L372"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.bg, cell.style.bg)) {</span>
<span class="line" id="L373"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L374"> <span class="tok-kw">switch</span> (cell.style.bg) {</span>
<span class="line" id="L375"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.bg_reset),</span>
<span class="line" id="L376"> .index =&gt; |idx| {</span>
<span class="line" id="L377"> <span class="tok-kw">switch</span> (idx) {</span>
<span class="line" id="L378"> <span class="tok-number">0</span>...<span class="tok-number">7</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_base, .{idx}),</span>
<span class="line" id="L379"> <span class="tok-number">8</span>...<span class="tok-number">15</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_bright, .{idx - <span class="tok-number">8</span>}),</span>
<span class="line" id="L380"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_indexed, .{idx}),</span>
<span class="line" id="L381"> }</span>
<span class="line" id="L382"> },</span>
<span class="line" id="L383"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L384"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L385"> },</span>
<span class="line" id="L386"> }</span>
<span class="line" id="L387"> }</span>
<span class="line" id="L388"> <span class="tok-comment">// underline color</span>
</span>
<span class="line" id="L389"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.ul, cell.style.ul)) {</span>
<span class="line" id="L390"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L391"> <span class="tok-kw">switch</span> (cell.style.bg) {</span>
<span class="line" id="L392"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.ul_reset),</span>
<span class="line" id="L393"> .index =&gt; |idx| {</span>
<span class="line" id="L394"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.ul_indexed, .{idx});</span>
<span class="line" id="L395"> },</span>
<span class="line" id="L396"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L397"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.ul_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L398"> },</span>
<span class="line" id="L399"> }</span>
<span class="line" id="L400"> }</span>
<span class="line" id="L401"> <span class="tok-comment">// underline style</span>
</span>
<span class="line" id="L402"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.ul_style, cell.style.ul_style)) {</span>
<span class="line" id="L403"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.ul_style) {</span>
<span class="line" id="L404"> .off =&gt; ctlseqs.ul_off,</span>
<span class="line" id="L405"> .single =&gt; ctlseqs.ul_single,</span>
<span class="line" id="L406"> .double =&gt; ctlseqs.ul_double,</span>
<span class="line" id="L407"> .curly =&gt; ctlseqs.ul_curly,</span>
<span class="line" id="L408"> .dotted =&gt; ctlseqs.ul_dotted,</span>
<span class="line" id="L409"> .dashed =&gt; ctlseqs.ul_dashed,</span>
<span class="line" id="L410"> };</span>
<span class="line" id="L411"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L412"> }</span>
<span class="line" id="L413"> <span class="tok-comment">// bold</span>
</span>
<span class="line" id="L414"> <span class="tok-kw">if</span> (cursor.bold != cell.style.bold) {</span>
<span class="line" id="L415"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.bold) {</span>
<span class="line" id="L416"> <span class="tok-null">true</span> =&gt; ctlseqs.bold_set,</span>
<span class="line" id="L417"> <span class="tok-null">false</span> =&gt; ctlseqs.bold_dim_reset,</span>
<span class="line" id="L418"> };</span>
<span class="line" id="L419"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L420"> <span class="tok-kw">if</span> (cell.style.dim) {</span>
<span class="line" id="L421"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.dim_set);</span>
<span class="line" id="L422"> }</span>
<span class="line" id="L423"> }</span>
<span class="line" id="L424"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L425"> <span class="tok-kw">if</span> (cursor.dim != cell.style.dim) {</span>
<span class="line" id="L426"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.dim) {</span>
<span class="line" id="L427"> <span class="tok-null">true</span> =&gt; ctlseqs.dim_set,</span>
<span class="line" id="L428"> <span class="tok-null">false</span> =&gt; ctlseqs.bold_dim_reset,</span>
<span class="line" id="L429"> };</span>
<span class="line" id="L430"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L431"> <span class="tok-kw">if</span> (cell.style.bold) {</span>
<span class="line" id="L432"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.bold_set);</span>
<span class="line" id="L433"> }</span>
<span class="line" id="L434"> }</span>
<span class="line" id="L435"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L436"> <span class="tok-kw">if</span> (cursor.italic != cell.style.italic) {</span>
<span class="line" id="L437"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.italic) {</span>
<span class="line" id="L438"> <span class="tok-null">true</span> =&gt; ctlseqs.italic_set,</span>
<span class="line" id="L439"> <span class="tok-null">false</span> =&gt; ctlseqs.italic_reset,</span>
<span class="line" id="L440"> };</span>
<span class="line" id="L441"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L442"> }</span>
<span class="line" id="L443"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L444"> <span class="tok-kw">if</span> (cursor.blink != cell.style.blink) {</span>
<span class="line" id="L445"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.blink) {</span>
<span class="line" id="L446"> <span class="tok-null">true</span> =&gt; ctlseqs.blink_set,</span>
<span class="line" id="L447"> <span class="tok-null">false</span> =&gt; ctlseqs.blink_reset,</span>
<span class="line" id="L448"> };</span>
<span class="line" id="L449"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L450"> }</span>
<span class="line" id="L451"> <span class="tok-comment">// reverse</span>
</span>
<span class="line" id="L452"> <span class="tok-kw">if</span> (cursor.reverse != cell.style.reverse) {</span>
<span class="line" id="L453"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.reverse) {</span>
<span class="line" id="L454"> <span class="tok-null">true</span> =&gt; ctlseqs.reverse_set,</span>
<span class="line" id="L455"> <span class="tok-null">false</span> =&gt; ctlseqs.reverse_reset,</span>
<span class="line" id="L456"> };</span>
<span class="line" id="L457"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L458"> }</span>
<span class="line" id="L459"> <span class="tok-comment">// invisible</span>
</span>
<span class="line" id="L460"> <span class="tok-kw">if</span> (cursor.invisible != cell.style.invisible) {</span>
<span class="line" id="L461"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.invisible) {</span>
<span class="line" id="L462"> <span class="tok-null">true</span> =&gt; ctlseqs.invisible_set,</span>
<span class="line" id="L463"> <span class="tok-null">false</span> =&gt; ctlseqs.invisible_reset,</span>
<span class="line" id="L464"> };</span>
<span class="line" id="L465"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L466"> }</span>
<span class="line" id="L467"> <span class="tok-comment">// strikethrough</span>
</span>
<span class="line" id="L468"> <span class="tok-kw">if</span> (cursor.strikethrough != cell.style.strikethrough) {</span>
<span class="line" id="L469"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.strikethrough) {</span>
<span class="line" id="L470"> <span class="tok-null">true</span> =&gt; ctlseqs.strikethrough_set,</span>
<span class="line" id="L471"> <span class="tok-null">false</span> =&gt; ctlseqs.strikethrough_reset,</span>
<span class="line" id="L472"> };</span>
<span class="line" id="L473"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L474"> }</span>
<span class="line" id="L475"></span>
<span class="line" id="L476"> <span class="tok-comment">// url</span>
</span>
<span class="line" id="L477"> <span class="tok-kw">if</span> (!std.meta.eql(link.uri, cell.link.uri)) {</span>
<span class="line" id="L478"> <span class="tok-kw">var</span> ps = cell.link.params;</span>
<span class="line" id="L479"> <span class="tok-kw">if</span> (cell.link.uri.len == <span class="tok-number">0</span>) {</span>
<span class="line" id="L480"> <span class="tok-comment">// Empty out the params no matter what if we don't have</span>
</span>
<span class="line" id="L481"> <span class="tok-comment">// a url</span>
</span>
<span class="line" id="L482"> ps = <span class="tok-str">&quot;&quot;</span>;</span>
<span class="line" id="L483"> }</span>
<span class="line" id="L484"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L485"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.osc8, .{ ps, cell.link.uri });</span>
<span class="line" id="L486"> }</span>
<span class="line" id="L487"> _ = <span class="tok-kw">try</span> tty.write(cell.char.grapheme);</span>
<span class="line" id="L488"> }</span>
<span class="line" id="L489"> <span class="tok-kw">if</span> (self.screen.cursor_vis) {</span>
<span class="line" id="L490"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L491"> tty.buffered_writer.writer(),</span>
<span class="line" id="L492"> ctlseqs.cup,</span>
<span class="line" id="L493"> .{</span>
<span class="line" id="L494"> self.screen.cursor_row + <span class="tok-number">1</span>,</span>
<span class="line" id="L495"> self.screen.cursor_col + <span class="tok-number">1</span>,</span>
<span class="line" id="L496"> },</span>
<span class="line" id="L497"> );</span>
<span class="line" id="L498"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.show_cursor);</span>
<span class="line" id="L499"> }</span>
<span class="line" id="L500"> <span class="tok-kw">if</span> (self.screen.mouse_shape != self.screen_last.mouse_shape) {</span>
<span class="line" id="L501"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L502"> tty.buffered_writer.writer(),</span>
<span class="line" id="L503"> ctlseqs.osc22_mouse_shape,</span>
<span class="line" id="L504"> .{<span class="tok-builtin">@tagName</span>(self.screen.mouse_shape)},</span>
<span class="line" id="L505"> );</span>
<span class="line" id="L506"> }</span>
<span class="line" id="L507"> }</span>
<span class="line" id="L508"></span>
<span class="line" id="L509"> <span class="tok-kw">fn</span> <span class="tok-fn">enableKittyKeyboard</span>(self: *Self, flags: Key.KittyFlags) !<span class="tok-type">void</span> {</span>
<span class="line" id="L510"> self.state.kitty_keyboard = <span class="tok-null">true</span>;</span>
<span class="line" id="L511"> <span class="tok-kw">const</span> flag_int: <span class="tok-type">u5</span> = <span class="tok-builtin">@bitCast</span>(flags);</span>
<span class="line" id="L512"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L513"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L514"> ctlseqs.csi_u_push,</span>
<span class="line" id="L515"> .{</span>
<span class="line" id="L516"> flag_int,</span>
<span class="line" id="L517"> },</span>
<span class="line" id="L518"> );</span>
<span class="line" id="L519"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L520"> }</span>
<span class="line" id="L521"></span>
<span class="line" id="L522"> <span class="tok-comment">/// send a system notification</span></span>
<span class="line" id="L523"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">notify</span>(self: *Self, title: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, body: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L524"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L525"> <span class="tok-kw">if</span> (title) |t| {</span>
<span class="line" id="L526"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L527"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L528"> ctlseqs.osc777_notify,</span>
<span class="line" id="L529"> .{ t, body },</span>
<span class="line" id="L530"> );</span>
<span class="line" id="L531"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L532"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L533"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L534"> ctlseqs.osc9_notify,</span>
<span class="line" id="L535"> .{body},</span>
<span class="line" id="L536"> );</span>
<span class="line" id="L537"> }</span>
<span class="line" id="L538"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L539"> }</span>
<span class="line" id="L540"></span>
<span class="line" id="L541"> <span class="tok-comment">/// sets the window title</span></span>
<span class="line" id="L542"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setTitle</span>(self: *Self, title: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L543"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L544"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L545"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L546"> ctlseqs.osc2_set_title,</span>
<span class="line" id="L547"> .{title},</span>
<span class="line" id="L548"> );</span>
<span class="line" id="L549"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L550"> }</span>
<span class="line" id="L551"></span>
<span class="line" id="L552"> <span class="tok-comment">// turn bracketed paste on or off. An event will be sent at the</span>
</span>
<span class="line" id="L553"> <span class="tok-comment">// beginning and end of a detected paste. All keystrokes between these</span>
</span>
<span class="line" id="L554"> <span class="tok-comment">// events were pasted</span>
</span>
<span class="line" id="L555"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setBracketedPaste</span>(self: *Self, enable: <span class="tok-type">bool</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L556"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L557"> self.state.bracketed_paste = enable;</span>
<span class="line" id="L558"> <span class="tok-kw">const</span> seq = <span class="tok-kw">if</span> (enable) {</span>
<span class="line" id="L559"> self.state.bracketed_paste = <span class="tok-null">true</span>;</span>
<span class="line" id="L560"> ctlseqs.bp_set;</span>
<span class="line" id="L561"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L562"> self.state.bracketed_paste = <span class="tok-null">true</span>;</span>
<span class="line" id="L563"> ctlseqs.bp_reset;</span>
<span class="line" id="L564"> };</span>
<span class="line" id="L565"> _ = <span class="tok-kw">try</span> self.tty.?.write(seq);</span>
<span class="line" id="L566"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L567"> }</span>
<span class="line" id="L568"></span>
<span class="line" id="L569"> <span class="tok-comment">/// set the mouse shape</span></span>
<span class="line" id="L570"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setMouseShape</span>(self: *Self, shape: Shape) <span class="tok-type">void</span> {</span>
<span class="line" id="L571"> self.screen.mouse_shape = shape;</span>
<span class="line" id="L572"> }</span>
<span class="line" id="L573"></span>
<span class="line" id="L574"> <span class="tok-comment">/// turn mouse reporting on or off</span></span>
<span class="line" id="L575"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setMouseMode</span>(self: *Self, enable: <span class="tok-type">bool</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L576"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L577"> self.state.mouse = enable;</span>
<span class="line" id="L578"> <span class="tok-kw">if</span> (enable) {</span>
<span class="line" id="L579"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.mouse_set);</span>
<span class="line" id="L580"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L581"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L582"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.mouse_reset);</span>
<span class="line" id="L583"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L584"> }</span>
<span class="line" id="L585"> }</span>
<span class="line" id="L586"></span>
<span class="line" id="L587"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">loadImage</span>(</span>
<span class="line" id="L588"> self: *Self,</span>
<span class="line" id="L589"> alloc: std.mem.Allocator,</span>
<span class="line" id="L590"> src: Image.Source,</span>
<span class="line" id="L591"> ) !Image {</span>
<span class="line" id="L592"> <span class="tok-kw">if</span> (!self.caps.kitty_graphics) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.NoGraphicsCapability;</span>
<span class="line" id="L593"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.NoTTY;</span>
<span class="line" id="L594"> <span class="tok-kw">defer</span> self.next_img_id += <span class="tok-number">1</span>;</span>
<span class="line" id="L595"></span>
<span class="line" id="L596"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L597"></span>
<span class="line" id="L598"> <span class="tok-kw">var</span> img = <span class="tok-kw">switch</span> (src) {</span>
<span class="line" id="L599"> .path =&gt; |path| <span class="tok-kw">try</span> zigimg.Image.fromFilePath(alloc, path),</span>
<span class="line" id="L600"> .mem =&gt; |bytes| <span class="tok-kw">try</span> zigimg.Image.fromMemory(alloc, bytes),</span>
<span class="line" id="L601"> };</span>
<span class="line" id="L602"> <span class="tok-kw">defer</span> img.deinit();</span>
<span class="line" id="L603"> <span class="tok-kw">const</span> png_buf = <span class="tok-kw">try</span> alloc.alloc(<span class="tok-type">u8</span>, img.imageByteSize());</span>
<span class="line" id="L604"> <span class="tok-kw">defer</span> alloc.free(png_buf);</span>
<span class="line" id="L605"> <span class="tok-kw">const</span> png = <span class="tok-kw">try</span> img.writeToMemory(png_buf, .{ .png = .{} });</span>
<span class="line" id="L606"> <span class="tok-kw">const</span> b64_buf = <span class="tok-kw">try</span> alloc.alloc(<span class="tok-type">u8</span>, base64.calcSize(png.len));</span>
<span class="line" id="L607"> <span class="tok-kw">const</span> encoded = base64.encode(b64_buf, png);</span>
<span class="line" id="L608"> <span class="tok-kw">defer</span> alloc.free(b64_buf);</span>
<span class="line" id="L609"></span>
<span class="line" id="L610"> <span class="tok-kw">const</span> id = self.next_img_id;</span>
<span class="line" id="L611"></span>
<span class="line" id="L612"> log.debug(<span class="tok-str">&quot;transmitting kitty image: id={d}, len={d}&quot;</span>, .{ id, encoded.len });</span>
<span class="line" id="L613"></span>
<span class="line" id="L614"> <span class="tok-kw">if</span> (encoded.len &lt; <span class="tok-number">4096</span>) {</span>
<span class="line" id="L615"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L616"> writer,</span>
<span class="line" id="L617"> <span class="tok-str">&quot;\x1b_Gf=100,i={d};{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L618"> .{</span>
<span class="line" id="L619"> id,</span>
<span class="line" id="L620"> encoded,</span>
<span class="line" id="L621"> },</span>
<span class="line" id="L622"> );</span>
<span class="line" id="L623"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L624"> <span class="tok-kw">var</span> n: <span class="tok-type">usize</span> = <span class="tok-number">4096</span>;</span>
<span class="line" id="L625"></span>
<span class="line" id="L626"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L627"> writer,</span>
<span class="line" id="L628"> <span class="tok-str">&quot;\x1b_Gf=100,i={d},m=1;{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L629"> .{ id, encoded[<span class="tok-number">0</span>..n] },</span>
<span class="line" id="L630"> );</span>
<span class="line" id="L631"> <span class="tok-kw">while</span> (n &lt; encoded.len) : (n += <span class="tok-number">4096</span>) {</span>
<span class="line" id="L632"> <span class="tok-kw">const</span> end: <span class="tok-type">usize</span> = <span class="tok-builtin">@min</span>(n + <span class="tok-number">4096</span>, encoded.len);</span>
<span class="line" id="L633"> <span class="tok-kw">const</span> m: <span class="tok-type">u2</span> = <span class="tok-kw">if</span> (end == encoded.len) <span class="tok-number">0</span> <span class="tok-kw">else</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L634"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L635"> writer,</span>
<span class="line" id="L636"> <span class="tok-str">&quot;\x1b_Gm={d};{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L637"> .{</span>
<span class="line" id="L638"> m,</span>
<span class="line" id="L639"> encoded[n..end],</span>
<span class="line" id="L640"> },</span>
<span class="line" id="L641"> );</span>
<span class="line" id="L642"> }</span>
<span class="line" id="L643"> }</span>
<span class="line" id="L644"> <span class="tok-kw">try</span> tty.buffered_writer.flush();</span>
<span class="line" id="L645"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L646"> .id = id,</span>
<span class="line" id="L647"> .width = img.width,</span>
<span class="line" id="L648"> .height = img.height,</span>
<span class="line" id="L649"> };</span>
<span class="line" id="L650"> }</span>
<span class="line" id="L651"></span>
<span class="line" id="L652"> <span class="tok-comment">/// deletes an image from the terminal's memory</span></span>
<span class="line" id="L653"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">freeImage</span>(self: Self, id: <span class="tok-type">u32</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L654"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L655"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L656"> std.fmt.format(writer, <span class="tok-str">&quot;\x1b_Ga=d,d=I,i={d};\x1b\\&quot;</span>, .{id}) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L657"> log.err(<span class="tok-str">&quot;couldn't delete image {d}: {}&quot;</span>, .{ id, err });</span>
<span class="line" id="L658"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L659"> };</span>
<span class="line" id="L660"> tty.buffered_writer.flush() <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L661"> log.err(<span class="tok-str">&quot;couldn't flush writer: {}&quot;</span>, .{err});</span>
<span class="line" id="L662"> };</span>
<span class="line" id="L663"> }</span>
<span class="line" id="L664"> };</span>
<span class="line" id="L665">}</span>
<span class="line" id="L666"></span>
<span class="line" id="L667"><span class="tok-kw">test</span> <span class="tok-str">&quot;Vaxis: event queueing&quot;</span> {</span>
<span class="line" id="L668"> <span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L669"> key,</span>
<span class="line" id="L670"> };</span>
<span class="line" id="L671"> <span class="tok-kw">var</span> vx: Vaxis(Event) = <span class="tok-kw">try</span> Vaxis(Event).init(.{});</span>
<span class="line" id="L672"> <span class="tok-kw">defer</span> vx.deinit(<span class="tok-null">null</span>);</span>
<span class="line" id="L673"> vx.postEvent(.key);</span>
<span class="line" id="L674"> <span class="tok-kw">const</span> event = vx.nextEvent();</span>
<span class="line" id="L675"> <span class="tok-kw">try</span> std.testing.expect(event == .key);</span>
<span class="line" id="L676">}</span>
<span class="line" id="L677"></span>
</code></pre></body>
</html>

View file

@ -1,120 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> border = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/border.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> alignment = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/alignment.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TextInput = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/TextInput.zig&quot;</span>);</span>
<span class="line" id="L4"></span>
</code></pre></body>
</html>

View file

@ -1,260 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/TextInput.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Key.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Cell.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> GraphemeIterator = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>).GraphemeIterator;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> log = std.log.scoped(.text_input);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> TextInput = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-comment">/// The events that this widget handles</span></span>
<span class="line" id="L12"><span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L13"> key_press: Key,</span>
<span class="line" id="L14">};</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-comment">// Index of our cursor</span>
</span>
<span class="line" id="L17">cursor_idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18">grapheme_count: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">// TODO: an ArrayList is not great for this. orderedRemove is O(n) and we can</span>
</span>
<span class="line" id="L21"><span class="tok-comment">// only remove one byte at a time. Make a bespoke ArrayList which allows removal</span>
</span>
<span class="line" id="L22"><span class="tok-comment">// of a slice at a time, or truncating even would be nice</span>
</span>
<span class="line" id="L23">buf: std.ArrayList(<span class="tok-type">u8</span>),</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator) TextInput {</span>
<span class="line" id="L26"> <span class="tok-kw">return</span> TextInput{</span>
<span class="line" id="L27"> .buf = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L28"> };</span>
<span class="line" id="L29">}</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L32"> self.buf.deinit();</span>
<span class="line" id="L33">}</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">update</span>(self: *TextInput, event: Event) !<span class="tok-type">void</span> {</span>
<span class="line" id="L36"> <span class="tok-kw">switch</span> (event) {</span>
<span class="line" id="L37"> .key_press =&gt; |key| {</span>
<span class="line" id="L38"> <span class="tok-kw">if</span> (key.matches(Key.backspace, .{})) {</span>
<span class="line" id="L39"> <span class="tok-kw">if</span> (self.cursor_idx == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L40"> self.deleteBeforeCursor();</span>
<span class="line" id="L41"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.delete, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'d'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L42"> <span class="tok-kw">if</span> (self.cursor_idx == self.grapheme_count) <span class="tok-kw">return</span>;</span>
<span class="line" id="L43"> self.deleteAtCursor();</span>
<span class="line" id="L44"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.left, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'b'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L45"> <span class="tok-kw">if</span> (self.cursor_idx &gt; <span class="tok-number">0</span>) self.cursor_idx -= <span class="tok-number">1</span>;</span>
<span class="line" id="L46"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.right, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'f'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L47"> <span class="tok-kw">if</span> (self.cursor_idx &lt; self.grapheme_count) self.cursor_idx += <span class="tok-number">1</span>;</span>
<span class="line" id="L48"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'a'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L49"> self.cursor_idx = <span class="tok-number">0</span>;</span>
<span class="line" id="L50"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'e'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L51"> self.cursor_idx = self.grapheme_count;</span>
<span class="line" id="L52"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'k'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L53"> <span class="tok-kw">while</span> (self.cursor_idx &lt; self.grapheme_count) {</span>
<span class="line" id="L54"> self.deleteAtCursor();</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'u'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L57"> <span class="tok-kw">while</span> (self.cursor_idx &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L58"> self.deleteBeforeCursor();</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.text) |text| {</span>
<span class="line" id="L61"> <span class="tok-kw">try</span> self.buf.insertSlice(self.byteOffsetToCursor(), text);</span>
<span class="line" id="L62"> self.cursor_idx += <span class="tok-number">1</span>;</span>
<span class="line" id="L63"> self.grapheme_count += <span class="tok-number">1</span>;</span>
<span class="line" id="L64"> }</span>
<span class="line" id="L65"> },</span>
<span class="line" id="L66"> }</span>
<span class="line" id="L67">}</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">draw</span>(self: *TextInput, win: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L70"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L71"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L72"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L73"> <span class="tok-kw">var</span> cursor_idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L74"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L75"> <span class="tok-kw">const</span> g = grapheme.slice(self.buf.items);</span>
<span class="line" id="L76"> <span class="tok-kw">const</span> w = win.gwidth(g);</span>
<span class="line" id="L77"> win.writeCell(col, <span class="tok-number">0</span>, .{</span>
<span class="line" id="L78"> .char = .{</span>
<span class="line" id="L79"> .grapheme = g,</span>
<span class="line" id="L80"> .width = w,</span>
<span class="line" id="L81"> },</span>
<span class="line" id="L82"> });</span>
<span class="line" id="L83"> col += w;</span>
<span class="line" id="L84"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L85"> <span class="tok-kw">if</span> (i == self.cursor_idx) cursor_idx = col;</span>
<span class="line" id="L86"> }</span>
<span class="line" id="L87"> win.showCursor(cursor_idx, <span class="tok-number">0</span>);</span>
<span class="line" id="L88">}</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"><span class="tok-comment">// returns the number of bytes before the cursor</span>
</span>
<span class="line" id="L91"><span class="tok-kw">fn</span> <span class="tok-fn">byteOffsetToCursor</span>(self: TextInput) <span class="tok-type">usize</span> {</span>
<span class="line" id="L92"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L93"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L94"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L95"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (i == self.cursor_idx) <span class="tok-kw">break</span>;</span>
<span class="line" id="L97"> offset += grapheme.len;</span>
<span class="line" id="L98"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> <span class="tok-kw">return</span> offset;</span>
<span class="line" id="L101">}</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"><span class="tok-kw">fn</span> <span class="tok-fn">deleteBeforeCursor</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L105"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L106"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L107"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L108"> <span class="tok-kw">if</span> (i == self.cursor_idx) {</span>
<span class="line" id="L109"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L110"> <span class="tok-kw">while</span> (j &lt; grapheme.len) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L111"> _ = self.buf.orderedRemove(offset);</span>
<span class="line" id="L112"> }</span>
<span class="line" id="L113"> self.cursor_idx -= <span class="tok-number">1</span>;</span>
<span class="line" id="L114"> self.grapheme_count -= <span class="tok-number">1</span>;</span>
<span class="line" id="L115"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"> offset += grapheme.len;</span>
<span class="line" id="L118"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120">}</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"><span class="tok-kw">fn</span> <span class="tok-fn">deleteAtCursor</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L123"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L124"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L125"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L126"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (i == self.cursor_idx + <span class="tok-number">1</span>) {</span>
<span class="line" id="L128"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L129"> <span class="tok-kw">while</span> (j &lt; grapheme.len) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L130"> _ = self.buf.orderedRemove(offset);</span>
<span class="line" id="L131"> }</span>
<span class="line" id="L132"> self.grapheme_count -= <span class="tok-number">1</span>;</span>
<span class="line" id="L133"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> offset += grapheme.len;</span>
<span class="line" id="L136"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L137"> }</span>
<span class="line" id="L138">}</span>
<span class="line" id="L139"></span>
</code></pre></body>
</html>

View file

@ -1,124 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/alignment.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">center</span>(parent: Window, cols: <span class="tok-type">usize</span>, rows: <span class="tok-type">usize</span>) Window {</span>
<span class="line" id="L4"> <span class="tok-kw">const</span> y_off = (parent.height / <span class="tok-number">2</span>) - (rows / <span class="tok-number">2</span>);</span>
<span class="line" id="L5"> <span class="tok-kw">const</span> x_off = (parent.width / <span class="tok-number">2</span>) - (cols / <span class="tok-number">2</span>);</span>
<span class="line" id="L6"> <span class="tok-kw">return</span> parent.initChild(x_off, y_off, .{ .limit = cols }, .{ .limit = rows });</span>
<span class="line" id="L7">}</span>
<span class="line" id="L8"></span>
</code></pre></body>
</html>

View file

@ -1,149 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/border.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Cell.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Style = Cell.Style;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Character = Cell.Character;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> horizontal = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L8"><span class="tok-kw">const</span> vertical = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L9"><span class="tok-kw">const</span> top_left = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L10"><span class="tok-kw">const</span> top_right = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L11"><span class="tok-kw">const</span> bottom_right = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L12"><span class="tok-kw">const</span> bottom_left = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">all</span>(win: Window, style: Style) Window {</span>
<span class="line" id="L15"> <span class="tok-kw">const</span> h = win.height;</span>
<span class="line" id="L16"> <span class="tok-kw">const</span> w = win.width;</span>
<span class="line" id="L17"> win.writeCell(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .char = top_left, .style = style });</span>
<span class="line" id="L18"> win.writeCell(<span class="tok-number">0</span>, h - <span class="tok-number">1</span>, .{ .char = bottom_left, .style = style });</span>
<span class="line" id="L19"> win.writeCell(w - <span class="tok-number">1</span>, <span class="tok-number">0</span>, .{ .char = top_right, .style = style });</span>
<span class="line" id="L20"> win.writeCell(w - <span class="tok-number">1</span>, h - <span class="tok-number">1</span>, .{ .char = bottom_right, .style = style });</span>
<span class="line" id="L21"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L22"> <span class="tok-kw">while</span> (i &lt; (h - <span class="tok-number">1</span>)) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L23"> win.writeCell(<span class="tok-number">0</span>, i, .{ .char = vertical, .style = style });</span>
<span class="line" id="L24"> win.writeCell(w - <span class="tok-number">1</span>, i, .{ .char = vertical, .style = style });</span>
<span class="line" id="L25"> }</span>
<span class="line" id="L26"> i = <span class="tok-number">1</span>;</span>
<span class="line" id="L27"> <span class="tok-kw">while</span> (i &lt; w - <span class="tok-number">1</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L28"> win.writeCell(i, <span class="tok-number">0</span>, .{ .char = horizontal, .style = style });</span>
<span class="line" id="L29"> win.writeCell(i, h - <span class="tok-number">1</span>, .{ .char = horizontal, .style = style });</span>
<span class="line" id="L30"> }</span>
<span class="line" id="L31"> <span class="tok-kw">return</span> win.initChild(<span class="tok-number">1</span>, <span class="tok-number">1</span>, .{ .limit = w - <span class="tok-number">2</span> }, .{ .limit = w - <span class="tok-number">2</span> });</span>
<span class="line" id="L32">}</span>
<span class="line" id="L33"></span>
</code></pre></body>
</html>

View file

@ -1,175 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Cell.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3">char: Character = .{},</span>
<span class="line" id="L4">style: Style = .{},</span>
<span class="line" id="L5">link: Hyperlink = .{},</span>
<span class="line" id="L6">image: ?Image.Placement = <span class="tok-null">null</span>,</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Segment is a contiguous run of text that has a constant style</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Segment = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L10"> text: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L11"> style: Style = .{},</span>
<span class="line" id="L12"> link: Hyperlink = .{},</span>
<span class="line" id="L13">};</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Character = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L16"> grapheme: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot; &quot;</span>,</span>
<span class="line" id="L17"> <span class="tok-comment">/// width should only be provided when the application is sure the terminal</span></span>
<span class="line" id="L18"> <span class="tok-comment">/// will measure the same width. This can be ensure by using the gwidth method</span></span>
<span class="line" id="L19"> <span class="tok-comment">/// included in libvaxis. If width is 0, libvaxis will measure the glyph at</span></span>
<span class="line" id="L20"> <span class="tok-comment">/// render time</span></span>
<span class="line" id="L21"> width: <span class="tok-type">usize</span> = <span class="tok-number">1</span>,</span>
<span class="line" id="L22">};</span>
<span class="line" id="L23"></span>
<span class="line" id="L24"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Hyperlink = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L25"> uri: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot;&quot;</span>,</span>
<span class="line" id="L26"> <span class="tok-comment">/// ie &quot;id=app-1234&quot;</span></span>
<span class="line" id="L27"> params: []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-str">&quot;&quot;</span>,</span>
<span class="line" id="L28">};</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Style = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L31"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Underline = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L32"> off,</span>
<span class="line" id="L33"> single,</span>
<span class="line" id="L34"> double,</span>
<span class="line" id="L35"> curly,</span>
<span class="line" id="L36"> dotted,</span>
<span class="line" id="L37"> dashed,</span>
<span class="line" id="L38"> };</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"> fg: Color = .default,</span>
<span class="line" id="L41"> bg: Color = .default,</span>
<span class="line" id="L42"> ul: Color = .default,</span>
<span class="line" id="L43"> ul_style: Underline = .off,</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> bold: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L46"> dim: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L47"> italic: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L48"> blink: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L49"> reverse: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L50"> invisible: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L51"> strikethrough: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L52">};</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Color = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L55"> default,</span>
<span class="line" id="L56"> index: <span class="tok-type">u8</span>,</span>
<span class="line" id="L57"> rgb: [<span class="tok-number">3</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L58">};</span>
<span class="line" id="L59"></span>
</code></pre></body>
</html>

View file

@ -1,142 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>GraphemeCache.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> GraphemeCache = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// the underlying storage for graphemes. Right now 8kb</span></span>
<span class="line" id="L7">buf: [<span class="tok-number">1024</span> * <span class="tok-number">8</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">// the start index of the next grapheme</span>
</span>
<span class="line" id="L10">idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-comment">/// put a slice of bytes in the cache as a grapheme</span></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">put</span>(self: *GraphemeCache, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) []<span class="tok-type">u8</span> {</span>
<span class="line" id="L14"> <span class="tok-comment">// reset the idx to 0 if we would overflow</span>
</span>
<span class="line" id="L15"> <span class="tok-kw">if</span> (self.idx + bytes.len &gt; self.buf.len) self.idx = <span class="tok-number">0</span>;</span>
<span class="line" id="L16"> <span class="tok-kw">defer</span> self.idx += bytes.len;</span>
<span class="line" id="L17"> <span class="tok-comment">// copy the grapheme to our storage</span>
</span>
<span class="line" id="L18"> <span class="tok-builtin">@memcpy</span>(self.buf[self.idx .. self.idx + bytes.len], bytes);</span>
<span class="line" id="L19"> <span class="tok-comment">// return the slice</span>
</span>
<span class="line" id="L20"> <span class="tok-kw">return</span> self.buf[self.idx .. self.idx + bytes.len];</span>
<span class="line" id="L21">}</span>
<span class="line" id="L22"></span>
</code></pre></body>
</html>

View file

@ -1,191 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Image.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> fmt = std.fmt;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> math = std.math;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> base64 = std.base64.standard.Encoder;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> zigimg = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zigimg&quot;</span>);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Window.zig&quot;</span>);</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">const</span> log = std.log.scoped(.image);</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> transmit_opener = <span class="tok-str">&quot;\x1b_Gf=32,i={d},s={d},v={d},m={d};&quot;</span>;</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Source = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L17"> path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L18"> mem: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Placement = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L22"> img_id: <span class="tok-type">u32</span>,</span>
<span class="line" id="L23"> z_index: <span class="tok-type">i32</span>,</span>
<span class="line" id="L24"> size: ?CellSize = <span class="tok-null">null</span>,</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CellSize = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L28"> rows: <span class="tok-type">usize</span>,</span>
<span class="line" id="L29"> cols: <span class="tok-type">usize</span>,</span>
<span class="line" id="L30">};</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"><span class="tok-comment">/// unique identifier for this image. This will be managed by the screen.</span></span>
<span class="line" id="L33">id: <span class="tok-type">u32</span>,</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-comment">// width in pixels</span>
</span>
<span class="line" id="L36">width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L37"><span class="tok-comment">// height in pixels</span>
</span>
<span class="line" id="L38">height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">draw</span>(self: Image, win: Window, scale: <span class="tok-type">bool</span>, z_index: <span class="tok-type">i32</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">const</span> p = Placement{</span>
<span class="line" id="L42"> .img_id = self.id,</span>
<span class="line" id="L43"> .z_index = z_index,</span>
<span class="line" id="L44"> .size = sz: {</span>
<span class="line" id="L45"> <span class="tok-kw">if</span> (!scale) <span class="tok-kw">break</span> :sz <span class="tok-null">null</span>;</span>
<span class="line" id="L46"> <span class="tok-kw">break</span> :sz CellSize{</span>
<span class="line" id="L47"> .rows = win.height,</span>
<span class="line" id="L48"> .cols = win.width,</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50"> },</span>
<span class="line" id="L51"> };</span>
<span class="line" id="L52"> win.writeCell(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .image = p });</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">cellSize</span>(self: Image, win: Window) !CellSize {</span>
<span class="line" id="L56"> <span class="tok-comment">// cell geometry</span>
</span>
<span class="line" id="L57"> <span class="tok-kw">const</span> x_pix = win.screen.width_pix;</span>
<span class="line" id="L58"> <span class="tok-kw">const</span> y_pix = win.screen.height_pix;</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> w = win.screen.width;</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> h = win.screen.height;</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> <span class="tok-kw">const</span> pix_per_col = <span class="tok-kw">try</span> std.math.divCeil(<span class="tok-type">usize</span>, x_pix, w);</span>
<span class="line" id="L63"> <span class="tok-kw">const</span> pix_per_row = <span class="tok-kw">try</span> std.math.divCeil(<span class="tok-type">usize</span>, y_pix, h);</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> <span class="tok-kw">const</span> cell_width = std.math.divCeil(<span class="tok-type">usize</span>, self.width, pix_per_col) <span class="tok-kw">catch</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L66"> <span class="tok-kw">const</span> cell_height = std.math.divCeil(<span class="tok-type">usize</span>, self.height, pix_per_row) <span class="tok-kw">catch</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L67"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L68"> .rows = cell_height,</span>
<span class="line" id="L69"> .cols = cell_width,</span>
<span class="line" id="L70"> };</span>
<span class="line" id="L71">}</span>
<span class="line" id="L72"></span>
</code></pre></body>
</html>

View file

@ -1,215 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>InternalScreen.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Style = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Style;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Shape = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>).Shape;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> log = std.log.scoped(.internal_screen);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> InternalScreen = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> InternalCell = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L12"> char: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L13"> style: Style = .{},</span>
<span class="line" id="L14"> uri: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L15"> uri_id: std.ArrayList(<span class="tok-type">u8</span>) = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L16"> <span class="tok-comment">// if we got skipped because of a wide character</span>
</span>
<span class="line" id="L17"> skipped: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">eql</span>(self: InternalCell, cell: Cell) <span class="tok-type">bool</span> {</span>
<span class="line" id="L20"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, self.char.items, cell.char.grapheme) <span class="tok-kw">and</span></span>
<span class="line" id="L21"> std.meta.eql(self.style, cell.style) <span class="tok-kw">and</span></span>
<span class="line" id="L22"> std.mem.eql(<span class="tok-type">u8</span>, self.uri.items, cell.link.uri) <span class="tok-kw">and</span></span>
<span class="line" id="L23"> std.mem.eql(<span class="tok-type">u8</span>, self.uri_id.items, cell.link.params);</span>
<span class="line" id="L24"> }</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"></span>
<span class="line" id="L27">width: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L28">height: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L29"></span>
<span class="line" id="L30">buf: []InternalCell = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L31"></span>
<span class="line" id="L32">cursor_row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L33">cursor_col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L34">cursor_vis: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L35"></span>
<span class="line" id="L36">mouse_shape: Shape = .default,</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-comment">/// sets each cell to the default cell</span></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator, w: <span class="tok-type">usize</span>, h: <span class="tok-type">usize</span>) !InternalScreen {</span>
<span class="line" id="L40"> <span class="tok-kw">var</span> screen = InternalScreen{</span>
<span class="line" id="L41"> .buf = <span class="tok-kw">try</span> alloc.alloc(InternalCell, w * h),</span>
<span class="line" id="L42"> };</span>
<span class="line" id="L43"> <span class="tok-kw">for</span> (screen.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L44"> screen.buf[i] = .{</span>
<span class="line" id="L45"> .char = <span class="tok-kw">try</span> std.ArrayList(<span class="tok-type">u8</span>).initCapacity(alloc, <span class="tok-number">1</span>),</span>
<span class="line" id="L46"> .uri = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L47"> .uri_id = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L48"> };</span>
<span class="line" id="L49"> }</span>
<span class="line" id="L50"> screen.width = w;</span>
<span class="line" id="L51"> screen.height = h;</span>
<span class="line" id="L52"> <span class="tok-kw">return</span> screen;</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *InternalScreen, alloc: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L56"> <span class="tok-kw">for</span> (self.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L57"> self.buf[i].char.deinit();</span>
<span class="line" id="L58"> self.buf[i].uri.deinit();</span>
<span class="line" id="L59"> self.buf[i].uri_id.deinit();</span>
<span class="line" id="L60"> }</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> alloc.free(self.buf);</span>
<span class="line" id="L63">}</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"><span class="tok-comment">/// writes a cell to a location. 0 indexed</span></span>
<span class="line" id="L66"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(</span>
<span class="line" id="L67"> self: *InternalScreen,</span>
<span class="line" id="L68"> col: <span class="tok-type">usize</span>,</span>
<span class="line" id="L69"> row: <span class="tok-type">usize</span>,</span>
<span class="line" id="L70"> cell: Cell,</span>
<span class="line" id="L71">) <span class="tok-type">void</span> {</span>
<span class="line" id="L72"> <span class="tok-kw">if</span> (self.width &lt; col) {</span>
<span class="line" id="L73"> <span class="tok-comment">// column out of bounds</span>
</span>
<span class="line" id="L74"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L75"> }</span>
<span class="line" id="L76"> <span class="tok-kw">if</span> (self.height &lt; row) {</span>
<span class="line" id="L77"> <span class="tok-comment">// height out of bounds</span>
</span>
<span class="line" id="L78"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L79"> }</span>
<span class="line" id="L80"> <span class="tok-kw">const</span> i = (row * self.width) + col;</span>
<span class="line" id="L81"> assert(i &lt; self.buf.len);</span>
<span class="line" id="L82"> self.buf[i].char.clearRetainingCapacity();</span>
<span class="line" id="L83"> self.buf[i].char.appendSlice(cell.char.grapheme) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L84"> log.warn(<span class="tok-str">&quot;couldn't write grapheme&quot;</span>, .{});</span>
<span class="line" id="L85"> };</span>
<span class="line" id="L86"> self.buf[i].uri.clearRetainingCapacity();</span>
<span class="line" id="L87"> self.buf[i].uri.appendSlice(cell.link.uri) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L88"> log.warn(<span class="tok-str">&quot;couldn't write uri&quot;</span>, .{});</span>
<span class="line" id="L89"> };</span>
<span class="line" id="L90"> self.buf[i].uri.clearRetainingCapacity();</span>
<span class="line" id="L91"> self.buf[i].uri_id.appendSlice(cell.link.params) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L92"> log.warn(<span class="tok-str">&quot;couldn't write uri_id&quot;</span>, .{});</span>
<span class="line" id="L93"> };</span>
<span class="line" id="L94"> self.buf[i].style = cell.style;</span>
<span class="line" id="L95">}</span>
<span class="line" id="L96"></span>
</code></pre></body>
</html>

View file

@ -1,419 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Key.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> Key = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Modifier Keys for a Key Match Event.</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Modifiers = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L10"> shift: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L11"> alt: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L12"> ctrl: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L13"> super: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L14"> hyper: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L15"> meta: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L16"> caps_lock: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L17"> num_lock: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L18">};</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// Flags for the Kitty Protocol.</span></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> KittyFlags = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u5</span>) {</span>
<span class="line" id="L22"> disambiguate: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L23"> report_events: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L24"> report_alternate_keys: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L25"> report_all_as_ctl_seqs: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L26"> report_text: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L27">};</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-comment">/// the unicode codepoint of the key event.</span></span>
<span class="line" id="L30">codepoint: <span class="tok-type">u21</span>,</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"><span class="tok-comment">/// the text generated from the key event. The underlying slice has a limited</span></span>
<span class="line" id="L33"><span class="tok-comment">/// lifetime. Vaxis maintains an internal ring buffer to temporarily store text.</span></span>
<span class="line" id="L34"><span class="tok-comment">/// If the application needs these values longer than the lifetime of the event</span></span>
<span class="line" id="L35"><span class="tok-comment">/// it must copy the data.</span></span>
<span class="line" id="L36">text: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-comment">/// the shifted codepoint of this key event. This will only be present if the</span></span>
<span class="line" id="L39"><span class="tok-comment">/// Shift modifier was used to generate the event</span></span>
<span class="line" id="L40">shifted_codepoint: ?<span class="tok-type">u21</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"><span class="tok-comment">/// the key that would have been pressed on a standard keyboard layout. This is</span></span>
<span class="line" id="L43"><span class="tok-comment">/// useful for shortcut matching</span></span>
<span class="line" id="L44">base_layout_codepoint: ?<span class="tok-type">u21</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L45"></span>
<span class="line" id="L46">mods: Modifiers = .{},</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"><span class="tok-comment">/// matches follows a loose matching algorithm for key matches.</span></span>
<span class="line" id="L49"><span class="tok-comment">/// 1. If the codepoint and modifiers are exact matches</span></span>
<span class="line" id="L50"><span class="tok-comment">/// 2. If the utf8 encoding of the codepoint matches the text</span></span>
<span class="line" id="L51"><span class="tok-comment">/// 3. If there is a shifted codepoint and it matches after removing the shift</span></span>
<span class="line" id="L52"><span class="tok-comment">/// modifier from self</span></span>
<span class="line" id="L53"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matches</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L54"> <span class="tok-comment">// rule 1</span>
</span>
<span class="line" id="L55"> <span class="tok-kw">if</span> (self.matchExact(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-comment">// rule 2</span>
</span>
<span class="line" id="L58"> <span class="tok-kw">if</span> (self.matchText(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L59"></span>
<span class="line" id="L60"> <span class="tok-comment">// rule 3</span>
</span>
<span class="line" id="L61"> <span class="tok-kw">if</span> (self.matchShiftedCodepoint(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L62"></span>
<span class="line" id="L63"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L64">}</span>
<span class="line" id="L65"></span>
<span class="line" id="L66"><span class="tok-comment">/// matches against any of the provided codepoints.</span></span>
<span class="line" id="L67"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchesAny</span>(self: Key, cps: []<span class="tok-kw">const</span> <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L68"> <span class="tok-kw">for</span> (cps) |cp| {</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (self.matches(cp, mods)) <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L70"> }</span>
<span class="line" id="L71"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L72">}</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"><span class="tok-comment">/// matches base layout codes, useful for shortcut matching when an alternate key</span></span>
<span class="line" id="L75"><span class="tok-comment">/// layout is used</span></span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchShortcut</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L77"> <span class="tok-kw">if</span> (self.base_layout_codepoint == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L78"> <span class="tok-kw">return</span> cp == self.base_layout_codepoint.? <span class="tok-kw">and</span> std.meta.eql(self.mods, mods);</span>
<span class="line" id="L79">}</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"><span class="tok-comment">/// matches keys that aren't upper case versions when shifted. For example, shift</span></span>
<span class="line" id="L82"><span class="tok-comment">/// + semicolon produces a colon. The key can be matched against shift +</span></span>
<span class="line" id="L83"><span class="tok-comment">/// semicolon or just colon...or shift + ctrl + ; or just ctrl + :</span></span>
<span class="line" id="L84"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchShiftedCodepoint</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L85"> <span class="tok-kw">if</span> (self.shifted_codepoint == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L86"> <span class="tok-kw">if</span> (!self.mods.shift) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L87"> <span class="tok-kw">var</span> self_mods = self.mods;</span>
<span class="line" id="L88"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L89"> <span class="tok-kw">return</span> cp == self.shifted_codepoint.? <span class="tok-kw">and</span> std.meta.eql(self_mods, mods);</span>
<span class="line" id="L90">}</span>
<span class="line" id="L91"></span>
<span class="line" id="L92"><span class="tok-comment">/// matches when the utf8 encoding of the codepoint and relevant mods matches the</span></span>
<span class="line" id="L93"><span class="tok-comment">/// text of the key. This function will consume Shift and Caps Lock when matching</span></span>
<span class="line" id="L94"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchText</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L95"> <span class="tok-comment">// return early if we have no text</span>
</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (self.text == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L97"></span>
<span class="line" id="L98"> <span class="tok-kw">var</span> self_mods = self.mods;</span>
<span class="line" id="L99"> <span class="tok-kw">var</span> arg_mods = mods;</span>
<span class="line" id="L100"> <span class="tok-kw">var</span> code = cp;</span>
<span class="line" id="L101"> <span class="tok-comment">// if the passed codepoint is upper, we consume all shift and caps mods for</span>
</span>
<span class="line" id="L102"> <span class="tok-comment">// checking</span>
</span>
<span class="line" id="L103"> <span class="tok-kw">if</span> (ziglyph.isUpper(cp)) {</span>
<span class="line" id="L104"> <span class="tok-comment">// consume mods</span>
</span>
<span class="line" id="L105"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L106"> self_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L107"> arg_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L108"> arg_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L109"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (mods.shift <span class="tok-kw">or</span> mods.caps_lock) {</span>
<span class="line" id="L110"> <span class="tok-comment">// uppercase the cp and consume all mods</span>
</span>
<span class="line" id="L111"> code = ziglyph.toUpper(cp);</span>
<span class="line" id="L112"> self_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L113"> self_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L114"> arg_mods.shift = <span class="tok-null">false</span>;</span>
<span class="line" id="L115"> arg_mods.caps_lock = <span class="tok-null">false</span>;</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> <span class="tok-kw">var</span> buf: [<span class="tok-number">4</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> n = std.unicode.utf8Encode(cp, buf[<span class="tok-number">0</span>..]) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L120"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, self.text.?, buf[<span class="tok-number">0</span>..n]) <span class="tok-kw">and</span> std.meta.eql(self_mods, arg_mods);</span>
<span class="line" id="L121">}</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"><span class="tok-comment">/// The key must exactly match the codepoint and modifiers</span></span>
<span class="line" id="L124"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">matchExact</span>(self: Key, cp: <span class="tok-type">u21</span>, mods: Modifiers) <span class="tok-type">bool</span> {</span>
<span class="line" id="L125"> <span class="tok-kw">return</span> self.codepoint == cp <span class="tok-kw">and</span> std.meta.eql(self.mods, mods);</span>
<span class="line" id="L126">}</span>
<span class="line" id="L127"></span>
<span class="line" id="L128"><span class="tok-comment">// a few special keys that we encode as their actual ascii value</span>
</span>
<span class="line" id="L129"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> tab: <span class="tok-type">u21</span> = <span class="tok-number">0x09</span>;</span>
<span class="line" id="L130"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> escape: <span class="tok-type">u21</span> = <span class="tok-number">0x1B</span>;</span>
<span class="line" id="L131"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> space: <span class="tok-type">u21</span> = <span class="tok-number">0x20</span>;</span>
<span class="line" id="L132"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> enter: <span class="tok-type">u21</span> = <span class="tok-number">0x6D</span>;</span>
<span class="line" id="L133"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> backspace: <span class="tok-type">u21</span> = <span class="tok-number">0x7F</span>;</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"><span class="tok-comment">/// multicodepoint is a key which generated text but cannot be expressed as a</span></span>
<span class="line" id="L136"><span class="tok-comment">/// single codepoint. The value is the maximum unicode codepoint + 1</span></span>
<span class="line" id="L137"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> multicodepoint: <span class="tok-type">u21</span> = <span class="tok-number">1_114_112</span> + <span class="tok-number">1</span>;</span>
<span class="line" id="L138"></span>
<span class="line" id="L139"><span class="tok-comment">// kitty encodes these keys directly in the private use area. We reuse those</span>
</span>
<span class="line" id="L140"><span class="tok-comment">// mappings</span>
</span>
<span class="line" id="L141"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> insert: <span class="tok-type">u21</span> = <span class="tok-number">57348</span>;</span>
<span class="line" id="L142"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> delete: <span class="tok-type">u21</span> = <span class="tok-number">57349</span>;</span>
<span class="line" id="L143"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left: <span class="tok-type">u21</span> = <span class="tok-number">57350</span>;</span>
<span class="line" id="L144"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right: <span class="tok-type">u21</span> = <span class="tok-number">57351</span>;</span>
<span class="line" id="L145"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> up: <span class="tok-type">u21</span> = <span class="tok-number">57352</span>;</span>
<span class="line" id="L146"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> down: <span class="tok-type">u21</span> = <span class="tok-number">57353</span>;</span>
<span class="line" id="L147"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> page_up: <span class="tok-type">u21</span> = <span class="tok-number">57354</span>;</span>
<span class="line" id="L148"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> page_down: <span class="tok-type">u21</span> = <span class="tok-number">57355</span>;</span>
<span class="line" id="L149"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> home: <span class="tok-type">u21</span> = <span class="tok-number">57356</span>;</span>
<span class="line" id="L150"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> end: <span class="tok-type">u21</span> = <span class="tok-number">57357</span>;</span>
<span class="line" id="L151"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> caps_lock: <span class="tok-type">u21</span> = <span class="tok-number">57358</span>;</span>
<span class="line" id="L152"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> scroll_lock: <span class="tok-type">u21</span> = <span class="tok-number">57359</span>;</span>
<span class="line" id="L153"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> num_lock: <span class="tok-type">u21</span> = <span class="tok-number">57360</span>;</span>
<span class="line" id="L154"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> print_screen: <span class="tok-type">u21</span> = <span class="tok-number">57361</span>;</span>
<span class="line" id="L155"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> pause: <span class="tok-type">u21</span> = <span class="tok-number">57362</span>;</span>
<span class="line" id="L156"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> menu: <span class="tok-type">u21</span> = <span class="tok-number">57363</span>;</span>
<span class="line" id="L157"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f1: <span class="tok-type">u21</span> = <span class="tok-number">57364</span>;</span>
<span class="line" id="L158"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f2: <span class="tok-type">u21</span> = <span class="tok-number">57365</span>;</span>
<span class="line" id="L159"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f3: <span class="tok-type">u21</span> = <span class="tok-number">57366</span>;</span>
<span class="line" id="L160"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f4: <span class="tok-type">u21</span> = <span class="tok-number">57367</span>;</span>
<span class="line" id="L161"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f5: <span class="tok-type">u21</span> = <span class="tok-number">57368</span>;</span>
<span class="line" id="L162"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f6: <span class="tok-type">u21</span> = <span class="tok-number">57369</span>;</span>
<span class="line" id="L163"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f7: <span class="tok-type">u21</span> = <span class="tok-number">57370</span>;</span>
<span class="line" id="L164"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f8: <span class="tok-type">u21</span> = <span class="tok-number">57371</span>;</span>
<span class="line" id="L165"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f9: <span class="tok-type">u21</span> = <span class="tok-number">57372</span>;</span>
<span class="line" id="L166"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f10: <span class="tok-type">u21</span> = <span class="tok-number">57373</span>;</span>
<span class="line" id="L167"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f11: <span class="tok-type">u21</span> = <span class="tok-number">57374</span>;</span>
<span class="line" id="L168"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f12: <span class="tok-type">u21</span> = <span class="tok-number">57375</span>;</span>
<span class="line" id="L169"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f13: <span class="tok-type">u21</span> = <span class="tok-number">57376</span>;</span>
<span class="line" id="L170"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f14: <span class="tok-type">u21</span> = <span class="tok-number">57377</span>;</span>
<span class="line" id="L171"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f15: <span class="tok-type">u21</span> = <span class="tok-number">57378</span>;</span>
<span class="line" id="L172"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> @&quot;f16&quot;: <span class="tok-type">u21</span> = <span class="tok-number">57379</span>;</span>
<span class="line" id="L173"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f17: <span class="tok-type">u21</span> = <span class="tok-number">57380</span>;</span>
<span class="line" id="L174"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f18: <span class="tok-type">u21</span> = <span class="tok-number">57381</span>;</span>
<span class="line" id="L175"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f19: <span class="tok-type">u21</span> = <span class="tok-number">57382</span>;</span>
<span class="line" id="L176"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f20: <span class="tok-type">u21</span> = <span class="tok-number">57383</span>;</span>
<span class="line" id="L177"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f21: <span class="tok-type">u21</span> = <span class="tok-number">57384</span>;</span>
<span class="line" id="L178"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f22: <span class="tok-type">u21</span> = <span class="tok-number">57385</span>;</span>
<span class="line" id="L179"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f23: <span class="tok-type">u21</span> = <span class="tok-number">57386</span>;</span>
<span class="line" id="L180"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f24: <span class="tok-type">u21</span> = <span class="tok-number">57387</span>;</span>
<span class="line" id="L181"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f25: <span class="tok-type">u21</span> = <span class="tok-number">57388</span>;</span>
<span class="line" id="L182"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f26: <span class="tok-type">u21</span> = <span class="tok-number">57389</span>;</span>
<span class="line" id="L183"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f27: <span class="tok-type">u21</span> = <span class="tok-number">57390</span>;</span>
<span class="line" id="L184"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f28: <span class="tok-type">u21</span> = <span class="tok-number">57391</span>;</span>
<span class="line" id="L185"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f29: <span class="tok-type">u21</span> = <span class="tok-number">57392</span>;</span>
<span class="line" id="L186"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f30: <span class="tok-type">u21</span> = <span class="tok-number">57393</span>;</span>
<span class="line" id="L187"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f31: <span class="tok-type">u21</span> = <span class="tok-number">57394</span>;</span>
<span class="line" id="L188"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> @&quot;f32&quot;: <span class="tok-type">u21</span> = <span class="tok-number">57395</span>;</span>
<span class="line" id="L189"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f33: <span class="tok-type">u21</span> = <span class="tok-number">57396</span>;</span>
<span class="line" id="L190"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f34: <span class="tok-type">u21</span> = <span class="tok-number">57397</span>;</span>
<span class="line" id="L191"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> f35: <span class="tok-type">u21</span> = <span class="tok-number">57398</span>;</span>
<span class="line" id="L192"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_0: <span class="tok-type">u21</span> = <span class="tok-number">57399</span>;</span>
<span class="line" id="L193"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_1: <span class="tok-type">u21</span> = <span class="tok-number">57400</span>;</span>
<span class="line" id="L194"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_2: <span class="tok-type">u21</span> = <span class="tok-number">57401</span>;</span>
<span class="line" id="L195"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_3: <span class="tok-type">u21</span> = <span class="tok-number">57402</span>;</span>
<span class="line" id="L196"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_4: <span class="tok-type">u21</span> = <span class="tok-number">57403</span>;</span>
<span class="line" id="L197"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_5: <span class="tok-type">u21</span> = <span class="tok-number">57404</span>;</span>
<span class="line" id="L198"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_6: <span class="tok-type">u21</span> = <span class="tok-number">57405</span>;</span>
<span class="line" id="L199"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_7: <span class="tok-type">u21</span> = <span class="tok-number">57406</span>;</span>
<span class="line" id="L200"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_8: <span class="tok-type">u21</span> = <span class="tok-number">57407</span>;</span>
<span class="line" id="L201"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_9: <span class="tok-type">u21</span> = <span class="tok-number">57408</span>;</span>
<span class="line" id="L202"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_decimal: <span class="tok-type">u21</span> = <span class="tok-number">57409</span>;</span>
<span class="line" id="L203"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_divide: <span class="tok-type">u21</span> = <span class="tok-number">57410</span>;</span>
<span class="line" id="L204"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_multiply: <span class="tok-type">u21</span> = <span class="tok-number">57411</span>;</span>
<span class="line" id="L205"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_subtract: <span class="tok-type">u21</span> = <span class="tok-number">57412</span>;</span>
<span class="line" id="L206"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_add: <span class="tok-type">u21</span> = <span class="tok-number">57413</span>;</span>
<span class="line" id="L207"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_enter: <span class="tok-type">u21</span> = <span class="tok-number">57414</span>;</span>
<span class="line" id="L208"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_equal: <span class="tok-type">u21</span> = <span class="tok-number">57415</span>;</span>
<span class="line" id="L209"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_separator: <span class="tok-type">u21</span> = <span class="tok-number">57416</span>;</span>
<span class="line" id="L210"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_left: <span class="tok-type">u21</span> = <span class="tok-number">57417</span>;</span>
<span class="line" id="L211"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_right: <span class="tok-type">u21</span> = <span class="tok-number">57418</span>;</span>
<span class="line" id="L212"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_up: <span class="tok-type">u21</span> = <span class="tok-number">57419</span>;</span>
<span class="line" id="L213"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_down: <span class="tok-type">u21</span> = <span class="tok-number">57420</span>;</span>
<span class="line" id="L214"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_page_up: <span class="tok-type">u21</span> = <span class="tok-number">57421</span>;</span>
<span class="line" id="L215"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_page_down: <span class="tok-type">u21</span> = <span class="tok-number">57422</span>;</span>
<span class="line" id="L216"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_home: <span class="tok-type">u21</span> = <span class="tok-number">57423</span>;</span>
<span class="line" id="L217"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_end: <span class="tok-type">u21</span> = <span class="tok-number">57424</span>;</span>
<span class="line" id="L218"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_insert: <span class="tok-type">u21</span> = <span class="tok-number">57425</span>;</span>
<span class="line" id="L219"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_delete: <span class="tok-type">u21</span> = <span class="tok-number">57426</span>;</span>
<span class="line" id="L220"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kp_begin: <span class="tok-type">u21</span> = <span class="tok-number">57427</span>;</span>
<span class="line" id="L221"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_play: <span class="tok-type">u21</span> = <span class="tok-number">57428</span>;</span>
<span class="line" id="L222"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_pause: <span class="tok-type">u21</span> = <span class="tok-number">57429</span>;</span>
<span class="line" id="L223"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_play_pause: <span class="tok-type">u21</span> = <span class="tok-number">57430</span>;</span>
<span class="line" id="L224"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_reverse: <span class="tok-type">u21</span> = <span class="tok-number">57431</span>;</span>
<span class="line" id="L225"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_stop: <span class="tok-type">u21</span> = <span class="tok-number">57432</span>;</span>
<span class="line" id="L226"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_fast_forward: <span class="tok-type">u21</span> = <span class="tok-number">57433</span>;</span>
<span class="line" id="L227"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_rewind: <span class="tok-type">u21</span> = <span class="tok-number">57434</span>;</span>
<span class="line" id="L228"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_track_next: <span class="tok-type">u21</span> = <span class="tok-number">57435</span>;</span>
<span class="line" id="L229"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_track_previous: <span class="tok-type">u21</span> = <span class="tok-number">57436</span>;</span>
<span class="line" id="L230"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> media_record: <span class="tok-type">u21</span> = <span class="tok-number">57437</span>;</span>
<span class="line" id="L231"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> lower_volume: <span class="tok-type">u21</span> = <span class="tok-number">57438</span>;</span>
<span class="line" id="L232"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> raise_volume: <span class="tok-type">u21</span> = <span class="tok-number">57439</span>;</span>
<span class="line" id="L233"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mute_volume: <span class="tok-type">u21</span> = <span class="tok-number">57440</span>;</span>
<span class="line" id="L234"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_shift: <span class="tok-type">u21</span> = <span class="tok-number">57441</span>;</span>
<span class="line" id="L235"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_control: <span class="tok-type">u21</span> = <span class="tok-number">57442</span>;</span>
<span class="line" id="L236"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_alt: <span class="tok-type">u21</span> = <span class="tok-number">57443</span>;</span>
<span class="line" id="L237"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_super: <span class="tok-type">u21</span> = <span class="tok-number">57444</span>;</span>
<span class="line" id="L238"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_hyper: <span class="tok-type">u21</span> = <span class="tok-number">57445</span>;</span>
<span class="line" id="L239"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> left_meta: <span class="tok-type">u21</span> = <span class="tok-number">57446</span>;</span>
<span class="line" id="L240"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_shift: <span class="tok-type">u21</span> = <span class="tok-number">57447</span>;</span>
<span class="line" id="L241"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_control: <span class="tok-type">u21</span> = <span class="tok-number">57448</span>;</span>
<span class="line" id="L242"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_alt: <span class="tok-type">u21</span> = <span class="tok-number">57449</span>;</span>
<span class="line" id="L243"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_super: <span class="tok-type">u21</span> = <span class="tok-number">57450</span>;</span>
<span class="line" id="L244"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_hyper: <span class="tok-type">u21</span> = <span class="tok-number">57451</span>;</span>
<span class="line" id="L245"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> right_meta: <span class="tok-type">u21</span> = <span class="tok-number">57452</span>;</span>
<span class="line" id="L246"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> iso_level_3_shift: <span class="tok-type">u21</span> = <span class="tok-number">57453</span>;</span>
<span class="line" id="L247"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> iso_level_5_shift: <span class="tok-type">u21</span> = <span class="tok-number">57454</span>;</span>
<span class="line" id="L248"></span>
<span class="line" id="L249"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'a'&quot;</span> {</span>
<span class="line" id="L250"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L251"> .codepoint = <span class="tok-str">'a'</span>,</span>
<span class="line" id="L252"> };</span>
<span class="line" id="L253"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'a'</span>, .{}));</span>
<span class="line" id="L254">}</span>
<span class="line" id="L255"></span>
<span class="line" id="L256"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+a'&quot;</span> {</span>
<span class="line" id="L257"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L258"> .codepoint = <span class="tok-str">'a'</span>,</span>
<span class="line" id="L259"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L260"> .text = <span class="tok-str">&quot;A&quot;</span>,</span>
<span class="line" id="L261"> };</span>
<span class="line" id="L262"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'a'</span>, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L263"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">'A'</span>, .{}));</span>
<span class="line" id="L264"> <span class="tok-kw">try</span> testing.expect(!key.matches(<span class="tok-str">'A'</span>, .{ .ctrl = <span class="tok-null">true</span> }));</span>
<span class="line" id="L265">}</span>
<span class="line" id="L266"></span>
<span class="line" id="L267"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+tab'&quot;</span> {</span>
<span class="line" id="L268"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L269"> .codepoint = Key.tab,</span>
<span class="line" id="L270"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L271"> };</span>
<span class="line" id="L272"> <span class="tok-kw">try</span> testing.expect(key.matches(Key.tab, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L273"> <span class="tok-kw">try</span> testing.expect(!key.matches(Key.tab, .{}));</span>
<span class="line" id="L274">}</span>
<span class="line" id="L275"></span>
<span class="line" id="L276"><span class="tok-kw">test</span> <span class="tok-str">&quot;matches 'shift+;'&quot;</span> {</span>
<span class="line" id="L277"> <span class="tok-kw">const</span> key: Key = .{</span>
<span class="line" id="L278"> .codepoint = <span class="tok-str">';'</span>,</span>
<span class="line" id="L279"> .shifted_codepoint = <span class="tok-str">':'</span>,</span>
<span class="line" id="L280"> .mods = .{ .shift = <span class="tok-null">true</span> },</span>
<span class="line" id="L281"> .text = <span class="tok-str">&quot;:&quot;</span>,</span>
<span class="line" id="L282"> };</span>
<span class="line" id="L283"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">';'</span>, .{ .shift = <span class="tok-null">true</span> }));</span>
<span class="line" id="L284"> <span class="tok-kw">try</span> testing.expect(key.matches(<span class="tok-str">':'</span>, .{}));</span>
<span class="line" id="L285"></span>
<span class="line" id="L286"> <span class="tok-kw">const</span> colon: Key = .{</span>
<span class="line" id="L287"> .codepoint = <span class="tok-str">':'</span>,</span>
<span class="line" id="L288"> .mods = .{},</span>
<span class="line" id="L289"> };</span>
<span class="line" id="L290"> <span class="tok-kw">try</span> testing.expect(colon.matches(<span class="tok-str">':'</span>, .{}));</span>
<span class="line" id="L291">}</span>
<span class="line" id="L292"></span>
</code></pre></body>
</html>

View file

@ -1,163 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Mouse.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">/// A mouse event</span></span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Shape = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L5"> default,</span>
<span class="line" id="L6"> text,</span>
<span class="line" id="L7"> pointer,</span>
<span class="line" id="L8"> help,</span>
<span class="line" id="L9"> progress,</span>
<span class="line" id="L10"> wait,</span>
<span class="line" id="L11"> @&quot;ew-resize&quot;,</span>
<span class="line" id="L12"> @&quot;ns-resize&quot;,</span>
<span class="line" id="L13"> cell,</span>
<span class="line" id="L14">};</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Button = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L17"> left,</span>
<span class="line" id="L18"> middle,</span>
<span class="line" id="L19"> right,</span>
<span class="line" id="L20"> none,</span>
<span class="line" id="L21"> wheel_up = <span class="tok-number">64</span>,</span>
<span class="line" id="L22"> wheel_down = <span class="tok-number">65</span>,</span>
<span class="line" id="L23"> button_8 = <span class="tok-number">128</span>,</span>
<span class="line" id="L24"> button_9 = <span class="tok-number">129</span>,</span>
<span class="line" id="L25"> button_10 = <span class="tok-number">130</span>,</span>
<span class="line" id="L26"> button_11 = <span class="tok-number">131</span>,</span>
<span class="line" id="L27">};</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Modifiers = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u3</span>) {</span>
<span class="line" id="L30"> shift: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L31"> alt: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L32"> ctrl: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L33">};</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Type = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L36"> press,</span>
<span class="line" id="L37"> release,</span>
<span class="line" id="L38"> motion,</span>
<span class="line" id="L39"> drag,</span>
<span class="line" id="L40">};</span>
<span class="line" id="L41"></span>
<span class="line" id="L42">col: <span class="tok-type">usize</span>,</span>
<span class="line" id="L43">row: <span class="tok-type">usize</span>,</span>
<span class="line" id="L44">button: Button,</span>
<span class="line" id="L45">mods: Modifiers,</span>
<span class="line" id="L46"><span class="tok-type">type</span>: Type,</span>
<span class="line" id="L47"></span>
</code></pre></body>
</html>

View file

@ -1,119 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Options.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">/// Runtime options</span></span>
<span class="line" id="L2"><span class="tok-kw">const</span> Options = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L3"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,181 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Screen.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Shape = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>).Shape;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Winsize = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Tty.zig&quot;</span>).Winsize;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> log = std.log.scoped(.screen);</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> Screen = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L12"></span>
<span class="line" id="L13">width: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L14">height: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L15"></span>
<span class="line" id="L16">width_pix: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17">height_pix: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19">buf: []Cell = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L20"></span>
<span class="line" id="L21">cursor_row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L22">cursor_col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L23">cursor_vis: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-comment">/// true when we measure cells with unicode</span></span>
<span class="line" id="L26">unicode: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28">mouse_shape: Shape = .default,</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator, winsize: Winsize) !Screen {</span>
<span class="line" id="L31"> <span class="tok-kw">const</span> w = winsize.cols;</span>
<span class="line" id="L32"> <span class="tok-kw">const</span> h = winsize.rows;</span>
<span class="line" id="L33"> <span class="tok-kw">var</span> self = Screen{</span>
<span class="line" id="L34"> .buf = <span class="tok-kw">try</span> alloc.alloc(Cell, w * h),</span>
<span class="line" id="L35"> .width = w,</span>
<span class="line" id="L36"> .height = h,</span>
<span class="line" id="L37"> .width_pix = winsize.x_pixel,</span>
<span class="line" id="L38"> .height_pix = winsize.y_pixel,</span>
<span class="line" id="L39"> };</span>
<span class="line" id="L40"> <span class="tok-kw">for</span> (self.buf, <span class="tok-number">0</span>..) |_, i| {</span>
<span class="line" id="L41"> self.buf[i] = .{};</span>
<span class="line" id="L42"> }</span>
<span class="line" id="L43"> <span class="tok-kw">return</span> self;</span>
<span class="line" id="L44">}</span>
<span class="line" id="L45"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Screen, alloc: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L46"> alloc.free(self.buf);</span>
<span class="line" id="L47">}</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"><span class="tok-comment">/// writes a cell to a location. 0 indexed</span></span>
<span class="line" id="L50"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(self: *Screen, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L51"> <span class="tok-kw">if</span> (self.width &lt; col) {</span>
<span class="line" id="L52"> <span class="tok-comment">// column out of bounds</span>
</span>
<span class="line" id="L53"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L54"> }</span>
<span class="line" id="L55"> <span class="tok-kw">if</span> (self.height &lt; row) {</span>
<span class="line" id="L56"> <span class="tok-comment">// height out of bounds</span>
</span>
<span class="line" id="L57"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L58"> }</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> i = (row * self.width) + col;</span>
<span class="line" id="L60"> assert(i &lt; self.buf.len);</span>
<span class="line" id="L61"> self.buf[i] = cell;</span>
<span class="line" id="L62">}</span>
<span class="line" id="L63"></span>
</code></pre></body>
</html>

View file

@ -1,411 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tty.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> builtin = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;builtin&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> os = std.os;</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> BufferedWriter = std.io.BufferedWriter(<span class="tok-number">4096</span>, Writer);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> Writer = std.io.Writer(os.fd_t, os.WriteError, os.write);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> Vaxis = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;vaxis.zig&quot;</span>).Vaxis;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Parser = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Parser.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> GraphemeCache = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;GraphemeCache.zig&quot;</span>);</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> log = std.log.scoped(.tty);</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> Tty = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-comment">/// the original state of the terminal, prior to calling makeRaw</span></span>
<span class="line" id="L18">termios: os.termios,</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// The file descriptor we are using for I/O</span></span>
<span class="line" id="L21">fd: os.fd_t,</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"><span class="tok-comment">/// the write end of a pipe to signal the tty should exit it's run loop</span></span>
<span class="line" id="L24">quit_fd: ?os.fd_t = <span class="tok-null">null</span>,</span>
<span class="line" id="L25"></span>
<span class="line" id="L26">buffered_writer: BufferedWriter,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"><span class="tok-comment">/// initializes a Tty instance by opening /dev/tty and &quot;making it raw&quot;</span></span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>() !Tty {</span>
<span class="line" id="L30"> <span class="tok-comment">// Open our tty</span>
</span>
<span class="line" id="L31"> <span class="tok-kw">const</span> fd = <span class="tok-kw">try</span> os.open(<span class="tok-str">&quot;/dev/tty&quot;</span>, .{ .ACCMODE = .RDWR }, <span class="tok-number">0</span>);</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"> <span class="tok-comment">// Set the termios of the tty</span>
</span>
<span class="line" id="L34"> <span class="tok-kw">const</span> termios = <span class="tok-kw">try</span> makeRaw(fd);</span>
<span class="line" id="L35"></span>
<span class="line" id="L36"> <span class="tok-kw">return</span> Tty{</span>
<span class="line" id="L37"> .fd = fd,</span>
<span class="line" id="L38"> .termios = termios,</span>
<span class="line" id="L39"> .buffered_writer = std.io.bufferedWriter(Writer{ .context = fd }),</span>
<span class="line" id="L40"> };</span>
<span class="line" id="L41">}</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"><span class="tok-comment">/// release resources associated with the Tty return it to it's original state</span></span>
<span class="line" id="L44"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Tty) <span class="tok-type">void</span> {</span>
<span class="line" id="L45"> os.tcsetattr(self.fd, .FLUSH, self.termios) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L46"> log.err(<span class="tok-str">&quot;couldn't restore terminal: {}&quot;</span>, .{err});</span>
<span class="line" id="L47"> };</span>
<span class="line" id="L48"> os.close(self.fd);</span>
<span class="line" id="L49">}</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"><span class="tok-comment">/// stops the run loop</span></span>
<span class="line" id="L52"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stop</span>(self: *Tty) <span class="tok-type">void</span> {</span>
<span class="line" id="L53"> <span class="tok-kw">if</span> (self.quit_fd) |fd| {</span>
<span class="line" id="L54"> _ = std.os.write(fd, <span class="tok-str">&quot;q&quot;</span>) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56">}</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"><span class="tok-comment">/// read input from the tty</span></span>
<span class="line" id="L59"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">run</span>(</span>
<span class="line" id="L60"> self: *Tty,</span>
<span class="line" id="L61"> <span class="tok-kw">comptime</span> Event: <span class="tok-type">type</span>,</span>
<span class="line" id="L62"> vx: *Vaxis(Event),</span>
<span class="line" id="L63">) !<span class="tok-type">void</span> {</span>
<span class="line" id="L64"> <span class="tok-comment">// create a pipe so we can signal to exit the run loop</span>
</span>
<span class="line" id="L65"> <span class="tok-kw">const</span> pipe = <span class="tok-kw">try</span> os.pipe();</span>
<span class="line" id="L66"> <span class="tok-kw">defer</span> os.close(pipe[<span class="tok-number">0</span>]);</span>
<span class="line" id="L67"> <span class="tok-kw">defer</span> os.close(pipe[<span class="tok-number">1</span>]);</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"> <span class="tok-comment">// get our initial winsize</span>
</span>
<span class="line" id="L70"> <span class="tok-kw">const</span> winsize = <span class="tok-kw">try</span> getWinsize(self.fd);</span>
<span class="line" id="L71"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;winsize&quot;</span>)) {</span>
<span class="line" id="L72"> vx.postEvent(.{ .winsize = winsize });</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-comment">// assign the write end of the pipe to our quit_fd</span>
</span>
<span class="line" id="L76"> self.quit_fd = pipe[<span class="tok-number">1</span>];</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-comment">// Build a winch handler. We need build this struct to get an anonymous</span>
</span>
<span class="line" id="L79"> <span class="tok-comment">// function which can post the winsize event</span>
</span>
<span class="line" id="L80"> <span class="tok-comment">// TODO: more signals, move this outside of this function?</span>
</span>
<span class="line" id="L81"> <span class="tok-kw">const</span> WinchHandler = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L83"></span>
<span class="line" id="L84"> <span class="tok-kw">var</span> vx_winch: *Vaxis(Event) = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L85"> <span class="tok-kw">var</span> fd: os.fd_t = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(vx_arg: *Vaxis(Event), fd_arg: os.fd_t) !<span class="tok-type">void</span> {</span>
<span class="line" id="L88"> vx_winch = vx_arg;</span>
<span class="line" id="L89"> fd = fd_arg;</span>
<span class="line" id="L90"> <span class="tok-kw">var</span> act = os.Sigaction{</span>
<span class="line" id="L91"> .handler = .{ .handler = Self.handleWinch },</span>
<span class="line" id="L92"> .mask = <span class="tok-kw">switch</span> (builtin.os.tag) {</span>
<span class="line" id="L93"> .macos =&gt; <span class="tok-number">0</span>,</span>
<span class="line" id="L94"> .linux =&gt; std.os.empty_sigset,</span>
<span class="line" id="L95"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;os not supported&quot;</span>),</span>
<span class="line" id="L96"> },</span>
<span class="line" id="L97"> .flags = <span class="tok-number">0</span>,</span>
<span class="line" id="L98"> };</span>
<span class="line" id="L99"></span>
<span class="line" id="L100"> <span class="tok-kw">try</span> os.sigaction(os.SIG.WINCH, &amp;act, <span class="tok-null">null</span>);</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"> <span class="tok-kw">fn</span> <span class="tok-fn">handleWinch</span>(_: <span class="tok-type">c_int</span>) <span class="tok-kw">callconv</span>(.C) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">const</span> ws = getWinsize(fd) <span class="tok-kw">catch</span> {</span>
<span class="line" id="L105"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L106"> };</span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;winsize&quot;</span>)) {</span>
<span class="line" id="L108"> vx_winch.postEvent(.{ .winsize = ws });</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"> }</span>
<span class="line" id="L111"> };</span>
<span class="line" id="L112"> <span class="tok-kw">try</span> WinchHandler.init(vx, self.fd);</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"> <span class="tok-comment">// initialize a grapheme cache</span>
</span>
<span class="line" id="L115"> <span class="tok-kw">var</span> cache: GraphemeCache = .{};</span>
<span class="line" id="L116"></span>
<span class="line" id="L117"> <span class="tok-comment">// Set up fds for polling</span>
</span>
<span class="line" id="L118"> <span class="tok-kw">var</span> pollfds: [<span class="tok-number">2</span>]std.os.pollfd = .{</span>
<span class="line" id="L119"> .{ .fd = self.fd, .events = std.os.POLL.IN, .revents = <span class="tok-null">undefined</span> },</span>
<span class="line" id="L120"> .{ .fd = pipe[<span class="tok-number">0</span>], .events = std.os.POLL.IN, .revents = <span class="tok-null">undefined</span> },</span>
<span class="line" id="L121"> };</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> <span class="tok-kw">var</span> parser: Parser = .{};</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-comment">// initialize the read buffer</span>
</span>
<span class="line" id="L126"> <span class="tok-kw">var</span> buf: [<span class="tok-number">1024</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L127"> <span class="tok-comment">// read loop</span>
</span>
<span class="line" id="L128"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L129"> _ = <span class="tok-kw">try</span> std.os.poll(&amp;pollfds, -<span class="tok-number">1</span>);</span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (pollfds[<span class="tok-number">1</span>].revents &amp; std.os.POLL.IN != <span class="tok-number">0</span>) {</span>
<span class="line" id="L131"> log.info(<span class="tok-str">&quot;quitting read thread&quot;</span>, .{});</span>
<span class="line" id="L132"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L133"> }</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"> <span class="tok-kw">const</span> n = <span class="tok-kw">try</span> os.read(self.fd, &amp;buf);</span>
<span class="line" id="L136"> <span class="tok-kw">var</span> start: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L137"> <span class="tok-kw">while</span> (start &lt; n) {</span>
<span class="line" id="L138"> <span class="tok-kw">const</span> result = <span class="tok-kw">try</span> parser.parse(buf[start..n]);</span>
<span class="line" id="L139"> start += result.n;</span>
<span class="line" id="L140"> <span class="tok-comment">// TODO: if we get 0 byte read, copy the remaining bytes to the</span>
</span>
<span class="line" id="L141"> <span class="tok-comment">// beginning of the buffer and read mmore? this should only happen</span>
</span>
<span class="line" id="L142"> <span class="tok-comment">// if we are in the middle of a grapheme at and filled our</span>
</span>
<span class="line" id="L143"> <span class="tok-comment">// buffer. Probably can happen on large pastes so needs to be</span>
</span>
<span class="line" id="L144"> <span class="tok-comment">// implemented but low priority</span>
</span>
<span class="line" id="L145"></span>
<span class="line" id="L146"> <span class="tok-kw">const</span> event = result.event <span class="tok-kw">orelse</span> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L147"> <span class="tok-kw">switch</span> (event) {</span>
<span class="line" id="L148"> .key_press =&gt; |key| {</span>
<span class="line" id="L149"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;key_press&quot;</span>)) {</span>
<span class="line" id="L150"> <span class="tok-comment">// HACK: yuck. there has to be a better way</span>
</span>
<span class="line" id="L151"> <span class="tok-kw">var</span> mut_key = key;</span>
<span class="line" id="L152"> <span class="tok-kw">if</span> (key.text) |text| {</span>
<span class="line" id="L153"> mut_key.text = cache.put(text);</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"> vx.postEvent(.{ .key_press = mut_key });</span>
<span class="line" id="L156"> }</span>
<span class="line" id="L157"> },</span>
<span class="line" id="L158"> .mouse =&gt; |mouse| {</span>
<span class="line" id="L159"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;mouse&quot;</span>)) {</span>
<span class="line" id="L160"> vx.postEvent(.{ .mouse = mouse });</span>
<span class="line" id="L161"> }</span>
<span class="line" id="L162"> },</span>
<span class="line" id="L163"> .focus_in =&gt; {</span>
<span class="line" id="L164"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;focus_in&quot;</span>)) {</span>
<span class="line" id="L165"> vx.postEvent(.focus_in);</span>
<span class="line" id="L166"> }</span>
<span class="line" id="L167"> },</span>
<span class="line" id="L168"> .focus_out =&gt; {</span>
<span class="line" id="L169"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;focus_out&quot;</span>)) {</span>
<span class="line" id="L170"> vx.postEvent(.focus_out);</span>
<span class="line" id="L171"> }</span>
<span class="line" id="L172"> },</span>
<span class="line" id="L173"> .paste_start =&gt; {</span>
<span class="line" id="L174"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;paste_start&quot;</span>)) {</span>
<span class="line" id="L175"> vx.postEvent(.paste_start);</span>
<span class="line" id="L176"> }</span>
<span class="line" id="L177"> },</span>
<span class="line" id="L178"> .paste_end =&gt; {</span>
<span class="line" id="L179"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;paste_end&quot;</span>)) {</span>
<span class="line" id="L180"> vx.postEvent(.paste_end);</span>
<span class="line" id="L181"> }</span>
<span class="line" id="L182"> },</span>
<span class="line" id="L183"> .cap_kitty_keyboard =&gt; {</span>
<span class="line" id="L184"> log.info(<span class="tok-str">&quot;kitty keyboard capability detected&quot;</span>, .{});</span>
<span class="line" id="L185"> vx.caps.kitty_keyboard = <span class="tok-null">true</span>;</span>
<span class="line" id="L186"> },</span>
<span class="line" id="L187"> .cap_kitty_graphics =&gt; {</span>
<span class="line" id="L188"> <span class="tok-kw">if</span> (!vx.caps.kitty_graphics) {</span>
<span class="line" id="L189"> log.info(<span class="tok-str">&quot;kitty graphics capability detected&quot;</span>, .{});</span>
<span class="line" id="L190"> vx.caps.kitty_graphics = <span class="tok-null">true</span>;</span>
<span class="line" id="L191"> }</span>
<span class="line" id="L192"> },</span>
<span class="line" id="L193"> .cap_rgb =&gt; {</span>
<span class="line" id="L194"> log.info(<span class="tok-str">&quot;rgb capability detected&quot;</span>, .{});</span>
<span class="line" id="L195"> vx.caps.rgb = <span class="tok-null">true</span>;</span>
<span class="line" id="L196"> },</span>
<span class="line" id="L197"> .cap_unicode =&gt; {</span>
<span class="line" id="L198"> log.info(<span class="tok-str">&quot;unicode capability detected&quot;</span>, .{});</span>
<span class="line" id="L199"> vx.caps.unicode = <span class="tok-null">true</span>;</span>
<span class="line" id="L200"> vx.screen.unicode = <span class="tok-null">true</span>;</span>
<span class="line" id="L201"> },</span>
<span class="line" id="L202"> .cap_da1 =&gt; {</span>
<span class="line" id="L203"> std.Thread.Futex.wake(&amp;vx.query_futex, <span class="tok-number">10</span>);</span>
<span class="line" id="L204"> },</span>
<span class="line" id="L205"> }</span>
<span class="line" id="L206"> }</span>
<span class="line" id="L207"> }</span>
<span class="line" id="L208">}</span>
<span class="line" id="L209"></span>
<span class="line" id="L210"><span class="tok-comment">/// write to the tty. These writes are buffered and require calling flush to</span></span>
<span class="line" id="L211"><span class="tok-comment">/// flush writes to the tty</span></span>
<span class="line" id="L212"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Tty, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">usize</span> {</span>
<span class="line" id="L213"> <span class="tok-kw">return</span> self.buffered_writer.write(bytes);</span>
<span class="line" id="L214">}</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"><span class="tok-comment">/// flushes the write buffer to the tty</span></span>
<span class="line" id="L217"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">flush</span>(self: *Tty) !<span class="tok-type">void</span> {</span>
<span class="line" id="L218"> <span class="tok-kw">try</span> self.buffered_writer.flush();</span>
<span class="line" id="L219">}</span>
<span class="line" id="L220"></span>
<span class="line" id="L221"><span class="tok-comment">/// makeRaw enters the raw state for the terminal.</span></span>
<span class="line" id="L222"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">makeRaw</span>(fd: os.fd_t) !os.termios {</span>
<span class="line" id="L223"> <span class="tok-kw">const</span> state = <span class="tok-kw">try</span> os.tcgetattr(fd);</span>
<span class="line" id="L224"> <span class="tok-kw">var</span> raw = state;</span>
<span class="line" id="L225"> <span class="tok-comment">// see termios(3)</span>
</span>
<span class="line" id="L226"> raw.iflag.IGNBRK = <span class="tok-null">false</span>;</span>
<span class="line" id="L227"> raw.iflag.BRKINT = <span class="tok-null">false</span>;</span>
<span class="line" id="L228"> raw.iflag.ISTRIP = <span class="tok-null">false</span>;</span>
<span class="line" id="L229"> raw.iflag.INLCR = <span class="tok-null">false</span>;</span>
<span class="line" id="L230"> raw.iflag.IGNCR = <span class="tok-null">false</span>;</span>
<span class="line" id="L231"> raw.iflag.ICRNL = <span class="tok-null">false</span>;</span>
<span class="line" id="L232"> raw.iflag.IXON = <span class="tok-null">false</span>;</span>
<span class="line" id="L233"></span>
<span class="line" id="L234"> raw.oflag.OPOST = <span class="tok-null">false</span>;</span>
<span class="line" id="L235"></span>
<span class="line" id="L236"> raw.lflag.ECHO = <span class="tok-null">false</span>;</span>
<span class="line" id="L237"> raw.lflag.ECHONL = <span class="tok-null">false</span>;</span>
<span class="line" id="L238"> raw.lflag.ICANON = <span class="tok-null">false</span>;</span>
<span class="line" id="L239"> raw.lflag.IEXTEN = <span class="tok-null">false</span>;</span>
<span class="line" id="L240"></span>
<span class="line" id="L241"> raw.cflag.CSIZE = .CS8;</span>
<span class="line" id="L242"> raw.cflag.PARENB = <span class="tok-null">false</span>;</span>
<span class="line" id="L243"></span>
<span class="line" id="L244"> raw.cc[<span class="tok-builtin">@intFromEnum</span>(std.posix.V.MIN)] = <span class="tok-number">1</span>;</span>
<span class="line" id="L245"> raw.cc[<span class="tok-builtin">@intFromEnum</span>(std.posix.V.TIME)] = <span class="tok-number">0</span>;</span>
<span class="line" id="L246"> <span class="tok-kw">try</span> os.tcsetattr(fd, .FLUSH, raw);</span>
<span class="line" id="L247"> <span class="tok-kw">return</span> state;</span>
<span class="line" id="L248">}</span>
<span class="line" id="L249"></span>
<span class="line" id="L250"><span class="tok-comment">/// The size of the terminal screen</span></span>
<span class="line" id="L251"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Winsize = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L252"> rows: <span class="tok-type">usize</span>,</span>
<span class="line" id="L253"> cols: <span class="tok-type">usize</span>,</span>
<span class="line" id="L254"> x_pixel: <span class="tok-type">usize</span>,</span>
<span class="line" id="L255"> y_pixel: <span class="tok-type">usize</span>,</span>
<span class="line" id="L256">};</span>
<span class="line" id="L257"></span>
<span class="line" id="L258"><span class="tok-kw">fn</span> <span class="tok-fn">getWinsize</span>(fd: os.fd_t) !Winsize {</span>
<span class="line" id="L259"> <span class="tok-kw">var</span> winsize = os.winsize{</span>
<span class="line" id="L260"> .ws_row = <span class="tok-number">0</span>,</span>
<span class="line" id="L261"> .ws_col = <span class="tok-number">0</span>,</span>
<span class="line" id="L262"> .ws_xpixel = <span class="tok-number">0</span>,</span>
<span class="line" id="L263"> .ws_ypixel = <span class="tok-number">0</span>,</span>
<span class="line" id="L264"> };</span>
<span class="line" id="L265"></span>
<span class="line" id="L266"> <span class="tok-kw">const</span> err = os.system.ioctl(fd, os.T.IOCGWINSZ, <span class="tok-builtin">@intFromPtr</span>(&amp;winsize));</span>
<span class="line" id="L267"> <span class="tok-kw">if</span> (os.errno(err) == .SUCCESS)</span>
<span class="line" id="L268"> <span class="tok-kw">return</span> Winsize{</span>
<span class="line" id="L269"> .rows = winsize.ws_row,</span>
<span class="line" id="L270"> .cols = winsize.ws_col,</span>
<span class="line" id="L271"> .x_pixel = winsize.ws_xpixel,</span>
<span class="line" id="L272"> .y_pixel = winsize.ws_ypixel,</span>
<span class="line" id="L273"> };</span>
<span class="line" id="L274"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.IoctlError;</span>
<span class="line" id="L275">}</span>
<span class="line" id="L276"></span>
</code></pre></body>
</html>

View file

@ -1,338 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Window.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> WordIterator = ziglyph.WordIterator;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> GraphemeIterator = ziglyph.GraphemeIterator;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Screen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Screen.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Segment = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>).Segment;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> gw = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;gwidth.zig&quot;</span>);</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> log = std.log.scoped(.window);</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Window = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Size = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L16"> expand,</span>
<span class="line" id="L17"> limit: <span class="tok-type">usize</span>,</span>
<span class="line" id="L18">};</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// horizontal offset from the screen</span></span>
<span class="line" id="L21">x_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L22"><span class="tok-comment">/// vertical offset from the screen</span></span>
<span class="line" id="L23">y_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L24"><span class="tok-comment">/// width of the window. This can't be larger than the terminal screen</span></span>
<span class="line" id="L25">width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L26"><span class="tok-comment">/// height of the window. This can't be larger than the terminal screen</span></span>
<span class="line" id="L27">height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L28"></span>
<span class="line" id="L29">screen: *Screen,</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-comment">/// Creates a new window with offset relative to parent and size clamped to the</span></span>
<span class="line" id="L32"><span class="tok-comment">/// parent's size. Windows do not retain a reference to their parent and are</span></span>
<span class="line" id="L33"><span class="tok-comment">/// unaware of resizes.</span></span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">initChild</span>(</span>
<span class="line" id="L35"> self: Window,</span>
<span class="line" id="L36"> x_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L37"> y_off: <span class="tok-type">usize</span>,</span>
<span class="line" id="L38"> width: Size,</span>
<span class="line" id="L39"> height: Size,</span>
<span class="line" id="L40">) Window {</span>
<span class="line" id="L41"> <span class="tok-kw">const</span> resolved_width = <span class="tok-kw">switch</span> (width) {</span>
<span class="line" id="L42"> .expand =&gt; self.width - x_off,</span>
<span class="line" id="L43"> .limit =&gt; |w| blk: {</span>
<span class="line" id="L44"> <span class="tok-kw">if</span> (w + x_off &gt; self.width) {</span>
<span class="line" id="L45"> <span class="tok-kw">break</span> :blk self.width - x_off;</span>
<span class="line" id="L46"> }</span>
<span class="line" id="L47"> <span class="tok-kw">break</span> :blk w;</span>
<span class="line" id="L48"> },</span>
<span class="line" id="L49"> };</span>
<span class="line" id="L50"> <span class="tok-kw">const</span> resolved_height = <span class="tok-kw">switch</span> (height) {</span>
<span class="line" id="L51"> .expand =&gt; self.height - y_off,</span>
<span class="line" id="L52"> .limit =&gt; |h| blk: {</span>
<span class="line" id="L53"> <span class="tok-kw">if</span> (h + y_off &gt; self.height) {</span>
<span class="line" id="L54"> <span class="tok-kw">break</span> :blk self.height - y_off;</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> <span class="tok-kw">break</span> :blk h;</span>
<span class="line" id="L57"> },</span>
<span class="line" id="L58"> };</span>
<span class="line" id="L59"> <span class="tok-kw">return</span> Window{</span>
<span class="line" id="L60"> .x_off = x_off + self.x_off,</span>
<span class="line" id="L61"> .y_off = y_off + self.y_off,</span>
<span class="line" id="L62"> .width = resolved_width,</span>
<span class="line" id="L63"> .height = resolved_height,</span>
<span class="line" id="L64"> .screen = self.screen,</span>
<span class="line" id="L65"> };</span>
<span class="line" id="L66">}</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"><span class="tok-comment">/// writes a cell to the location in the window</span></span>
<span class="line" id="L69"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeCell</span>(self: Window, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (self.height == <span class="tok-number">0</span> <span class="tok-kw">or</span> self.width == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L71"> <span class="tok-kw">if</span> (self.height &lt;= row <span class="tok-kw">or</span> self.width &lt;= col) <span class="tok-kw">return</span>;</span>
<span class="line" id="L72"> self.screen.writeCell(col + self.x_off, row + self.y_off, cell);</span>
<span class="line" id="L73">}</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"><span class="tok-comment">/// fills the window with the default cell</span></span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">clear</span>(self: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L77"> self.fill(.{});</span>
<span class="line" id="L78">}</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"><span class="tok-comment">/// returns the width of the grapheme. This depends on the terminal capabilities</span></span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">gwidth</span>(self: Window, str: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">const</span> m: gw.Method = <span class="tok-kw">if</span> (self.screen.unicode) .unicode <span class="tok-kw">else</span> .wcwidth;</span>
<span class="line" id="L83"> <span class="tok-kw">return</span> gw.gwidth(str, m) <span class="tok-kw">catch</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L84">}</span>
<span class="line" id="L85"></span>
<span class="line" id="L86"><span class="tok-comment">/// fills the window with the provided cell</span></span>
<span class="line" id="L87"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fill</span>(self: Window, cell: Cell) <span class="tok-type">void</span> {</span>
<span class="line" id="L88"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = self.y_off;</span>
<span class="line" id="L89"> <span class="tok-kw">while</span> (row &lt; (self.height + self.y_off)) : (row += <span class="tok-number">1</span>) {</span>
<span class="line" id="L90"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = self.x_off;</span>
<span class="line" id="L91"> <span class="tok-kw">while</span> (col &lt; (self.width + self.x_off)) : (col += <span class="tok-number">1</span>) {</span>
<span class="line" id="L92"> self.screen.writeCell(col, row, cell);</span>
<span class="line" id="L93"> }</span>
<span class="line" id="L94"> }</span>
<span class="line" id="L95">}</span>
<span class="line" id="L96"></span>
<span class="line" id="L97"><span class="tok-comment">/// hide the cursor</span></span>
<span class="line" id="L98"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">hideCursor</span>(self: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L99"> self.screen.cursor_vis = <span class="tok-null">false</span>;</span>
<span class="line" id="L100">}</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"><span class="tok-comment">/// show the cursor at the given coordinates, 0 indexed</span></span>
<span class="line" id="L103"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">showCursor</span>(self: Window, col: <span class="tok-type">usize</span>, row: <span class="tok-type">usize</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">if</span> (self.height == <span class="tok-number">0</span> <span class="tok-kw">or</span> self.width == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L105"> <span class="tok-kw">if</span> (self.height &lt;= row <span class="tok-kw">or</span> self.width &lt;= col) <span class="tok-kw">return</span>;</span>
<span class="line" id="L106"> self.screen.cursor_vis = <span class="tok-null">true</span>;</span>
<span class="line" id="L107"> self.screen.cursor_row = row + self.y_off;</span>
<span class="line" id="L108"> self.screen.cursor_col = col + self.x_off;</span>
<span class="line" id="L109">}</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"><span class="tok-comment">/// prints text in the window with simple word wrapping.</span></span>
<span class="line" id="L112"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">wrap</span>(self: Window, segments: []Segment) !<span class="tok-type">void</span> {</span>
<span class="line" id="L113"> <span class="tok-comment">// pub fn wrap(self: Window, str: []const u8) !void {</span>
</span>
<span class="line" id="L114"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L115"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L116"> <span class="tok-kw">var</span> wrapped: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L117"> <span class="tok-kw">for</span> (segments) |segment| {</span>
<span class="line" id="L118"> <span class="tok-kw">var</span> word_iter = <span class="tok-kw">try</span> WordIterator.init(segment.text);</span>
<span class="line" id="L119"> <span class="tok-kw">while</span> (word_iter.next()) |word| {</span>
<span class="line" id="L120"> <span class="tok-comment">// break lines when we need</span>
</span>
<span class="line" id="L121"> <span class="tok-kw">if</span> (word.bytes[<span class="tok-number">0</span>] == <span class="tok-str">'\r'</span> <span class="tok-kw">or</span> word.bytes[<span class="tok-number">0</span>] == <span class="tok-str">'\n'</span>) {</span>
<span class="line" id="L122"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L123"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L124"> wrapped = <span class="tok-null">false</span>;</span>
<span class="line" id="L125"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L126"> }</span>
<span class="line" id="L127"> <span class="tok-comment">// break lines when we can't fit this word, and the word isn't longer</span>
</span>
<span class="line" id="L128"> <span class="tok-comment">// than our width</span>
</span>
<span class="line" id="L129"> <span class="tok-kw">const</span> word_width = self.gwidth(word.bytes);</span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (word_width + col &gt;= self.width <span class="tok-kw">and</span> word_width &lt; self.width) {</span>
<span class="line" id="L131"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L132"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L133"> wrapped = <span class="tok-null">true</span>;</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> <span class="tok-comment">// don't print whitespace in the first column, unless we had a hard</span>
</span>
<span class="line" id="L136"> <span class="tok-comment">// break</span>
</span>
<span class="line" id="L137"> <span class="tok-kw">if</span> (col == <span class="tok-number">0</span> <span class="tok-kw">and</span> std.mem.eql(<span class="tok-type">u8</span>, word.bytes, <span class="tok-str">&quot; &quot;</span>) <span class="tok-kw">and</span> wrapped) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(word.bytes);</span>
<span class="line" id="L139"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L140"> <span class="tok-kw">if</span> (col &gt;= self.width) {</span>
<span class="line" id="L141"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L142"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L143"> wrapped = <span class="tok-null">true</span>;</span>
<span class="line" id="L144"> }</span>
<span class="line" id="L145"> <span class="tok-kw">const</span> s = grapheme.slice(word.bytes);</span>
<span class="line" id="L146"> <span class="tok-kw">const</span> w = self.gwidth(s);</span>
<span class="line" id="L147"> self.writeCell(col, row, .{</span>
<span class="line" id="L148"> .char = .{</span>
<span class="line" id="L149"> .grapheme = s,</span>
<span class="line" id="L150"> .width = w,</span>
<span class="line" id="L151"> },</span>
<span class="line" id="L152"> .style = segment.style,</span>
<span class="line" id="L153"> .link = segment.link,</span>
<span class="line" id="L154"> });</span>
<span class="line" id="L155"> col += w;</span>
<span class="line" id="L156"> }</span>
<span class="line" id="L157"> }</span>
<span class="line" id="L158"> }</span>
<span class="line" id="L159">}</span>
<span class="line" id="L160"></span>
<span class="line" id="L161"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set&quot;</span> {</span>
<span class="line" id="L162"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L163"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L164"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L165"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L166"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L167"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L168"> };</span>
<span class="line" id="L169"></span>
<span class="line" id="L170"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">1</span>, <span class="tok-number">1</span>, .expand, .expand);</span>
<span class="line" id="L171"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">19</span>, child.width);</span>
<span class="line" id="L172"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">19</span>, child.height);</span>
<span class="line" id="L173">}</span>
<span class="line" id="L174"></span>
<span class="line" id="L175"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set too big&quot;</span> {</span>
<span class="line" id="L176"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L177"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L178"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L179"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L180"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L181"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L182"> };</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L185"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">20</span>, child.width);</span>
<span class="line" id="L186"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">20</span>, child.height);</span>
<span class="line" id="L187">}</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size set too big with offset&quot;</span> {</span>
<span class="line" id="L190"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L191"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L192"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L193"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L194"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L195"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L196"> };</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">10</span>, <span class="tok-number">10</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L199"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">10</span>, child.width);</span>
<span class="line" id="L200"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">10</span>, child.height);</span>
<span class="line" id="L201">}</span>
<span class="line" id="L202"></span>
<span class="line" id="L203"><span class="tok-kw">test</span> <span class="tok-str">&quot;Window size nested offsets&quot;</span> {</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> parent = Window{</span>
<span class="line" id="L205"> .x_off = <span class="tok-number">1</span>,</span>
<span class="line" id="L206"> .y_off = <span class="tok-number">1</span>,</span>
<span class="line" id="L207"> .width = <span class="tok-number">20</span>,</span>
<span class="line" id="L208"> .height = <span class="tok-number">20</span>,</span>
<span class="line" id="L209"> .screen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L210"> };</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">const</span> child = parent.initChild(<span class="tok-number">10</span>, <span class="tok-number">10</span>, .{ .limit = <span class="tok-number">21</span> }, .{ .limit = <span class="tok-number">21</span> });</span>
<span class="line" id="L213"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">11</span>, child.x_off);</span>
<span class="line" id="L214"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">11</span>, child.y_off);</span>
<span class="line" id="L215">}</span>
<span class="line" id="L216"></span>
</code></pre></body>
</html>

View file

@ -1,228 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ctlseqs.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Queries</span>
</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> primary_device_attrs = <span class="tok-str">&quot;\x1b[c&quot;</span>;</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> tertiary_device_attrs = <span class="tok-str">&quot;\x1b[=c&quot;</span>;</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> xtversion = <span class="tok-str">&quot;\x1b[&gt;0q&quot;</span>;</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_focus = <span class="tok-str">&quot;\x1b[?1004$p&quot;</span>;</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_sync = <span class="tok-str">&quot;\x1b[?2026$p&quot;</span>;</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_unicode = <span class="tok-str">&quot;\x1b[?2027$p&quot;</span>;</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> decrqm_color_theme = <span class="tok-str">&quot;\x1b[?2031$p&quot;</span>;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_query = <span class="tok-str">&quot;\x1b[?u&quot;</span>;</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_query = <span class="tok-str">&quot;\x1b_Gi=1,a=q\x1b\\&quot;</span>;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sixel_geometry_query = <span class="tok-str">&quot;\x1b[?2;1;0S&quot;</span>;</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-comment">// mouse</span>
</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mouse_set = <span class="tok-str">&quot;\x1b[?1003;1004;1006h&quot;</span>;</span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> mouse_reset = <span class="tok-str">&quot;\x1b[?1003;1004;1006l&quot;</span>;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-comment">// sync</span>
</span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sync_set = <span class="tok-str">&quot;\x1b[?2026h&quot;</span>;</span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sync_reset = <span class="tok-str">&quot;\x1b[?2026l&quot;</span>;</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-comment">// unicode</span>
</span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> unicode_set = <span class="tok-str">&quot;\x1b[?2027h&quot;</span>;</span>
<span class="line" id="L23"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> unicode_reset = <span class="tok-str">&quot;\x1b[?2027l&quot;</span>;</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-comment">// bracketed paste</span>
</span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bp_set = <span class="tok-str">&quot;\x1b[?2004h&quot;</span>;</span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bp_reset = <span class="tok-str">&quot;\x1b[?2004l&quot;</span>;</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"><span class="tok-comment">// Key encoding</span>
</span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_push = <span class="tok-str">&quot;\x1b[&gt;{d}u&quot;</span>;</span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> csi_u_pop = <span class="tok-str">&quot;\x1b[&lt;u&quot;</span>;</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"><span class="tok-comment">// Cursor</span>
</span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> home = <span class="tok-str">&quot;\x1b[H&quot;</span>;</span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> cup = <span class="tok-str">&quot;\x1b[{d};{d}H&quot;</span>;</span>
<span class="line" id="L36"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> hide_cursor = <span class="tok-str">&quot;\x1b[?25l&quot;</span>;</span>
<span class="line" id="L37"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> show_cursor = <span class="tok-str">&quot;\x1b[?25h&quot;</span>;</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-comment">// alt screen</span>
</span>
<span class="line" id="L40"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> smcup = <span class="tok-str">&quot;\x1b[?1049h&quot;</span>;</span>
<span class="line" id="L41"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> rmcup = <span class="tok-str">&quot;\x1b[?1049l&quot;</span>;</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"><span class="tok-comment">// sgr reset all</span>
</span>
<span class="line" id="L44"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> sgr_reset = <span class="tok-str">&quot;\x1b[m&quot;</span>;</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"><span class="tok-comment">// colors</span>
</span>
<span class="line" id="L47"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_base = <span class="tok-str">&quot;\x1b[3{d}m&quot;</span>;</span>
<span class="line" id="L48"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_bright = <span class="tok-str">&quot;\x1b[9{d}m&quot;</span>;</span>
<span class="line" id="L49"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_base = <span class="tok-str">&quot;\x1b[4{d}m&quot;</span>;</span>
<span class="line" id="L50"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_bright = <span class="tok-str">&quot;\x1b[10{d}m&quot;</span>;</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_reset = <span class="tok-str">&quot;\x1b[39m&quot;</span>;</span>
<span class="line" id="L53"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_reset = <span class="tok-str">&quot;\x1b[49m&quot;</span>;</span>
<span class="line" id="L54"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_reset = <span class="tok-str">&quot;\x1b[59m&quot;</span>;</span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_indexed = <span class="tok-str">&quot;\x1b[38:5:{d}m&quot;</span>;</span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_indexed = <span class="tok-str">&quot;\x1b[48:5:{d}m&quot;</span>;</span>
<span class="line" id="L57"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_indexed = <span class="tok-str">&quot;\x1b[58:5:{d}m&quot;</span>;</span>
<span class="line" id="L58"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> fg_rgb = <span class="tok-str">&quot;\x1b[38:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L59"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bg_rgb = <span class="tok-str">&quot;\x1b[48:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L60"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_rgb = <span class="tok-str">&quot;\x1b[58:2:{d}:{d}:{d}m&quot;</span>;</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"><span class="tok-comment">// Underlines</span>
</span>
<span class="line" id="L63"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_off = <span class="tok-str">&quot;\x1b[24m&quot;</span>; <span class="tok-comment">// NOTE: this could be \x1b[4:0m but is not as widely supported</span>
</span>
<span class="line" id="L64"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_single = <span class="tok-str">&quot;\x1b[4m&quot;</span>;</span>
<span class="line" id="L65"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_double = <span class="tok-str">&quot;\x1b[4:2m&quot;</span>;</span>
<span class="line" id="L66"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_curly = <span class="tok-str">&quot;\x1b[4:3m&quot;</span>;</span>
<span class="line" id="L67"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_dotted = <span class="tok-str">&quot;\x1b[4:4m&quot;</span>;</span>
<span class="line" id="L68"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ul_dashed = <span class="tok-str">&quot;\x1b[4:5m&quot;</span>;</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"><span class="tok-comment">// Attributes</span>
</span>
<span class="line" id="L71"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bold_set = <span class="tok-str">&quot;\x1b[1m&quot;</span>;</span>
<span class="line" id="L72"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> dim_set = <span class="tok-str">&quot;\x1b[2m&quot;</span>;</span>
<span class="line" id="L73"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> italic_set = <span class="tok-str">&quot;\x1b[3m&quot;</span>;</span>
<span class="line" id="L74"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> blink_set = <span class="tok-str">&quot;\x1b[5m&quot;</span>;</span>
<span class="line" id="L75"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> reverse_set = <span class="tok-str">&quot;\x1b[7m&quot;</span>;</span>
<span class="line" id="L76"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> invisible_set = <span class="tok-str">&quot;\x1b[8m&quot;</span>;</span>
<span class="line" id="L77"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strikethrough_set = <span class="tok-str">&quot;\x1b[9m&quot;</span>;</span>
<span class="line" id="L78"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bold_dim_reset = <span class="tok-str">&quot;\x1b[22m&quot;</span>;</span>
<span class="line" id="L79"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> italic_reset = <span class="tok-str">&quot;\x1b[23m&quot;</span>;</span>
<span class="line" id="L80"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> blink_reset = <span class="tok-str">&quot;\x1b[25m&quot;</span>;</span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> reverse_reset = <span class="tok-str">&quot;\x1b[27m&quot;</span>;</span>
<span class="line" id="L82"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> invisible_reset = <span class="tok-str">&quot;\x1b[28m&quot;</span>;</span>
<span class="line" id="L83"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> strikethrough_reset = <span class="tok-str">&quot;\x1b[29m&quot;</span>;</span>
<span class="line" id="L84"></span>
<span class="line" id="L85"><span class="tok-comment">// OSC sequences</span>
</span>
<span class="line" id="L86"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc2_set_title = <span class="tok-str">&quot;\x1b]2;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L87"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc8 = <span class="tok-str">&quot;\x1b]8;{s};{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L88"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc8_clear = <span class="tok-str">&quot;\x1b]8;;\x1b\\&quot;</span>;</span>
<span class="line" id="L89"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc9_notify = <span class="tok-str">&quot;\x1b]9;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L90"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc777_notify = <span class="tok-str">&quot;\x1b]777;notify;{s};{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L91"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> osc22_mouse_shape = <span class="tok-str">&quot;\x1b]22;{s}\x1b\\&quot;</span>;</span>
<span class="line" id="L92"></span>
<span class="line" id="L93"><span class="tok-comment">// Kitty graphics</span>
</span>
<span class="line" id="L94"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_clear = <span class="tok-str">&quot;\x1b_Ga=d\x1b\\&quot;</span>;</span>
<span class="line" id="L95"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_place = <span class="tok-str">&quot;\x1b_Ga=p,i={d},z={d},C=1\x1b\\&quot;</span>;</span>
<span class="line" id="L96"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> kitty_graphics_scale = <span class="tok-str">&quot;\x1b_Ga=p,i={d},z={d},c={d},r={d},C=1\x1b\\&quot;</span>;</span>
<span class="line" id="L97"></span>
</code></pre></body>
</html>

View file

@ -1,137 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>event.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Key.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">/// The events that Vaxis emits internally</span></span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L6"> key_press: Key,</span>
<span class="line" id="L7"> mouse: Mouse,</span>
<span class="line" id="L8"> focus_in,</span>
<span class="line" id="L9"> focus_out,</span>
<span class="line" id="L10"> paste_start,</span>
<span class="line" id="L11"> paste_end,</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"> <span class="tok-comment">// these are delivered as discovered terminal capabilities</span>
</span>
<span class="line" id="L14"> cap_kitty_keyboard,</span>
<span class="line" id="L15"> cap_kitty_graphics,</span>
<span class="line" id="L16"> cap_rgb,</span>
<span class="line" id="L17"> cap_unicode,</span>
<span class="line" id="L18"> cap_da1,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
</code></pre></body>
</html>

View file

@ -1,185 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>gwidth.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> unicode = std.unicode;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> testing = std.testing;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> ziglyph = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-comment">/// the method to use when calculating the width of a grapheme</span></span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Method = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L8"> unicode,</span>
<span class="line" id="L9"> wcwidth,</span>
<span class="line" id="L10"> no_zwj,</span>
<span class="line" id="L11">};</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-comment">/// returns the width of the provided string, as measured by the method chosen</span></span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">gwidth</span>(str: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, method: Method) !<span class="tok-type">usize</span> {</span>
<span class="line" id="L15"> <span class="tok-kw">switch</span> (method) {</span>
<span class="line" id="L16"> .unicode =&gt; {</span>
<span class="line" id="L17"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> ziglyph.display_width.strWidth(str, .half);</span>
<span class="line" id="L18"> },</span>
<span class="line" id="L19"> .wcwidth =&gt; {</span>
<span class="line" id="L20"> <span class="tok-kw">var</span> total: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L21"> <span class="tok-kw">const</span> utf8 = <span class="tok-kw">try</span> unicode.Utf8View.init(str);</span>
<span class="line" id="L22"> <span class="tok-kw">var</span> iter = utf8.iterator();</span>
<span class="line" id="L23"></span>
<span class="line" id="L24"> <span class="tok-kw">while</span> (iter.nextCodepoint()) |cp| {</span>
<span class="line" id="L25"> <span class="tok-kw">const</span> w = ziglyph.display_width.codePointWidth(cp, .half);</span>
<span class="line" id="L26"> <span class="tok-kw">if</span> (w &lt; <span class="tok-number">0</span>) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L27"> total += <span class="tok-builtin">@intCast</span>(w);</span>
<span class="line" id="L28"> }</span>
<span class="line" id="L29"> <span class="tok-kw">return</span> total;</span>
<span class="line" id="L30"> },</span>
<span class="line" id="L31"> .no_zwj =&gt; {</span>
<span class="line" id="L32"> <span class="tok-kw">var</span> out: [<span class="tok-number">256</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L33"> <span class="tok-kw">if</span> (str.len &gt; out.len) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.OutOfMemory;</span>
<span class="line" id="L34"> <span class="tok-kw">const</span> n = std.mem.replace(<span class="tok-type">u8</span>, str, <span class="tok-str">&quot;\u{200D}&quot;</span>, <span class="tok-str">&quot;&quot;</span>, &amp;out);</span>
<span class="line" id="L35"> <span class="tok-kw">return</span> gwidth(out[<span class="tok-number">0</span>..n], .unicode);</span>
<span class="line" id="L36"> },</span>
<span class="line" id="L37"> }</span>
<span class="line" id="L38">}</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: a&quot;</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .unicode));</span>
<span class="line" id="L42"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .wcwidth));</span>
<span class="line" id="L43"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;a&quot;</span>, .no_zwj));</span>
<span class="line" id="L44">}</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with ZWJ&quot;</span> {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .unicode));</span>
<span class="line" id="L48"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .wcwidth));</span>
<span class="line" id="L49"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👩‍🚀&quot;</span>, .no_zwj));</span>
<span class="line" id="L50">}</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with VS16 selector&quot;</span> {</span>
<span class="line" id="L53"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .unicode));</span>
<span class="line" id="L54"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">1</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .wcwidth));</span>
<span class="line" id="L55"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;\xE2\x9D\xA4\xEF\xB8\x8F&quot;</span>, .no_zwj));</span>
<span class="line" id="L56">}</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: emoji with skin tone selector&quot;</span> {</span>
<span class="line" id="L59"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .unicode));</span>
<span class="line" id="L60"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">4</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .wcwidth));</span>
<span class="line" id="L61"> <span class="tok-kw">try</span> testing.expectEqual(<span class="tok-number">2</span>, <span class="tok-kw">try</span> gwidth(<span class="tok-str">&quot;👋🏿&quot;</span>, .no_zwj));</span>
<span class="line" id="L62">}</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"><span class="tok-kw">test</span> <span class="tok-str">&quot;gwidth: invalid string&quot;</span> {</span>
<span class="line" id="L65"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .unicode));</span>
<span class="line" id="L66"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .wcwidth));</span>
<span class="line" id="L67"> <span class="tok-kw">try</span> testing.expectError(<span class="tok-kw">error</span>.InvalidUtf8, gwidth(<span class="tok-str">&quot;\xc3\x28&quot;</span>, .no_zwj));</span>
<span class="line" id="L68">}</span>
<span class="line" id="L69"></span>
</code></pre></body>
</html>

View file

@ -1,243 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>queue.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> assert = std.debug.assert;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> atomic = std.atomic;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Futex = std.Thread.Futex;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> log = std.log.scoped(.queue);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Thread safe. Fixed size. Blocking push and pop.</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Queue</span>(</span>
<span class="line" id="L10"> <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>,</span>
<span class="line" id="L11"> <span class="tok-kw">comptime</span> size: <span class="tok-type">usize</span>,</span>
<span class="line" id="L12">) <span class="tok-type">type</span> {</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L14"> buf: [size]T = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> read_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17"> write_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> mutex: std.Thread.Mutex = .{},</span>
<span class="line" id="L20"> <span class="tok-comment">/// blocks when the buffer is full or empty</span></span>
<span class="line" id="L21"> futex: atomic.Value(<span class="tok-type">u32</span>) = atomic.Value(<span class="tok-type">u32</span>).init(<span class="tok-number">0</span>),</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> <span class="tok-comment">/// pop an item from the queue. Blocks until an item is available</span></span>
<span class="line" id="L26"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pop</span>(self: *Self) T {</span>
<span class="line" id="L27"> self.mutex.lock();</span>
<span class="line" id="L28"> <span class="tok-kw">defer</span> self.mutex.unlock();</span>
<span class="line" id="L29"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L30"> <span class="tok-comment">// If we don't have any items, we unlock and wait</span>
</span>
<span class="line" id="L31"> self.mutex.unlock();</span>
<span class="line" id="L32"> Futex.wait(&amp;self.futex, <span class="tok-number">0</span>);</span>
<span class="line" id="L33"> <span class="tok-comment">// regain our lock</span>
</span>
<span class="line" id="L34"> self.mutex.lock();</span>
<span class="line" id="L35"> }</span>
<span class="line" id="L36"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L37"> <span class="tok-comment">// If we are full, wake up the push</span>
</span>
<span class="line" id="L38"> Futex.wake(&amp;self.futex, <span class="tok-number">1</span>);</span>
<span class="line" id="L39"> }</span>
<span class="line" id="L40"> <span class="tok-kw">const</span> i = self.read_index;</span>
<span class="line" id="L41"> self.read_index += <span class="tok-number">1</span>;</span>
<span class="line" id="L42"> self.read_index = self.read_index % self.buf.len;</span>
<span class="line" id="L43"> <span class="tok-kw">return</span> self.buf[i];</span>
<span class="line" id="L44"> }</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-comment">/// push an item into the queue. Blocks until the item has been put in</span></span>
<span class="line" id="L47"> <span class="tok-comment">/// the queue</span></span>
<span class="line" id="L48"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">push</span>(self: *Self, item: T) <span class="tok-type">void</span> {</span>
<span class="line" id="L49"> self.mutex.lock();</span>
<span class="line" id="L50"> <span class="tok-kw">defer</span> self.mutex.unlock();</span>
<span class="line" id="L51"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L52"> self.mutex.unlock();</span>
<span class="line" id="L53"> Futex.wait(&amp;self.futex, <span class="tok-number">0</span>);</span>
<span class="line" id="L54"> self.mutex.lock();</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L57"> Futex.wake(&amp;self.futex, <span class="tok-number">1</span>);</span>
<span class="line" id="L58"> }</span>
<span class="line" id="L59"> <span class="tok-kw">const</span> i = self.write_index;</span>
<span class="line" id="L60"> self.write_index += <span class="tok-number">1</span>;</span>
<span class="line" id="L61"> self.write_index = self.write_index % self.buf.len;</span>
<span class="line" id="L62"> self.buf[i] = item;</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> <span class="tok-comment">/// push an item into the queue. Returns true when the item was</span></span>
<span class="line" id="L66"> <span class="tok-comment">/// successfully placed in the queue</span></span>
<span class="line" id="L67"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">tryPush</span>(self: *Self, item: T) <span class="tok-type">bool</span> {</span>
<span class="line" id="L68"> self.mutex.lock();</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (self.isFull()) {</span>
<span class="line" id="L70"> self.mutex.unlock();</span>
<span class="line" id="L71"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"> self.mutex.unlock();</span>
<span class="line" id="L74"> self.push(item);</span>
<span class="line" id="L75"> <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L76"> }</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-comment">/// pop an item from the queue. Returns null when no item is available</span></span>
<span class="line" id="L79"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">tryPop</span>(self: *Self) ?T {</span>
<span class="line" id="L80"> self.mutex.lock();</span>
<span class="line" id="L81"> <span class="tok-kw">if</span> (self.isEmpty()) {</span>
<span class="line" id="L82"> self.mutex.unlock();</span>
<span class="line" id="L83"> <span class="tok-kw">return</span> <span class="tok-null">null</span>;</span>
<span class="line" id="L84"> }</span>
<span class="line" id="L85"> self.mutex.unlock();</span>
<span class="line" id="L86"> <span class="tok-kw">return</span> self.pop();</span>
<span class="line" id="L87"> }</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"> <span class="tok-comment">/// Returns `true` if the ring buffer is empty and `false` otherwise.</span></span>
<span class="line" id="L90"> <span class="tok-kw">fn</span> <span class="tok-fn">isEmpty</span>(self: Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L91"> <span class="tok-kw">return</span> self.write_index == self.read_index;</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-comment">/// Returns `true` if the ring buffer is full and `false` otherwise.</span></span>
<span class="line" id="L95"> <span class="tok-kw">fn</span> <span class="tok-fn">isFull</span>(self: Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> self.mask2(self.write_index + self.buf.len) == self.read_index;</span>
<span class="line" id="L97"> }</span>
<span class="line" id="L98"></span>
<span class="line" id="L99"> <span class="tok-comment">/// Returns the length</span></span>
<span class="line" id="L100"> <span class="tok-kw">fn</span> <span class="tok-fn">len</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L101"> <span class="tok-kw">const</span> wrap_offset = <span class="tok-number">2</span> * self.buf.len * <span class="tok-builtin">@intFromBool</span>(self.write_index &lt; self.read_index);</span>
<span class="line" id="L102"> <span class="tok-kw">const</span> adjusted_write_index = self.write_index + wrap_offset;</span>
<span class="line" id="L103"> <span class="tok-kw">return</span> adjusted_write_index - self.read_index;</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"> <span class="tok-comment">/// Returns `index` modulo the length of the backing slice.</span></span>
<span class="line" id="L107"> <span class="tok-kw">fn</span> <span class="tok-fn">mask</span>(self: Self, index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L108"> <span class="tok-kw">return</span> index % self.buf.len;</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-comment">/// Returns `index` modulo twice the length of the backing slice.</span></span>
<span class="line" id="L112"> <span class="tok-kw">fn</span> <span class="tok-fn">mask2</span>(self: Self, index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L113"> <span class="tok-kw">return</span> index % (<span class="tok-number">2</span> * self.buf.len);</span>
<span class="line" id="L114"> }</span>
<span class="line" id="L115"> };</span>
<span class="line" id="L116">}</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"><span class="tok-kw">test</span> <span class="tok-str">&quot;Queue: simple push / pop&quot;</span> {</span>
<span class="line" id="L119"> <span class="tok-kw">var</span> queue: Queue(<span class="tok-type">u8</span>, <span class="tok-number">16</span>) = .{};</span>
<span class="line" id="L120"> queue.push(<span class="tok-number">1</span>);</span>
<span class="line" id="L121"> <span class="tok-kw">const</span> pop = queue.pop();</span>
<span class="line" id="L122"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-number">1</span>, pop);</span>
<span class="line" id="L123">}</span>
<span class="line" id="L124"></span>
</code></pre></body>
</html>

View file

@ -1,861 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>vaxis.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> atomic = std.atomic;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> base64 = std.base64.standard.Encoder;</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Cell.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> InternalScreen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;InternalScreen.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Key.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Mouse = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Mouse.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Options = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Options.zig&quot;</span>);</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Queue = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;queue.zig&quot;</span>).Queue;</span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Screen = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Screen.zig&quot;</span>);</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Tty = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Tty.zig&quot;</span>);</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Window.zig&quot;</span>);</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ctlseqs = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ctlseqs.zig&quot;</span>);</span>
<span class="line" id="L17"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> gwidth = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;gwidth.zig&quot;</span>);</span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> widgets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets.zig&quot;</span>);</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-kw">const</span> zigimg = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;zigimg&quot;</span>);</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"></span>
<span class="line" id="L23"><span class="tok-comment">/// Initialize a Vaxis application.</span></span>
<span class="line" id="L24"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(<span class="tok-kw">comptime</span> Event: <span class="tok-type">type</span>, opts: Options) !Vaxis(Event) {</span>
<span class="line" id="L25"> <span class="tok-kw">return</span> Vaxis(Event).init(opts);</span>
<span class="line" id="L26">}</span>
<span class="line" id="L27"><span class="tok-kw">test</span> {</span>
<span class="line" id="L28"> std.testing.refAllDecls(<span class="tok-builtin">@This</span>());</span>
<span class="line" id="L29">}</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-comment">/// Vaxis is the entrypoint for a Vaxis application. The provided type T should</span></span>
<span class="line" id="L32"><span class="tok-comment">/// be a tagged union which contains all of the events the application will</span></span>
<span class="line" id="L33"><span class="tok-comment">/// handle. Vaxis will look for the following fields on the union and, if</span></span>
<span class="line" id="L34"><span class="tok-comment">/// found, emit them via the &quot;nextEvent&quot; method</span></span>
<span class="line" id="L35"><span class="tok-comment">///</span></span>
<span class="line" id="L36"><span class="tok-comment">/// The following events are available:</span></span>
<span class="line" id="L37"><span class="tok-comment">/// - `key_press: Key`, for key press events</span></span>
<span class="line" id="L38"><span class="tok-comment">/// - `winsize: Winsize`, for resize events. Must call app.resize when receiving</span></span>
<span class="line" id="L39"><span class="tok-comment">/// this event</span></span>
<span class="line" id="L40"><span class="tok-comment">/// - `focus_in` and `focus_out` for focus events</span></span>
<span class="line" id="L41"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Vaxis</span>(<span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L42"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L43"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> <span class="tok-kw">const</span> log = std.log.scoped(.vaxis);</span>
<span class="line" id="L46"></span>
<span class="line" id="L47"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Event = T;</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Capabilities = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L50"> kitty_keyboard: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L51"> kitty_graphics: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L52"> rgb: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L53"> unicode: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L54"> };</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"> <span class="tok-comment">/// the event queue for Vaxis</span></span>
<span class="line" id="L57"> <span class="tok-comment">//</span>
</span>
<span class="line" id="L58"> <span class="tok-comment">// TODO: is 512 ok?</span>
</span>
<span class="line" id="L59"> queue: Queue(T, <span class="tok-number">512</span>),</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> tty: ?Tty,</span>
<span class="line" id="L62"></span>
<span class="line" id="L63"> <span class="tok-comment">/// the screen we write to</span></span>
<span class="line" id="L64"> screen: Screen,</span>
<span class="line" id="L65"> <span class="tok-comment">/// The last screen we drew. We keep this so we can efficiently update on</span></span>
<span class="line" id="L66"> <span class="tok-comment">/// the next render</span></span>
<span class="line" id="L67"> screen_last: InternalScreen = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"> state: <span class="tok-kw">struct</span> {</span>
<span class="line" id="L70"> <span class="tok-comment">/// if we are in the alt screen</span></span>
<span class="line" id="L71"> alt_screen: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L72"> <span class="tok-comment">/// if we have entered kitty keyboard</span></span>
<span class="line" id="L73"> kitty_keyboard: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L74"> bracketed_paste: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L75"> mouse: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L76"> } = .{},</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> caps: Capabilities = .{},</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"> <span class="tok-comment">/// if we should redraw the entire screen on the next render</span></span>
<span class="line" id="L81"> refresh: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"> <span class="tok-comment">/// blocks the main thread until a DA1 query has been received, or the</span></span>
<span class="line" id="L84"> <span class="tok-comment">/// futex times out</span></span>
<span class="line" id="L85"> query_futex: atomic.Value(<span class="tok-type">u32</span>) = atomic.Value(<span class="tok-type">u32</span>).init(<span class="tok-number">0</span>),</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> <span class="tok-comment">// images</span>
</span>
<span class="line" id="L88"> next_img_id: <span class="tok-type">u32</span> = <span class="tok-number">1</span>,</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> <span class="tok-comment">// statistics</span>
</span>
<span class="line" id="L91"> renders: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L92"> render_dur: <span class="tok-type">i128</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-comment">/// Initialize Vaxis with runtime options</span></span>
<span class="line" id="L95"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(_: Options) !Self {</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L97"> .queue = .{},</span>
<span class="line" id="L98"> .tty = <span class="tok-null">null</span>,</span>
<span class="line" id="L99"> .screen = .{},</span>
<span class="line" id="L100"> .screen_last = .{},</span>
<span class="line" id="L101"> };</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"> <span class="tok-comment">/// Resets the terminal to it's original state. If an allocator is</span></span>
<span class="line" id="L105"> <span class="tok-comment">/// passed, this will free resources associated with Vaxis. This is left as an</span></span>
<span class="line" id="L106"> <span class="tok-comment">/// optional so applications can choose to not free resources when the</span></span>
<span class="line" id="L107"> <span class="tok-comment">/// application will be exiting anyways</span></span>
<span class="line" id="L108"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self, alloc: ?std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L109"> <span class="tok-kw">if</span> (self.tty) |_| {</span>
<span class="line" id="L110"> <span class="tok-kw">var</span> tty = &amp;self.tty.?;</span>
<span class="line" id="L111"> <span class="tok-kw">if</span> (self.state.kitty_keyboard) {</span>
<span class="line" id="L112"> _ = tty.write(ctlseqs.csi_u_pop) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114"> <span class="tok-kw">if</span> (self.state.mouse) {</span>
<span class="line" id="L115"> _ = tty.write(ctlseqs.mouse_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"> <span class="tok-kw">if</span> (self.state.bracketed_paste) {</span>
<span class="line" id="L118"> _ = tty.write(ctlseqs.bp_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (self.state.alt_screen) {</span>
<span class="line" id="L121"> _ = tty.write(ctlseqs.rmcup) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L122"> }</span>
<span class="line" id="L123"> tty.flush() <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L124"> tty.deinit();</span>
<span class="line" id="L125"> }</span>
<span class="line" id="L126"> <span class="tok-kw">if</span> (alloc) |a| {</span>
<span class="line" id="L127"> self.screen.deinit(a);</span>
<span class="line" id="L128"> self.screen_last.deinit(a);</span>
<span class="line" id="L129"> }</span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (self.renders &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L131"> <span class="tok-kw">const</span> tpr = <span class="tok-builtin">@divTrunc</span>(self.render_dur, self.renders);</span>
<span class="line" id="L132"> log.debug(<span class="tok-str">&quot;total renders = {d}&quot;</span>, .{self.renders});</span>
<span class="line" id="L133"> log.debug(<span class="tok-str">&quot;microseconds per render = {d}&quot;</span>, .{tpr});</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-comment">/// spawns the input thread to start listening to the tty for input</span></span>
<span class="line" id="L138"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">startReadThread</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L139"> self.tty = <span class="tok-kw">try</span> Tty.init();</span>
<span class="line" id="L140"> <span class="tok-comment">// run our tty read loop in it's own thread</span>
</span>
<span class="line" id="L141"> <span class="tok-kw">const</span> read_thread = <span class="tok-kw">try</span> std.Thread.spawn(.{}, Tty.run, .{ &amp;self.tty.?, T, self });</span>
<span class="line" id="L142"> <span class="tok-kw">try</span> read_thread.setName(<span class="tok-str">&quot;tty&quot;</span>);</span>
<span class="line" id="L143"> }</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"> <span class="tok-comment">/// stops reading from the tty</span></span>
<span class="line" id="L146"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">stopReadThread</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L147"> <span class="tok-kw">if</span> (self.tty) |_| {</span>
<span class="line" id="L148"> <span class="tok-kw">var</span> tty = &amp;self.tty.?;</span>
<span class="line" id="L149"> tty.stop();</span>
<span class="line" id="L150"> }</span>
<span class="line" id="L151"> }</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"> <span class="tok-comment">/// returns the next available event, blocking until one is available</span></span>
<span class="line" id="L154"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">nextEvent</span>(self: *Self) T {</span>
<span class="line" id="L155"> <span class="tok-kw">return</span> self.queue.pop();</span>
<span class="line" id="L156"> }</span>
<span class="line" id="L157"></span>
<span class="line" id="L158"> <span class="tok-comment">/// posts an event into the event queue. Will block if there is not</span></span>
<span class="line" id="L159"> <span class="tok-comment">/// capacity for the event</span></span>
<span class="line" id="L160"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">postEvent</span>(self: *Self, event: T) <span class="tok-type">void</span> {</span>
<span class="line" id="L161"> self.queue.push(event);</span>
<span class="line" id="L162"> }</span>
<span class="line" id="L163"></span>
<span class="line" id="L164"> <span class="tok-comment">/// resize allocates a slice of cells equal to the number of cells</span></span>
<span class="line" id="L165"> <span class="tok-comment">/// required to display the screen (ie width x height). Any previous screen is</span></span>
<span class="line" id="L166"> <span class="tok-comment">/// freed when resizing</span></span>
<span class="line" id="L167"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">resize</span>(self: *Self, alloc: std.mem.Allocator, winsize: Tty.Winsize) !<span class="tok-type">void</span> {</span>
<span class="line" id="L168"> log.debug(<span class="tok-str">&quot;resizing screen: width={d} height={d}&quot;</span>, .{ winsize.cols, winsize.rows });</span>
<span class="line" id="L169"> self.screen.deinit(alloc);</span>
<span class="line" id="L170"> self.screen = <span class="tok-kw">try</span> Screen.init(alloc, winsize);</span>
<span class="line" id="L171"> self.screen.unicode = self.caps.unicode;</span>
<span class="line" id="L172"> <span class="tok-comment">// try self.screen.int(alloc, winsize.cols, winsize.rows);</span>
</span>
<span class="line" id="L173"> <span class="tok-comment">// we only init our current screen. This has the effect of redrawing</span>
</span>
<span class="line" id="L174"> <span class="tok-comment">// every cell</span>
</span>
<span class="line" id="L175"> self.screen_last.deinit(alloc);</span>
<span class="line" id="L176"> self.screen_last = <span class="tok-kw">try</span> InternalScreen.init(alloc, winsize.cols, winsize.rows);</span>
<span class="line" id="L177"> <span class="tok-comment">// try self.screen_last.resize(alloc, winsize.cols, winsize.rows);</span>
</span>
<span class="line" id="L178"> }</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-comment">/// returns a Window comprising of the entire terminal screen</span></span>
<span class="line" id="L181"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">window</span>(self: *Self) Window {</span>
<span class="line" id="L182"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L183"> .x_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L184"> .y_off = <span class="tok-number">0</span>,</span>
<span class="line" id="L185"> .width = self.screen.width,</span>
<span class="line" id="L186"> .height = self.screen.height,</span>
<span class="line" id="L187"> .screen = &amp;self.screen,</span>
<span class="line" id="L188"> };</span>
<span class="line" id="L189"> }</span>
<span class="line" id="L190"></span>
<span class="line" id="L191"> <span class="tok-comment">/// enter the alternate screen. The alternate screen will automatically</span></span>
<span class="line" id="L192"> <span class="tok-comment">/// be exited if calling deinit while in the alt screen</span></span>
<span class="line" id="L193"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">enterAltScreen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L194"> <span class="tok-kw">if</span> (self.state.alt_screen) <span class="tok-kw">return</span>;</span>
<span class="line" id="L195"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L196"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.smcup);</span>
<span class="line" id="L197"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L198"> self.state.alt_screen = <span class="tok-null">true</span>;</span>
<span class="line" id="L199"> }</span>
<span class="line" id="L200"></span>
<span class="line" id="L201"> <span class="tok-comment">/// exit the alternate screen</span></span>
<span class="line" id="L202"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">exitAltScreen</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L203"> <span class="tok-kw">if</span> (!self.state.alt_screen) <span class="tok-kw">return</span>;</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L205"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.rmcup);</span>
<span class="line" id="L206"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L207"> self.state.alt_screen = <span class="tok-null">false</span>;</span>
<span class="line" id="L208"> }</span>
<span class="line" id="L209"></span>
<span class="line" id="L210"> <span class="tok-comment">/// write queries to the terminal to determine capabilities. Individual</span></span>
<span class="line" id="L211"> <span class="tok-comment">/// capabilities will be delivered to the client and possibly intercepted by</span></span>
<span class="line" id="L212"> <span class="tok-comment">/// Vaxis to enable features</span></span>
<span class="line" id="L213"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">queryTerminal</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L214"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"> <span class="tok-kw">const</span> colorterm = std.os.getenv(<span class="tok-str">&quot;COLORTERM&quot;</span>) <span class="tok-kw">orelse</span> <span class="tok-str">&quot;&quot;</span>;</span>
<span class="line" id="L217"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, colorterm, <span class="tok-str">&quot;truecolor&quot;</span>) <span class="tok-kw">or</span></span>
<span class="line" id="L218"> std.mem.eql(<span class="tok-type">u8</span>, colorterm, <span class="tok-str">&quot;24bit&quot;</span>))</span>
<span class="line" id="L219"> {</span>
<span class="line" id="L220"> <span class="tok-kw">if</span> (<span class="tok-builtin">@hasField</span>(Event, <span class="tok-str">&quot;cap_rgb&quot;</span>)) {</span>
<span class="line" id="L221"> self.postEvent(.cap_rgb);</span>
<span class="line" id="L222"> }</span>
<span class="line" id="L223"> }</span>
<span class="line" id="L224"></span>
<span class="line" id="L225"> <span class="tok-comment">// TODO: decide if we actually want to query for focus and sync. It</span>
</span>
<span class="line" id="L226"> <span class="tok-comment">// doesn't hurt to blindly use them</span>
</span>
<span class="line" id="L227"> <span class="tok-comment">// _ = try tty.write(ctlseqs.decrqm_focus);</span>
</span>
<span class="line" id="L228"> <span class="tok-comment">// _ = try tty.write(ctlseqs.decrqm_sync);</span>
</span>
<span class="line" id="L229"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.decrqm_unicode);</span>
<span class="line" id="L230"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.decrqm_color_theme);</span>
<span class="line" id="L231"> <span class="tok-comment">// TODO: XTVERSION has a DCS response. uncomment when we can parse</span>
</span>
<span class="line" id="L232"> <span class="tok-comment">// that</span>
</span>
<span class="line" id="L233"> <span class="tok-comment">// _ = try tty.write(ctlseqs.xtversion);</span>
</span>
<span class="line" id="L234"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.csi_u_query);</span>
<span class="line" id="L235"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.kitty_graphics_query);</span>
<span class="line" id="L236"> <span class="tok-comment">// TODO: sixel geometry query interferes with F4 keys.</span>
</span>
<span class="line" id="L237"> <span class="tok-comment">// _ = try tty.write(ctlseqs.sixel_geometry_query);</span>
</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"> <span class="tok-comment">// TODO: XTGETTCAP queries (&quot;RGB&quot;, &quot;Smulx&quot;)</span>
</span>
<span class="line" id="L240"></span>
<span class="line" id="L241"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.primary_device_attrs);</span>
<span class="line" id="L242"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L243"></span>
<span class="line" id="L244"> <span class="tok-comment">// 1 second timeout</span>
</span>
<span class="line" id="L245"> std.Thread.Futex.timedWait(&amp;self.query_futex, <span class="tok-number">0</span>, <span class="tok-number">1</span> * std.time.ns_per_s) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L246"></span>
<span class="line" id="L247"> <span class="tok-comment">// enable detected features</span>
</span>
<span class="line" id="L248"> <span class="tok-kw">if</span> (self.caps.kitty_keyboard) {</span>
<span class="line" id="L249"> <span class="tok-kw">try</span> self.enableKittyKeyboard(.{});</span>
<span class="line" id="L250"> }</span>
<span class="line" id="L251"> <span class="tok-kw">if</span> (self.caps.unicode) {</span>
<span class="line" id="L252"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.unicode_set);</span>
<span class="line" id="L253"> }</span>
<span class="line" id="L254"> }</span>
<span class="line" id="L255"></span>
<span class="line" id="L256"> <span class="tok-comment">// the next render call will refresh the entire screen</span>
</span>
<span class="line" id="L257"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">queueRefresh</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L258"> self.refresh = <span class="tok-null">true</span>;</span>
<span class="line" id="L259"> }</span>
<span class="line" id="L260"></span>
<span class="line" id="L261"> <span class="tok-comment">/// draws the screen to the terminal</span></span>
<span class="line" id="L262"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">render</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L263"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L264"> self.renders += <span class="tok-number">1</span>;</span>
<span class="line" id="L265"> <span class="tok-kw">const</span> timer_start = std.time.microTimestamp();</span>
<span class="line" id="L266"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L267"> self.render_dur += std.time.microTimestamp() - timer_start;</span>
<span class="line" id="L268"> }</span>
<span class="line" id="L269"></span>
<span class="line" id="L270"> <span class="tok-kw">defer</span> self.refresh = <span class="tok-null">false</span>;</span>
<span class="line" id="L271"> <span class="tok-kw">defer</span> tty.flush() <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L272"></span>
<span class="line" id="L273"> <span class="tok-comment">// Set up sync before we write anything</span>
</span>
<span class="line" id="L274"> <span class="tok-comment">// TODO: optimize sync so we only sync _when we have changes_. This</span>
</span>
<span class="line" id="L275"> <span class="tok-comment">// requires a smarter buffered writer, we'll probably have to write</span>
</span>
<span class="line" id="L276"> <span class="tok-comment">// our own</span>
</span>
<span class="line" id="L277"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.sync_set);</span>
<span class="line" id="L278"> <span class="tok-kw">defer</span> _ = tty.write(ctlseqs.sync_reset) <span class="tok-kw">catch</span> {};</span>
<span class="line" id="L279"></span>
<span class="line" id="L280"> <span class="tok-comment">// Send the cursor to 0,0</span>
</span>
<span class="line" id="L281"> <span class="tok-comment">// TODO: this needs to move after we optimize writes. We only do</span>
</span>
<span class="line" id="L282"> <span class="tok-comment">// this if we have an update to make. We also need to hide cursor</span>
</span>
<span class="line" id="L283"> <span class="tok-comment">// and then reshow it if needed</span>
</span>
<span class="line" id="L284"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.hide_cursor);</span>
<span class="line" id="L285"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.home);</span>
<span class="line" id="L286"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.sgr_reset);</span>
<span class="line" id="L287"></span>
<span class="line" id="L288"> <span class="tok-comment">// initialize some variables</span>
</span>
<span class="line" id="L289"> <span class="tok-kw">var</span> reposition: <span class="tok-type">bool</span> = <span class="tok-null">false</span>;</span>
<span class="line" id="L290"> <span class="tok-kw">var</span> row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L291"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L292"> <span class="tok-kw">var</span> cursor: Cell.Style = .{};</span>
<span class="line" id="L293"> <span class="tok-kw">var</span> link: Cell.Hyperlink = .{};</span>
<span class="line" id="L294"></span>
<span class="line" id="L295"> <span class="tok-comment">// Clear all images</span>
</span>
<span class="line" id="L296"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.kitty_graphics_clear);</span>
<span class="line" id="L297"></span>
<span class="line" id="L298"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L299"> <span class="tok-kw">while</span> (i &lt; self.screen.buf.len) {</span>
<span class="line" id="L300"> <span class="tok-kw">const</span> cell = self.screen.buf[i];</span>
<span class="line" id="L301"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L302"> <span class="tok-comment">// advance by the width of this char mod 1</span>
</span>
<span class="line" id="L303"> <span class="tok-kw">const</span> w = blk: {</span>
<span class="line" id="L304"> <span class="tok-kw">if</span> (cell.char.width != <span class="tok-number">0</span>) <span class="tok-kw">break</span> :blk cell.char.width;</span>
<span class="line" id="L305"></span>
<span class="line" id="L306"> <span class="tok-kw">const</span> method: gwidth.Method = <span class="tok-kw">if</span> (self.caps.unicode) .unicode <span class="tok-kw">else</span> .wcwidth;</span>
<span class="line" id="L307"> <span class="tok-kw">break</span> :blk gwidth.gwidth(cell.char.grapheme, method) <span class="tok-kw">catch</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L308"> };</span>
<span class="line" id="L309"> <span class="tok-kw">var</span> j = i + <span class="tok-number">1</span>;</span>
<span class="line" id="L310"> <span class="tok-kw">while</span> (j &lt; i + w) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L311"> self.screen_last.buf[j].skipped = <span class="tok-null">true</span>;</span>
<span class="line" id="L312"> }</span>
<span class="line" id="L313"> col += w;</span>
<span class="line" id="L314"> i += w;</span>
<span class="line" id="L315"> }</span>
<span class="line" id="L316"> <span class="tok-kw">if</span> (col &gt;= self.screen.width) {</span>
<span class="line" id="L317"> row += <span class="tok-number">1</span>;</span>
<span class="line" id="L318"> col = <span class="tok-number">0</span>;</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"> <span class="tok-comment">// If cell is the same as our last frame, we don't need to do</span>
</span>
<span class="line" id="L321"> <span class="tok-comment">// anything</span>
</span>
<span class="line" id="L322"> <span class="tok-kw">const</span> last = self.screen_last.buf[i];</span>
<span class="line" id="L323"> <span class="tok-kw">if</span> (!self.refresh <span class="tok-kw">and</span> last.eql(cell) <span class="tok-kw">and</span> !last.skipped <span class="tok-kw">and</span> cell.image == <span class="tok-null">null</span>) {</span>
<span class="line" id="L324"> reposition = <span class="tok-null">true</span>;</span>
<span class="line" id="L325"> <span class="tok-comment">// Close any osc8 sequence we might be in before</span>
</span>
<span class="line" id="L326"> <span class="tok-comment">// repositioning</span>
</span>
<span class="line" id="L327"> <span class="tok-kw">if</span> (link.uri.len &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L328"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.osc8_clear);</span>
<span class="line" id="L329"> }</span>
<span class="line" id="L330"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L331"> }</span>
<span class="line" id="L332"> self.screen_last.buf[i].skipped = <span class="tok-null">false</span>;</span>
<span class="line" id="L333"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L334"> cursor = cell.style;</span>
<span class="line" id="L335"> link = cell.link;</span>
<span class="line" id="L336"> }</span>
<span class="line" id="L337"> <span class="tok-comment">// Set this cell in the last frame</span>
</span>
<span class="line" id="L338"> self.screen_last.writeCell(col, row, cell);</span>
<span class="line" id="L339"></span>
<span class="line" id="L340"> <span class="tok-comment">// reposition the cursor, if needed</span>
</span>
<span class="line" id="L341"> <span class="tok-kw">if</span> (reposition) {</span>
<span class="line" id="L342"> <span class="tok-kw">try</span> std.fmt.format(tty.buffered_writer.writer(), ctlseqs.cup, .{ row + <span class="tok-number">1</span>, col + <span class="tok-number">1</span> });</span>
<span class="line" id="L343"> }</span>
<span class="line" id="L344"></span>
<span class="line" id="L345"> <span class="tok-kw">if</span> (cell.image) |img| {</span>
<span class="line" id="L346"> <span class="tok-kw">if</span> (img.size) |size| {</span>
<span class="line" id="L347"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L348"> tty.buffered_writer.writer(),</span>
<span class="line" id="L349"> ctlseqs.kitty_graphics_scale,</span>
<span class="line" id="L350"> .{ img.img_id, img.z_index, size.cols, size.rows },</span>
<span class="line" id="L351"> );</span>
<span class="line" id="L352"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L353"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L354"> tty.buffered_writer.writer(),</span>
<span class="line" id="L355"> ctlseqs.kitty_graphics_place,</span>
<span class="line" id="L356"> .{ img.img_id, img.z_index },</span>
<span class="line" id="L357"> );</span>
<span class="line" id="L358"> }</span>
<span class="line" id="L359"> }</span>
<span class="line" id="L360"></span>
<span class="line" id="L361"> <span class="tok-comment">// something is different, so let's loop through everything and</span>
</span>
<span class="line" id="L362"> <span class="tok-comment">// find out what</span>
</span>
<span class="line" id="L363"></span>
<span class="line" id="L364"> <span class="tok-comment">// foreground</span>
</span>
<span class="line" id="L365"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.fg, cell.style.fg)) {</span>
<span class="line" id="L366"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L367"> <span class="tok-kw">switch</span> (cell.style.fg) {</span>
<span class="line" id="L368"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.fg_reset),</span>
<span class="line" id="L369"> .index =&gt; |idx| {</span>
<span class="line" id="L370"> <span class="tok-kw">switch</span> (idx) {</span>
<span class="line" id="L371"> <span class="tok-number">0</span>...<span class="tok-number">7</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_base, .{idx}),</span>
<span class="line" id="L372"> <span class="tok-number">8</span>...<span class="tok-number">15</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_bright, .{idx - <span class="tok-number">8</span>}),</span>
<span class="line" id="L373"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_indexed, .{idx}),</span>
<span class="line" id="L374"> }</span>
<span class="line" id="L375"> },</span>
<span class="line" id="L376"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L377"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.fg_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L378"> },</span>
<span class="line" id="L379"> }</span>
<span class="line" id="L380"> }</span>
<span class="line" id="L381"> <span class="tok-comment">// background</span>
</span>
<span class="line" id="L382"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.bg, cell.style.bg)) {</span>
<span class="line" id="L383"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L384"> <span class="tok-kw">switch</span> (cell.style.bg) {</span>
<span class="line" id="L385"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.bg_reset),</span>
<span class="line" id="L386"> .index =&gt; |idx| {</span>
<span class="line" id="L387"> <span class="tok-kw">switch</span> (idx) {</span>
<span class="line" id="L388"> <span class="tok-number">0</span>...<span class="tok-number">7</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_base, .{idx}),</span>
<span class="line" id="L389"> <span class="tok-number">8</span>...<span class="tok-number">15</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_bright, .{idx - <span class="tok-number">8</span>}),</span>
<span class="line" id="L390"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_indexed, .{idx}),</span>
<span class="line" id="L391"> }</span>
<span class="line" id="L392"> },</span>
<span class="line" id="L393"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L394"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.bg_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L395"> },</span>
<span class="line" id="L396"> }</span>
<span class="line" id="L397"> }</span>
<span class="line" id="L398"> <span class="tok-comment">// underline color</span>
</span>
<span class="line" id="L399"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.ul, cell.style.ul)) {</span>
<span class="line" id="L400"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L401"> <span class="tok-kw">switch</span> (cell.style.bg) {</span>
<span class="line" id="L402"> .default =&gt; _ = <span class="tok-kw">try</span> tty.write(ctlseqs.ul_reset),</span>
<span class="line" id="L403"> .index =&gt; |idx| {</span>
<span class="line" id="L404"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.ul_indexed, .{idx});</span>
<span class="line" id="L405"> },</span>
<span class="line" id="L406"> .rgb =&gt; |rgb| {</span>
<span class="line" id="L407"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.ul_rgb, .{ rgb[<span class="tok-number">0</span>], rgb[<span class="tok-number">1</span>], rgb[<span class="tok-number">2</span>] });</span>
<span class="line" id="L408"> },</span>
<span class="line" id="L409"> }</span>
<span class="line" id="L410"> }</span>
<span class="line" id="L411"> <span class="tok-comment">// underline style</span>
</span>
<span class="line" id="L412"> <span class="tok-kw">if</span> (!std.meta.eql(cursor.ul_style, cell.style.ul_style)) {</span>
<span class="line" id="L413"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.ul_style) {</span>
<span class="line" id="L414"> .off =&gt; ctlseqs.ul_off,</span>
<span class="line" id="L415"> .single =&gt; ctlseqs.ul_single,</span>
<span class="line" id="L416"> .double =&gt; ctlseqs.ul_double,</span>
<span class="line" id="L417"> .curly =&gt; ctlseqs.ul_curly,</span>
<span class="line" id="L418"> .dotted =&gt; ctlseqs.ul_dotted,</span>
<span class="line" id="L419"> .dashed =&gt; ctlseqs.ul_dashed,</span>
<span class="line" id="L420"> };</span>
<span class="line" id="L421"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L422"> }</span>
<span class="line" id="L423"> <span class="tok-comment">// bold</span>
</span>
<span class="line" id="L424"> <span class="tok-kw">if</span> (cursor.bold != cell.style.bold) {</span>
<span class="line" id="L425"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.bold) {</span>
<span class="line" id="L426"> <span class="tok-null">true</span> =&gt; ctlseqs.bold_set,</span>
<span class="line" id="L427"> <span class="tok-null">false</span> =&gt; ctlseqs.bold_dim_reset,</span>
<span class="line" id="L428"> };</span>
<span class="line" id="L429"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L430"> <span class="tok-kw">if</span> (cell.style.dim) {</span>
<span class="line" id="L431"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.dim_set);</span>
<span class="line" id="L432"> }</span>
<span class="line" id="L433"> }</span>
<span class="line" id="L434"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L435"> <span class="tok-kw">if</span> (cursor.dim != cell.style.dim) {</span>
<span class="line" id="L436"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.dim) {</span>
<span class="line" id="L437"> <span class="tok-null">true</span> =&gt; ctlseqs.dim_set,</span>
<span class="line" id="L438"> <span class="tok-null">false</span> =&gt; ctlseqs.bold_dim_reset,</span>
<span class="line" id="L439"> };</span>
<span class="line" id="L440"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L441"> <span class="tok-kw">if</span> (cell.style.bold) {</span>
<span class="line" id="L442"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.bold_set);</span>
<span class="line" id="L443"> }</span>
<span class="line" id="L444"> }</span>
<span class="line" id="L445"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L446"> <span class="tok-kw">if</span> (cursor.italic != cell.style.italic) {</span>
<span class="line" id="L447"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.italic) {</span>
<span class="line" id="L448"> <span class="tok-null">true</span> =&gt; ctlseqs.italic_set,</span>
<span class="line" id="L449"> <span class="tok-null">false</span> =&gt; ctlseqs.italic_reset,</span>
<span class="line" id="L450"> };</span>
<span class="line" id="L451"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L452"> }</span>
<span class="line" id="L453"> <span class="tok-comment">// dim</span>
</span>
<span class="line" id="L454"> <span class="tok-kw">if</span> (cursor.blink != cell.style.blink) {</span>
<span class="line" id="L455"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.blink) {</span>
<span class="line" id="L456"> <span class="tok-null">true</span> =&gt; ctlseqs.blink_set,</span>
<span class="line" id="L457"> <span class="tok-null">false</span> =&gt; ctlseqs.blink_reset,</span>
<span class="line" id="L458"> };</span>
<span class="line" id="L459"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L460"> }</span>
<span class="line" id="L461"> <span class="tok-comment">// reverse</span>
</span>
<span class="line" id="L462"> <span class="tok-kw">if</span> (cursor.reverse != cell.style.reverse) {</span>
<span class="line" id="L463"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.reverse) {</span>
<span class="line" id="L464"> <span class="tok-null">true</span> =&gt; ctlseqs.reverse_set,</span>
<span class="line" id="L465"> <span class="tok-null">false</span> =&gt; ctlseqs.reverse_reset,</span>
<span class="line" id="L466"> };</span>
<span class="line" id="L467"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L468"> }</span>
<span class="line" id="L469"> <span class="tok-comment">// invisible</span>
</span>
<span class="line" id="L470"> <span class="tok-kw">if</span> (cursor.invisible != cell.style.invisible) {</span>
<span class="line" id="L471"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.invisible) {</span>
<span class="line" id="L472"> <span class="tok-null">true</span> =&gt; ctlseqs.invisible_set,</span>
<span class="line" id="L473"> <span class="tok-null">false</span> =&gt; ctlseqs.invisible_reset,</span>
<span class="line" id="L474"> };</span>
<span class="line" id="L475"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L476"> }</span>
<span class="line" id="L477"> <span class="tok-comment">// strikethrough</span>
</span>
<span class="line" id="L478"> <span class="tok-kw">if</span> (cursor.strikethrough != cell.style.strikethrough) {</span>
<span class="line" id="L479"> <span class="tok-kw">const</span> seq = <span class="tok-kw">switch</span> (cell.style.strikethrough) {</span>
<span class="line" id="L480"> <span class="tok-null">true</span> =&gt; ctlseqs.strikethrough_set,</span>
<span class="line" id="L481"> <span class="tok-null">false</span> =&gt; ctlseqs.strikethrough_reset,</span>
<span class="line" id="L482"> };</span>
<span class="line" id="L483"> _ = <span class="tok-kw">try</span> tty.write(seq);</span>
<span class="line" id="L484"> }</span>
<span class="line" id="L485"></span>
<span class="line" id="L486"> <span class="tok-comment">// url</span>
</span>
<span class="line" id="L487"> <span class="tok-kw">if</span> (!std.meta.eql(link.uri, cell.link.uri)) {</span>
<span class="line" id="L488"> <span class="tok-kw">var</span> ps = cell.link.params;</span>
<span class="line" id="L489"> <span class="tok-kw">if</span> (cell.link.uri.len == <span class="tok-number">0</span>) {</span>
<span class="line" id="L490"> <span class="tok-comment">// Empty out the params no matter what if we don't have</span>
</span>
<span class="line" id="L491"> <span class="tok-comment">// a url</span>
</span>
<span class="line" id="L492"> ps = <span class="tok-str">&quot;&quot;</span>;</span>
<span class="line" id="L493"> }</span>
<span class="line" id="L494"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L495"> <span class="tok-kw">try</span> std.fmt.format(writer, ctlseqs.osc8, .{ ps, cell.link.uri });</span>
<span class="line" id="L496"> }</span>
<span class="line" id="L497"> _ = <span class="tok-kw">try</span> tty.write(cell.char.grapheme);</span>
<span class="line" id="L498"> }</span>
<span class="line" id="L499"> <span class="tok-kw">if</span> (self.screen.cursor_vis) {</span>
<span class="line" id="L500"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L501"> tty.buffered_writer.writer(),</span>
<span class="line" id="L502"> ctlseqs.cup,</span>
<span class="line" id="L503"> .{</span>
<span class="line" id="L504"> self.screen.cursor_row + <span class="tok-number">1</span>,</span>
<span class="line" id="L505"> self.screen.cursor_col + <span class="tok-number">1</span>,</span>
<span class="line" id="L506"> },</span>
<span class="line" id="L507"> );</span>
<span class="line" id="L508"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.show_cursor);</span>
<span class="line" id="L509"> }</span>
<span class="line" id="L510"> <span class="tok-kw">if</span> (self.screen.mouse_shape != self.screen_last.mouse_shape) {</span>
<span class="line" id="L511"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L512"> tty.buffered_writer.writer(),</span>
<span class="line" id="L513"> ctlseqs.osc22_mouse_shape,</span>
<span class="line" id="L514"> .{<span class="tok-builtin">@tagName</span>(self.screen.mouse_shape)},</span>
<span class="line" id="L515"> );</span>
<span class="line" id="L516"> }</span>
<span class="line" id="L517"> }</span>
<span class="line" id="L518"></span>
<span class="line" id="L519"> <span class="tok-kw">fn</span> <span class="tok-fn">enableKittyKeyboard</span>(self: *Self, flags: Key.KittyFlags) !<span class="tok-type">void</span> {</span>
<span class="line" id="L520"> self.state.kitty_keyboard = <span class="tok-null">true</span>;</span>
<span class="line" id="L521"> <span class="tok-kw">const</span> flag_int: <span class="tok-type">u5</span> = <span class="tok-builtin">@bitCast</span>(flags);</span>
<span class="line" id="L522"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L523"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L524"> ctlseqs.csi_u_push,</span>
<span class="line" id="L525"> .{</span>
<span class="line" id="L526"> flag_int,</span>
<span class="line" id="L527"> },</span>
<span class="line" id="L528"> );</span>
<span class="line" id="L529"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L530"> }</span>
<span class="line" id="L531"></span>
<span class="line" id="L532"> <span class="tok-comment">/// send a system notification</span></span>
<span class="line" id="L533"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">notify</span>(self: *Self, title: ?[]<span class="tok-kw">const</span> <span class="tok-type">u8</span>, body: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L534"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L535"> <span class="tok-kw">if</span> (title) |t| {</span>
<span class="line" id="L536"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L537"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L538"> ctlseqs.osc777_notify,</span>
<span class="line" id="L539"> .{ t, body },</span>
<span class="line" id="L540"> );</span>
<span class="line" id="L541"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L542"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L543"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L544"> ctlseqs.osc9_notify,</span>
<span class="line" id="L545"> .{body},</span>
<span class="line" id="L546"> );</span>
<span class="line" id="L547"> }</span>
<span class="line" id="L548"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L549"> }</span>
<span class="line" id="L550"></span>
<span class="line" id="L551"> <span class="tok-comment">/// sets the window title</span></span>
<span class="line" id="L552"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setTitle</span>(self: *Self, title: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L553"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L554"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L555"> self.tty.?.buffered_writer.writer(),</span>
<span class="line" id="L556"> ctlseqs.osc2_set_title,</span>
<span class="line" id="L557"> .{title},</span>
<span class="line" id="L558"> );</span>
<span class="line" id="L559"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L560"> }</span>
<span class="line" id="L561"></span>
<span class="line" id="L562"> <span class="tok-comment">// turn bracketed paste on or off. An event will be sent at the</span>
</span>
<span class="line" id="L563"> <span class="tok-comment">// beginning and end of a detected paste. All keystrokes between these</span>
</span>
<span class="line" id="L564"> <span class="tok-comment">// events were pasted</span>
</span>
<span class="line" id="L565"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setBracketedPaste</span>(self: *Self, enable: <span class="tok-type">bool</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L566"> <span class="tok-kw">if</span> (self.tty == <span class="tok-null">null</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L567"> self.state.bracketed_paste = enable;</span>
<span class="line" id="L568"> <span class="tok-kw">const</span> seq = <span class="tok-kw">if</span> (enable) {</span>
<span class="line" id="L569"> self.state.bracketed_paste = <span class="tok-null">true</span>;</span>
<span class="line" id="L570"> ctlseqs.bp_set;</span>
<span class="line" id="L571"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L572"> self.state.bracketed_paste = <span class="tok-null">true</span>;</span>
<span class="line" id="L573"> ctlseqs.bp_reset;</span>
<span class="line" id="L574"> };</span>
<span class="line" id="L575"> _ = <span class="tok-kw">try</span> self.tty.?.write(seq);</span>
<span class="line" id="L576"> <span class="tok-kw">try</span> self.tty.?.flush();</span>
<span class="line" id="L577"> }</span>
<span class="line" id="L578"></span>
<span class="line" id="L579"> <span class="tok-comment">/// set the mouse shape</span></span>
<span class="line" id="L580"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setMouseShape</span>(self: *Self, shape: Mouse.Shape) <span class="tok-type">void</span> {</span>
<span class="line" id="L581"> self.screen.mouse_shape = shape;</span>
<span class="line" id="L582"> }</span>
<span class="line" id="L583"></span>
<span class="line" id="L584"> <span class="tok-comment">/// turn mouse reporting on or off</span></span>
<span class="line" id="L585"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setMouseMode</span>(self: *Self, enable: <span class="tok-type">bool</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L586"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L587"> self.state.mouse = enable;</span>
<span class="line" id="L588"> <span class="tok-kw">if</span> (enable) {</span>
<span class="line" id="L589"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.mouse_set);</span>
<span class="line" id="L590"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L591"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L592"> _ = <span class="tok-kw">try</span> tty.write(ctlseqs.mouse_reset);</span>
<span class="line" id="L593"> <span class="tok-kw">try</span> tty.flush();</span>
<span class="line" id="L594"> }</span>
<span class="line" id="L595"> }</span>
<span class="line" id="L596"></span>
<span class="line" id="L597"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">loadImage</span>(</span>
<span class="line" id="L598"> self: *Self,</span>
<span class="line" id="L599"> alloc: std.mem.Allocator,</span>
<span class="line" id="L600"> src: Image.Source,</span>
<span class="line" id="L601"> ) !Image {</span>
<span class="line" id="L602"> <span class="tok-kw">if</span> (!self.caps.kitty_graphics) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.NoGraphicsCapability;</span>
<span class="line" id="L603"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.NoTTY;</span>
<span class="line" id="L604"> <span class="tok-kw">defer</span> self.next_img_id += <span class="tok-number">1</span>;</span>
<span class="line" id="L605"></span>
<span class="line" id="L606"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L607"></span>
<span class="line" id="L608"> <span class="tok-kw">var</span> img = <span class="tok-kw">switch</span> (src) {</span>
<span class="line" id="L609"> .path =&gt; |path| <span class="tok-kw">try</span> zigimg.Image.fromFilePath(alloc, path),</span>
<span class="line" id="L610"> .mem =&gt; |bytes| <span class="tok-kw">try</span> zigimg.Image.fromMemory(alloc, bytes),</span>
<span class="line" id="L611"> };</span>
<span class="line" id="L612"> <span class="tok-kw">defer</span> img.deinit();</span>
<span class="line" id="L613"> <span class="tok-kw">const</span> png_buf = <span class="tok-kw">try</span> alloc.alloc(<span class="tok-type">u8</span>, img.imageByteSize());</span>
<span class="line" id="L614"> <span class="tok-kw">defer</span> alloc.free(png_buf);</span>
<span class="line" id="L615"> <span class="tok-kw">const</span> png = <span class="tok-kw">try</span> img.writeToMemory(png_buf, .{ .png = .{} });</span>
<span class="line" id="L616"> <span class="tok-kw">const</span> b64_buf = <span class="tok-kw">try</span> alloc.alloc(<span class="tok-type">u8</span>, base64.calcSize(png.len));</span>
<span class="line" id="L617"> <span class="tok-kw">const</span> encoded = base64.encode(b64_buf, png);</span>
<span class="line" id="L618"> <span class="tok-kw">defer</span> alloc.free(b64_buf);</span>
<span class="line" id="L619"></span>
<span class="line" id="L620"> <span class="tok-kw">const</span> id = self.next_img_id;</span>
<span class="line" id="L621"></span>
<span class="line" id="L622"> log.debug(<span class="tok-str">&quot;transmitting kitty image: id={d}, len={d}&quot;</span>, .{ id, encoded.len });</span>
<span class="line" id="L623"></span>
<span class="line" id="L624"> <span class="tok-kw">if</span> (encoded.len &lt; <span class="tok-number">4096</span>) {</span>
<span class="line" id="L625"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L626"> writer,</span>
<span class="line" id="L627"> <span class="tok-str">&quot;\x1b_Gf=100,i={d};{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L628"> .{</span>
<span class="line" id="L629"> id,</span>
<span class="line" id="L630"> encoded,</span>
<span class="line" id="L631"> },</span>
<span class="line" id="L632"> );</span>
<span class="line" id="L633"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L634"> <span class="tok-kw">var</span> n: <span class="tok-type">usize</span> = <span class="tok-number">4096</span>;</span>
<span class="line" id="L635"></span>
<span class="line" id="L636"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L637"> writer,</span>
<span class="line" id="L638"> <span class="tok-str">&quot;\x1b_Gf=100,i={d},m=1;{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L639"> .{ id, encoded[<span class="tok-number">0</span>..n] },</span>
<span class="line" id="L640"> );</span>
<span class="line" id="L641"> <span class="tok-kw">while</span> (n &lt; encoded.len) : (n += <span class="tok-number">4096</span>) {</span>
<span class="line" id="L642"> <span class="tok-kw">const</span> end: <span class="tok-type">usize</span> = <span class="tok-builtin">@min</span>(n + <span class="tok-number">4096</span>, encoded.len);</span>
<span class="line" id="L643"> <span class="tok-kw">const</span> m: <span class="tok-type">u2</span> = <span class="tok-kw">if</span> (end == encoded.len) <span class="tok-number">0</span> <span class="tok-kw">else</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L644"> <span class="tok-kw">try</span> std.fmt.format(</span>
<span class="line" id="L645"> writer,</span>
<span class="line" id="L646"> <span class="tok-str">&quot;\x1b_Gm={d};{s}\x1b\\&quot;</span>,</span>
<span class="line" id="L647"> .{</span>
<span class="line" id="L648"> m,</span>
<span class="line" id="L649"> encoded[n..end],</span>
<span class="line" id="L650"> },</span>
<span class="line" id="L651"> );</span>
<span class="line" id="L652"> }</span>
<span class="line" id="L653"> }</span>
<span class="line" id="L654"> <span class="tok-kw">try</span> tty.buffered_writer.flush();</span>
<span class="line" id="L655"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L656"> .id = id,</span>
<span class="line" id="L657"> .width = img.width,</span>
<span class="line" id="L658"> .height = img.height,</span>
<span class="line" id="L659"> };</span>
<span class="line" id="L660"> }</span>
<span class="line" id="L661"></span>
<span class="line" id="L662"> <span class="tok-comment">/// deletes an image from the terminal's memory</span></span>
<span class="line" id="L663"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">freeImage</span>(self: Self, id: <span class="tok-type">u32</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L664"> <span class="tok-kw">var</span> tty = self.tty <span class="tok-kw">orelse</span> <span class="tok-kw">return</span>;</span>
<span class="line" id="L665"> <span class="tok-kw">const</span> writer = tty.buffered_writer.writer();</span>
<span class="line" id="L666"> std.fmt.format(writer, <span class="tok-str">&quot;\x1b_Ga=d,d=I,i={d};\x1b\\&quot;</span>, .{id}) <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L667"> log.err(<span class="tok-str">&quot;couldn't delete image {d}: {}&quot;</span>, .{ id, err });</span>
<span class="line" id="L668"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L669"> };</span>
<span class="line" id="L670"> tty.buffered_writer.flush() <span class="tok-kw">catch</span> |err| {</span>
<span class="line" id="L671"> log.err(<span class="tok-str">&quot;couldn't flush writer: {}&quot;</span>, .{err});</span>
<span class="line" id="L672"> };</span>
<span class="line" id="L673"> }</span>
<span class="line" id="L674"> };</span>
<span class="line" id="L675">}</span>
<span class="line" id="L676"></span>
<span class="line" id="L677"><span class="tok-kw">test</span> <span class="tok-str">&quot;Vaxis: event queueing&quot;</span> {</span>
<span class="line" id="L678"> <span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L679"> key,</span>
<span class="line" id="L680"> };</span>
<span class="line" id="L681"> <span class="tok-kw">var</span> vx: Vaxis(Event) = <span class="tok-kw">try</span> Vaxis(Event).init(.{});</span>
<span class="line" id="L682"> <span class="tok-kw">defer</span> vx.deinit(<span class="tok-null">null</span>);</span>
<span class="line" id="L683"> vx.postEvent(.key);</span>
<span class="line" id="L684"> <span class="tok-kw">const</span> event = vx.nextEvent();</span>
<span class="line" id="L685"> <span class="tok-kw">try</span> std.testing.expect(event == .key);</span>
<span class="line" id="L686">}</span>
<span class="line" id="L687"></span>
</code></pre></body>
</html>

View file

@ -1,121 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> border = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/border.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> alignment = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/alignment.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TextInput = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/TextInput.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Table = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;widgets/Table.zig&quot;</span>);</span>
<span class="line" id="L5"></span>
</code></pre></body>
</html>

View file

@ -1,274 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/Table.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> fmt = std.fmt;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> heap = std.heap;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> mem = std.mem;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> meta = std.meta;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> vaxis = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../vaxis.zig&quot;</span>);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">/// Table Context for maintaining state and drawing Tables with `drawTable()`.</span></span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TableContext = <span class="tok-kw">struct</span>{</span>
<span class="line" id="L11"> <span class="tok-comment">/// Current selected Row of the Table.</span></span>
<span class="line" id="L12"> row: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L13"> <span class="tok-comment">/// Current selected Column of the Table.</span></span>
<span class="line" id="L14"> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L15"> <span class="tok-comment">/// Starting point within the Data List.</span></span>
<span class="line" id="L16"> start: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17"></span>
<span class="line" id="L18"> <span class="tok-comment">/// Active status of the Table.</span></span>
<span class="line" id="L19"> active: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"> <span class="tok-comment">/// The Background Color for Selected Rows and Column Headers.</span></span>
<span class="line" id="L22"> selected_bg: vaxis.Cell.Color,</span>
<span class="line" id="L23"> <span class="tok-comment">/// First Column Header Background Color</span></span>
<span class="line" id="L24"> hdr_bg_1: vaxis.Cell.Color = .{ .rgb = [_]<span class="tok-type">u8</span>{ <span class="tok-number">64</span>, <span class="tok-number">64</span>, <span class="tok-number">64</span> } },</span>
<span class="line" id="L25"> <span class="tok-comment">/// Second Column Header Background Color</span></span>
<span class="line" id="L26"> hdr_bg_2: vaxis.Cell.Color = .{ .rgb = [_]<span class="tok-type">u8</span>{ <span class="tok-number">8</span>, <span class="tok-number">8</span>, <span class="tok-number">24</span> } },</span>
<span class="line" id="L27"> <span class="tok-comment">/// First Row Background Color</span></span>
<span class="line" id="L28"> row_bg_1: vaxis.Cell.Color = .{ .rgb = [_]<span class="tok-type">u8</span>{ <span class="tok-number">32</span>, <span class="tok-number">32</span>, <span class="tok-number">32</span> } },</span>
<span class="line" id="L29"> <span class="tok-comment">/// Second Row Background Color</span></span>
<span class="line" id="L30"> row_bg_2: vaxis.Cell.Color = .{ .rgb = [_]<span class="tok-type">u8</span>{ <span class="tok-number">8</span>, <span class="tok-number">8</span>, <span class="tok-number">8</span> } },</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"> <span class="tok-comment">/// Y Offset for drawing to the parent Window.</span></span>
<span class="line" id="L33"> y_off: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L34">};</span>
<span class="line" id="L35"></span>
<span class="line" id="L36"><span class="tok-comment">/// Draw a Table for the TUI.</span></span>
<span class="line" id="L37"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">drawTable</span>(</span>
<span class="line" id="L38"> <span class="tok-comment">/// This should be an ArenaAllocator that can be deinitialized after each event call.</span></span>
<span class="line" id="L39"> <span class="tok-comment">/// The Allocator is only used if a row field is a non-String.</span></span>
<span class="line" id="L40"> <span class="tok-comment">/// If the Allocator is not provided, those fields will show &quot;[unsupported (TypeName)]&quot;.</span></span>
<span class="line" id="L41"> alloc: ?mem.Allocator,</span>
<span class="line" id="L42"> <span class="tok-comment">/// The parent Window to draw to.</span></span>
<span class="line" id="L43"> win: vaxis.Window,</span>
<span class="line" id="L44"> <span class="tok-comment">/// Headers for the Table</span></span>
<span class="line" id="L45"> headers: []<span class="tok-kw">const</span> []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L46"> <span class="tok-comment">/// This must be an ArrayList.</span></span>
<span class="line" id="L47"> data_list: <span class="tok-kw">anytype</span>,</span>
<span class="line" id="L48"> <span class="tok-comment">// The Table Context for this Table.</span>
</span>
<span class="line" id="L49"> table_ctx: *TableContext,</span>
<span class="line" id="L50">) !<span class="tok-type">void</span> {</span>
<span class="line" id="L51"> <span class="tok-kw">const</span> table_win = win.initChild(</span>
<span class="line" id="L52"> <span class="tok-number">0</span>,</span>
<span class="line" id="L53"> table_ctx.y_off,</span>
<span class="line" id="L54"> .{ .limit = win.width },</span>
<span class="line" id="L55"> .{ .limit = win.height },</span>
<span class="line" id="L56"> );</span>
<span class="line" id="L57"> </span>
<span class="line" id="L58"> <span class="tok-kw">var</span> item_width = table_win.width / headers.len;</span>
<span class="line" id="L59"> <span class="tok-kw">if</span> (item_width % <span class="tok-number">2</span> != <span class="tok-number">0</span>) item_width += <span class="tok-number">1</span>;</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> <span class="tok-kw">if</span> (table_ctx.col &gt; headers.len - <span class="tok-number">1</span>) table_ctx.*.col = headers.len - <span class="tok-number">1</span>;</span>
<span class="line" id="L62"> <span class="tok-kw">for</span> (headers[<span class="tok-number">0</span>..], <span class="tok-number">0</span>..) |hdr_txt, idx| {</span>
<span class="line" id="L63"> <span class="tok-kw">const</span> hdr_bg =</span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (table_ctx.active <span class="tok-kw">and</span> idx == table_ctx.col) table_ctx.selected_bg</span>
<span class="line" id="L65"> <span class="tok-kw">else</span> <span class="tok-kw">if</span> (idx % <span class="tok-number">2</span> == <span class="tok-number">0</span>) table_ctx.hdr_bg_1</span>
<span class="line" id="L66"> <span class="tok-kw">else</span> table_ctx.hdr_bg_2;</span>
<span class="line" id="L67"> <span class="tok-kw">const</span> hdr_win = table_win.initChild(</span>
<span class="line" id="L68"> idx * item_width,</span>
<span class="line" id="L69"> <span class="tok-number">0</span>,</span>
<span class="line" id="L70"> .{ .limit = item_width },</span>
<span class="line" id="L71"> .{ .limit = <span class="tok-number">1</span> },</span>
<span class="line" id="L72"> );</span>
<span class="line" id="L73"> <span class="tok-kw">var</span> hdr = vaxis.widgets.alignment.center(hdr_win, <span class="tok-builtin">@min</span>(item_width - <span class="tok-number">1</span>, hdr_txt.len), <span class="tok-number">1</span>);</span>
<span class="line" id="L74"> hdr_win.fill(.{ .style = .{ .bg = hdr_bg } });</span>
<span class="line" id="L75"> <span class="tok-kw">var</span> seg = [_]vaxis.Cell.Segment{ .{</span>
<span class="line" id="L76"> .text = hdr_txt,</span>
<span class="line" id="L77"> .style = .{</span>
<span class="line" id="L78"> .bg = hdr_bg,</span>
<span class="line" id="L79"> .bold = <span class="tok-null">true</span>,</span>
<span class="line" id="L80"> .ul_style = <span class="tok-kw">if</span> (idx == table_ctx.col) .single <span class="tok-kw">else</span> .dotted,</span>
<span class="line" id="L81"> },</span>
<span class="line" id="L82"> } };</span>
<span class="line" id="L83"> <span class="tok-kw">try</span> hdr.wrap(seg[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L84"> }</span>
<span class="line" id="L85"></span>
<span class="line" id="L86"> <span class="tok-kw">const</span> max_items = <span class="tok-kw">if</span> (data_list.items.len &gt; table_win.height - <span class="tok-number">1</span>) table_win.height - <span class="tok-number">1</span> <span class="tok-kw">else</span> data_list.items.len;</span>
<span class="line" id="L87"> <span class="tok-kw">var</span> end = table_ctx.*.start + max_items;</span>
<span class="line" id="L88"> <span class="tok-kw">if</span> (end &gt; data_list.items.len) end = data_list.items.len;</span>
<span class="line" id="L89"> table_ctx.*.start = tableStart: {</span>
<span class="line" id="L90"> <span class="tok-kw">if</span> (table_ctx.row == <span class="tok-number">0</span>) </span>
<span class="line" id="L91"> <span class="tok-kw">break</span> :tableStart <span class="tok-number">0</span>;</span>
<span class="line" id="L92"> <span class="tok-kw">if</span> (table_ctx.row &lt; table_ctx.start) </span>
<span class="line" id="L93"> <span class="tok-kw">break</span> :tableStart table_ctx.start - (table_ctx.start - table_ctx.row);</span>
<span class="line" id="L94"> <span class="tok-kw">if</span> (table_ctx.row &gt;= data_list.items.len - <span class="tok-number">1</span>) </span>
<span class="line" id="L95"> table_ctx.*.row = data_list.items.len - <span class="tok-number">1</span>;</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (table_ctx.row &gt;= end) </span>
<span class="line" id="L97"> <span class="tok-kw">break</span> :tableStart table_ctx.start + (table_ctx.row - end + <span class="tok-number">1</span>);</span>
<span class="line" id="L98"> <span class="tok-kw">break</span> :tableStart table_ctx.start;</span>
<span class="line" id="L99"> };</span>
<span class="line" id="L100"> end = table_ctx.*.start + max_items;</span>
<span class="line" id="L101"> <span class="tok-kw">if</span> (end &gt; data_list.items.len) end = data_list.items.len;</span>
<span class="line" id="L102"> <span class="tok-kw">for</span> (data_list.items[table_ctx.start..end], <span class="tok-number">0</span>..) |data, idx| {</span>
<span class="line" id="L103"> <span class="tok-kw">const</span> row_bg =</span>
<span class="line" id="L104"> <span class="tok-kw">if</span> (table_ctx.active <span class="tok-kw">and</span> table_ctx.start + idx == table_ctx.row) table_ctx.selected_bg</span>
<span class="line" id="L105"> <span class="tok-kw">else</span> <span class="tok-kw">if</span> (idx % <span class="tok-number">2</span> == <span class="tok-number">0</span>) table_ctx.row_bg_1</span>
<span class="line" id="L106"> <span class="tok-kw">else</span> table_ctx.row_bg_2;</span>
<span class="line" id="L107"></span>
<span class="line" id="L108"> <span class="tok-kw">const</span> row_win = table_win.initChild(</span>
<span class="line" id="L109"> <span class="tok-number">0</span>,</span>
<span class="line" id="L110"> <span class="tok-number">1</span> + idx,</span>
<span class="line" id="L111"> .{ .limit = table_win.width },</span>
<span class="line" id="L112"> .{ .limit = <span class="tok-number">1</span> },</span>
<span class="line" id="L113"> );</span>
<span class="line" id="L114"> <span class="tok-kw">const</span> DataT = <span class="tok-builtin">@TypeOf</span>(data);</span>
<span class="line" id="L115"> <span class="tok-kw">const</span> item_fields = meta.fields(DataT);</span>
<span class="line" id="L116"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (item_fields[<span class="tok-number">0</span>..], <span class="tok-number">0</span>..) |item_field, item_idx| {</span>
<span class="line" id="L117"> <span class="tok-kw">const</span> item = <span class="tok-builtin">@field</span>(data, item_field.name);</span>
<span class="line" id="L118"> <span class="tok-kw">const</span> ItemT = <span class="tok-builtin">@TypeOf</span>(item);</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> item_win = row_win.initChild(</span>
<span class="line" id="L120"> item_idx * item_width,</span>
<span class="line" id="L121"> <span class="tok-number">0</span>,</span>
<span class="line" id="L122"> .{ .limit = item_width },</span>
<span class="line" id="L123"> .{ .limit = <span class="tok-number">1</span> },</span>
<span class="line" id="L124"> );</span>
<span class="line" id="L125"> item_win.fill(.{ .style = .{ .bg = row_bg } });</span>
<span class="line" id="L126"> <span class="tok-kw">var</span> seg = [_]vaxis.Cell.Segment{ .{</span>
<span class="line" id="L127"> .text = <span class="tok-kw">switch</span>(ItemT) {</span>
<span class="line" id="L128"> []<span class="tok-kw">const</span> <span class="tok-type">u8</span> =&gt; item,</span>
<span class="line" id="L129"> <span class="tok-kw">else</span> =&gt; nonStr: {</span>
<span class="line" id="L130"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(ItemT)) {</span>
<span class="line" id="L131"> .Optional =&gt; {</span>
<span class="line" id="L132"> <span class="tok-kw">const</span> opt_item = item <span class="tok-kw">orelse</span> <span class="tok-kw">break</span> :nonStr <span class="tok-str">&quot;-&quot;</span>;</span>
<span class="line" id="L133"> <span class="tok-kw">switch</span>(<span class="tok-builtin">@typeInfo</span>(ItemT).Optional.child) {</span>
<span class="line" id="L134"> []<span class="tok-kw">const</span> <span class="tok-type">u8</span> =&gt; <span class="tok-kw">break</span> :nonStr opt_item,</span>
<span class="line" id="L135"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L136"> <span class="tok-kw">break</span> :nonStr</span>
<span class="line" id="L137"> <span class="tok-kw">if</span> (alloc) |_alloc| <span class="tok-kw">try</span> fmt.allocPrint(_alloc, <span class="tok-str">&quot;{any}&quot;</span>, .{ opt_item })</span>
<span class="line" id="L138"> <span class="tok-kw">else</span> fmt.comptimePrint(<span class="tok-str">&quot;[unsupported ({s})]&quot;</span>, .{ <span class="tok-builtin">@typeName</span>(DataT) });</span>
<span class="line" id="L139"> }</span>
<span class="line" id="L140"> }</span>
<span class="line" id="L141"> },</span>
<span class="line" id="L142"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L143"> <span class="tok-kw">break</span> :nonStr</span>
<span class="line" id="L144"> <span class="tok-kw">if</span> (alloc) |_alloc| <span class="tok-kw">try</span> fmt.allocPrint(_alloc, <span class="tok-str">&quot;{any}&quot;</span>, .{ item })</span>
<span class="line" id="L145"> <span class="tok-kw">else</span> fmt.comptimePrint(<span class="tok-str">&quot;[unsupported ({s})]&quot;</span>, .{ <span class="tok-builtin">@typeName</span>(DataT) });</span>
<span class="line" id="L146"> }</span>
<span class="line" id="L147"> }</span>
<span class="line" id="L148"> },</span>
<span class="line" id="L149"> },</span>
<span class="line" id="L150"> .style = .{ .bg = row_bg },</span>
<span class="line" id="L151"> } };</span>
<span class="line" id="L152"> <span class="tok-kw">try</span> item_win.wrap(seg[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L153"> }</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155">}</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"></span>
</code></pre></body>
</html>

View file

@ -1,260 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/TextInput.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Key = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Key.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Cell.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> GraphemeIterator = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;ziglyph&quot;</span>).GraphemeIterator;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> log = std.log.scoped(.text_input);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> TextInput = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-comment">/// The events that this widget handles</span></span>
<span class="line" id="L12"><span class="tok-kw">const</span> Event = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L13"> key_press: Key,</span>
<span class="line" id="L14">};</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-comment">// Index of our cursor</span>
</span>
<span class="line" id="L17">cursor_idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18">grapheme_count: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">// TODO: an ArrayList is not great for this. orderedRemove is O(n) and we can</span>
</span>
<span class="line" id="L21"><span class="tok-comment">// only remove one byte at a time. Make a bespoke ArrayList which allows removal</span>
</span>
<span class="line" id="L22"><span class="tok-comment">// of a slice at a time, or truncating even would be nice</span>
</span>
<span class="line" id="L23">buf: std.ArrayList(<span class="tok-type">u8</span>),</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(alloc: std.mem.Allocator) TextInput {</span>
<span class="line" id="L26"> <span class="tok-kw">return</span> TextInput{</span>
<span class="line" id="L27"> .buf = std.ArrayList(<span class="tok-type">u8</span>).init(alloc),</span>
<span class="line" id="L28"> };</span>
<span class="line" id="L29">}</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L32"> self.buf.deinit();</span>
<span class="line" id="L33">}</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">update</span>(self: *TextInput, event: Event) !<span class="tok-type">void</span> {</span>
<span class="line" id="L36"> <span class="tok-kw">switch</span> (event) {</span>
<span class="line" id="L37"> .key_press =&gt; |key| {</span>
<span class="line" id="L38"> <span class="tok-kw">if</span> (key.matches(Key.backspace, .{})) {</span>
<span class="line" id="L39"> <span class="tok-kw">if</span> (self.cursor_idx == <span class="tok-number">0</span>) <span class="tok-kw">return</span>;</span>
<span class="line" id="L40"> self.deleteBeforeCursor();</span>
<span class="line" id="L41"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.delete, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'d'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L42"> <span class="tok-kw">if</span> (self.cursor_idx == self.grapheme_count) <span class="tok-kw">return</span>;</span>
<span class="line" id="L43"> self.deleteAtCursor();</span>
<span class="line" id="L44"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.left, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'b'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L45"> <span class="tok-kw">if</span> (self.cursor_idx &gt; <span class="tok-number">0</span>) self.cursor_idx -= <span class="tok-number">1</span>;</span>
<span class="line" id="L46"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(Key.right, .{}) <span class="tok-kw">or</span> key.matches(<span class="tok-str">'f'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L47"> <span class="tok-kw">if</span> (self.cursor_idx &lt; self.grapheme_count) self.cursor_idx += <span class="tok-number">1</span>;</span>
<span class="line" id="L48"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'a'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L49"> self.cursor_idx = <span class="tok-number">0</span>;</span>
<span class="line" id="L50"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'e'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L51"> self.cursor_idx = self.grapheme_count;</span>
<span class="line" id="L52"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'k'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L53"> <span class="tok-kw">while</span> (self.cursor_idx &lt; self.grapheme_count) {</span>
<span class="line" id="L54"> self.deleteAtCursor();</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.matches(<span class="tok-str">'u'</span>, .{ .ctrl = <span class="tok-null">true</span> })) {</span>
<span class="line" id="L57"> <span class="tok-kw">while</span> (self.cursor_idx &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L58"> self.deleteBeforeCursor();</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (key.text) |text| {</span>
<span class="line" id="L61"> <span class="tok-kw">try</span> self.buf.insertSlice(self.byteOffsetToCursor(), text);</span>
<span class="line" id="L62"> self.cursor_idx += <span class="tok-number">1</span>;</span>
<span class="line" id="L63"> self.grapheme_count += <span class="tok-number">1</span>;</span>
<span class="line" id="L64"> }</span>
<span class="line" id="L65"> },</span>
<span class="line" id="L66"> }</span>
<span class="line" id="L67">}</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">draw</span>(self: *TextInput, win: Window) <span class="tok-type">void</span> {</span>
<span class="line" id="L70"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L71"> <span class="tok-kw">var</span> col: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L72"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L73"> <span class="tok-kw">var</span> cursor_idx: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L74"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L75"> <span class="tok-kw">const</span> g = grapheme.slice(self.buf.items);</span>
<span class="line" id="L76"> <span class="tok-kw">const</span> w = win.gwidth(g);</span>
<span class="line" id="L77"> win.writeCell(col, <span class="tok-number">0</span>, .{</span>
<span class="line" id="L78"> .char = .{</span>
<span class="line" id="L79"> .grapheme = g,</span>
<span class="line" id="L80"> .width = w,</span>
<span class="line" id="L81"> },</span>
<span class="line" id="L82"> });</span>
<span class="line" id="L83"> col += w;</span>
<span class="line" id="L84"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L85"> <span class="tok-kw">if</span> (i == self.cursor_idx) cursor_idx = col;</span>
<span class="line" id="L86"> }</span>
<span class="line" id="L87"> win.showCursor(cursor_idx, <span class="tok-number">0</span>);</span>
<span class="line" id="L88">}</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"><span class="tok-comment">// returns the number of bytes before the cursor</span>
</span>
<span class="line" id="L91"><span class="tok-kw">fn</span> <span class="tok-fn">byteOffsetToCursor</span>(self: TextInput) <span class="tok-type">usize</span> {</span>
<span class="line" id="L92"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L93"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L94"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L95"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (i == self.cursor_idx) <span class="tok-kw">break</span>;</span>
<span class="line" id="L97"> offset += grapheme.len;</span>
<span class="line" id="L98"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> <span class="tok-kw">return</span> offset;</span>
<span class="line" id="L101">}</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"><span class="tok-kw">fn</span> <span class="tok-fn">deleteBeforeCursor</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L105"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L106"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L107"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L108"> <span class="tok-kw">if</span> (i == self.cursor_idx) {</span>
<span class="line" id="L109"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L110"> <span class="tok-kw">while</span> (j &lt; grapheme.len) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L111"> _ = self.buf.orderedRemove(offset);</span>
<span class="line" id="L112"> }</span>
<span class="line" id="L113"> self.cursor_idx -= <span class="tok-number">1</span>;</span>
<span class="line" id="L114"> self.grapheme_count -= <span class="tok-number">1</span>;</span>
<span class="line" id="L115"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"> offset += grapheme.len;</span>
<span class="line" id="L118"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120">}</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"><span class="tok-kw">fn</span> <span class="tok-fn">deleteAtCursor</span>(self: *TextInput) <span class="tok-type">void</span> {</span>
<span class="line" id="L123"> <span class="tok-kw">var</span> iter = GraphemeIterator.init(self.buf.items);</span>
<span class="line" id="L124"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L125"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L126"> <span class="tok-kw">while</span> (iter.next()) |grapheme| {</span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (i == self.cursor_idx + <span class="tok-number">1</span>) {</span>
<span class="line" id="L128"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L129"> <span class="tok-kw">while</span> (j &lt; grapheme.len) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L130"> _ = self.buf.orderedRemove(offset);</span>
<span class="line" id="L131"> }</span>
<span class="line" id="L132"> self.grapheme_count -= <span class="tok-number">1</span>;</span>
<span class="line" id="L133"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> offset += grapheme.len;</span>
<span class="line" id="L136"> i += <span class="tok-number">1</span>;</span>
<span class="line" id="L137"> }</span>
<span class="line" id="L138">}</span>
<span class="line" id="L139"></span>
</code></pre></body>
</html>

View file

@ -1,124 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/alignment.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">center</span>(parent: Window, cols: <span class="tok-type">usize</span>, rows: <span class="tok-type">usize</span>) Window {</span>
<span class="line" id="L4"> <span class="tok-kw">const</span> y_off = (parent.height / <span class="tok-number">2</span>) - (rows / <span class="tok-number">2</span>);</span>
<span class="line" id="L5"> <span class="tok-kw">const</span> x_off = (parent.width / <span class="tok-number">2</span>) - (cols / <span class="tok-number">2</span>);</span>
<span class="line" id="L6"> <span class="tok-kw">return</span> parent.initChild(x_off, y_off, .{ .limit = cols }, .{ .limit = rows });</span>
<span class="line" id="L7">}</span>
<span class="line" id="L8"></span>
</code></pre></body>
</html>

View file

@ -1,149 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>widgets/border.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Cell = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Cell.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Window = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Window.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Style = Cell.Style;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Character = Cell.Character;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> horizontal = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L8"><span class="tok-kw">const</span> vertical = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L9"><span class="tok-kw">const</span> top_left = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L10"><span class="tok-kw">const</span> top_right = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L11"><span class="tok-kw">const</span> bottom_right = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L12"><span class="tok-kw">const</span> bottom_left = Character{ .grapheme = <span class="tok-str">&quot;&quot;</span>, .width = <span class="tok-number">1</span> };</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">all</span>(win: Window, style: Style) Window {</span>
<span class="line" id="L15"> <span class="tok-kw">const</span> h = win.height;</span>
<span class="line" id="L16"> <span class="tok-kw">const</span> w = win.width;</span>
<span class="line" id="L17"> win.writeCell(<span class="tok-number">0</span>, <span class="tok-number">0</span>, .{ .char = top_left, .style = style });</span>
<span class="line" id="L18"> win.writeCell(<span class="tok-number">0</span>, h - <span class="tok-number">1</span>, .{ .char = bottom_left, .style = style });</span>
<span class="line" id="L19"> win.writeCell(w - <span class="tok-number">1</span>, <span class="tok-number">0</span>, .{ .char = top_right, .style = style });</span>
<span class="line" id="L20"> win.writeCell(w - <span class="tok-number">1</span>, h - <span class="tok-number">1</span>, .{ .char = bottom_right, .style = style });</span>
<span class="line" id="L21"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L22"> <span class="tok-kw">while</span> (i &lt; (h - <span class="tok-number">1</span>)) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L23"> win.writeCell(<span class="tok-number">0</span>, i, .{ .char = vertical, .style = style });</span>
<span class="line" id="L24"> win.writeCell(w - <span class="tok-number">1</span>, i, .{ .char = vertical, .style = style });</span>
<span class="line" id="L25"> }</span>
<span class="line" id="L26"> i = <span class="tok-number">1</span>;</span>
<span class="line" id="L27"> <span class="tok-kw">while</span> (i &lt; w - <span class="tok-number">1</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L28"> win.writeCell(i, <span class="tok-number">0</span>, .{ .char = horizontal, .style = style });</span>
<span class="line" id="L29"> win.writeCell(i, h - <span class="tok-number">1</span>, .{ .char = horizontal, .style = style });</span>
<span class="line" id="L30"> }</span>
<span class="line" id="L31"> <span class="tok-kw">return</span> win.initChild(<span class="tok-number">1</span>, <span class="tok-number">1</span>, .{ .limit = w - <span class="tok-number">2</span> }, .{ .limit = w - <span class="tok-number">2</span> });</span>
<span class="line" id="L32">}</span>
<span class="line" id="L33"></span>
</code></pre></body>
</html>

View file

@ -1,132 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/FormatInterface.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Image.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;color.zig&quot;</span>);</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-comment">// mlarouche: Because this is a interface, I use Zig function naming convention instead of the variable naming convention</span>
</span>
<span class="line" id="L6">format: *<span class="tok-kw">const</span> FormatFn,</span>
<span class="line" id="L7">formatDetect: *<span class="tok-kw">const</span> FormatDetectFn,</span>
<span class="line" id="L8">readImage: *<span class="tok-kw">const</span> ReadImageFn,</span>
<span class="line" id="L9">writeImage: *<span class="tok-kw">const</span> WriteImageFn,</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FormatFn = <span class="tok-kw">fn</span> () Image.Format;</span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FormatDetectFn = <span class="tok-kw">fn</span> (stream: *Image.Stream) Image.ReadError!<span class="tok-type">bool</span>;</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ReadImageFn = <span class="tok-kw">fn</span> (allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image;</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> WriteImageFn = <span class="tok-kw">fn</span> (allocator: std.mem.Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.WriteError!<span class="tok-type">void</span>;</span>
<span class="line" id="L15"></span>
</code></pre></body>
</html>

View file

@ -1,370 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/Image.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> AllImageFormats = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;formats/all.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;color.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Error = <span class="tok-kw">error</span>{</span>
<span class="line" id="L9"> Unsupported,</span>
<span class="line" id="L10">};</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ReadError = Error ||</span>
<span class="line" id="L13"> std.mem.Allocator.Error ||</span>
<span class="line" id="L14"> utils.StructReadError ||</span>
<span class="line" id="L15"> std.io.StreamSource.SeekError ||</span>
<span class="line" id="L16"> std.io.StreamSource.GetSeekPosError ||</span>
<span class="line" id="L17"> <span class="tok-kw">error</span>{ EndOfStream, StreamTooLong, InvalidData };</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> WriteError = Error ||</span>
<span class="line" id="L20"> std.mem.Allocator.Error ||</span>
<span class="line" id="L21"> std.io.StreamSource.WriteError ||</span>
<span class="line" id="L22"> std.io.StreamSource.SeekError ||</span>
<span class="line" id="L23"> std.io.StreamSource.GetSeekPosError ||</span>
<span class="line" id="L24"> std.fs.File.OpenError ||</span>
<span class="line" id="L25"> <span class="tok-kw">error</span>{ EndOfStream, InvalidData, UnfinishedBits };</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Format = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L28"> bmp,</span>
<span class="line" id="L29"> gif,</span>
<span class="line" id="L30"> jpg,</span>
<span class="line" id="L31"> pbm,</span>
<span class="line" id="L32"> pcx,</span>
<span class="line" id="L33"> pgm,</span>
<span class="line" id="L34"> png,</span>
<span class="line" id="L35"> ppm,</span>
<span class="line" id="L36"> qoi,</span>
<span class="line" id="L37"> tga,</span>
<span class="line" id="L38"> pam,</span>
<span class="line" id="L39">};</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Stream = std.io.StreamSource;</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = AllImageFormats.ImageEncoderOptions;</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> AnimationLoopInfinite = -<span class="tok-number">1</span>;</span>
<span class="line" id="L46"></span>
<span class="line" id="L47"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> AnimationFrame = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L48"> pixels: color.PixelStorage,</span>
<span class="line" id="L49"> duration: <span class="tok-type">f32</span>,</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: AnimationFrame, allocator: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L52"> self.pixels.deinit(allocator);</span>
<span class="line" id="L53"> }</span>
<span class="line" id="L54">};</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Animation = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L57"> frames: FrameList = .{},</span>
<span class="line" id="L58"> loop_count: <span class="tok-type">i32</span> = AnimationLoopInfinite,</span>
<span class="line" id="L59"></span>
<span class="line" id="L60"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> FrameList = std.ArrayListUnmanaged(AnimationFrame);</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Animation, allocator: std.mem.Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L63"> <span class="tok-comment">// Animation share its first frame with the pixels in Image, we don't want to free it twice</span>
</span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (self.frames.items.len &gt;= <span class="tok-number">2</span>) {</span>
<span class="line" id="L65"> <span class="tok-kw">for</span> (self.frames.items[<span class="tok-number">1</span>..]) |frame| {</span>
<span class="line" id="L66"> frame.pixels.deinit(allocator);</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> self.frames.deinit(allocator);</span>
<span class="line" id="L71"> }</span>
<span class="line" id="L72">};</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"><span class="tok-comment">/// Format-independant image</span></span>
<span class="line" id="L75">allocator: std.mem.Allocator = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L76">width: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L77">height: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L78">pixels: color.PixelStorage = .{ .invalid = <span class="tok-type">void</span>{} },</span>
<span class="line" id="L79">animation: Animation = .{},</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"><span class="tok-kw">const</span> FormatInteraceFnType = *<span class="tok-kw">const</span> <span class="tok-kw">fn</span> () FormatInterface;</span>
<span class="line" id="L84"><span class="tok-kw">const</span> all_interface_funcs = blk: {</span>
<span class="line" id="L85"> <span class="tok-kw">const</span> allFormatDecls = std.meta.declarations(AllImageFormats);</span>
<span class="line" id="L86"> <span class="tok-kw">var</span> result: [allFormatDecls.len]FormatInteraceFnType = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L87"> <span class="tok-kw">var</span> index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L88"> <span class="tok-kw">for</span> (allFormatDecls) |decl| {</span>
<span class="line" id="L89"> <span class="tok-kw">const</span> decl_value = <span class="tok-builtin">@field</span>(AllImageFormats, decl.name);</span>
<span class="line" id="L90"> <span class="tok-kw">const</span> entry_type = <span class="tok-builtin">@TypeOf</span>(decl_value);</span>
<span class="line" id="L91"> <span class="tok-kw">if</span> (entry_type == <span class="tok-type">type</span>) {</span>
<span class="line" id="L92"> <span class="tok-kw">const</span> entryTypeInfo = <span class="tok-builtin">@typeInfo</span>(decl_value);</span>
<span class="line" id="L93"> <span class="tok-kw">if</span> (entryTypeInfo == .Struct) {</span>
<span class="line" id="L94"> <span class="tok-kw">for</span> (entryTypeInfo.Struct.decls) |structEntry| {</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, structEntry.name, <span class="tok-str">&quot;formatInterface&quot;</span>)) {</span>
<span class="line" id="L96"> result[index] = <span class="tok-builtin">@field</span>(decl_value, structEntry.name);</span>
<span class="line" id="L97"> index += <span class="tok-number">1</span>;</span>
<span class="line" id="L98"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103"> }</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"> <span class="tok-kw">break</span> :blk result[<span class="tok-number">0</span>..index];</span>
<span class="line" id="L106">};</span>
<span class="line" id="L107"></span>
<span class="line" id="L108"><span class="tok-comment">/// Init an empty image with no pixel data</span></span>
<span class="line" id="L109"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: std.mem.Allocator) Image {</span>
<span class="line" id="L110"> <span class="tok-kw">return</span> Image{</span>
<span class="line" id="L111"> .allocator = allocator,</span>
<span class="line" id="L112"> };</span>
<span class="line" id="L113">}</span>
<span class="line" id="L114"></span>
<span class="line" id="L115"><span class="tok-comment">/// Deinit the image</span></span>
<span class="line" id="L116"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Image) <span class="tok-type">void</span> {</span>
<span class="line" id="L117"> self.pixels.deinit(self.allocator);</span>
<span class="line" id="L118"> self.animation.deinit(self.allocator);</span>
<span class="line" id="L119">}</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"><span class="tok-comment">/// Load an image from a file path</span></span>
<span class="line" id="L122"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromFilePath</span>(allocator: std.mem.Allocator, file_path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !Image {</span>
<span class="line" id="L123"> <span class="tok-kw">var</span> file = <span class="tok-kw">try</span> std.fs.cwd().openFile(file_path, .{});</span>
<span class="line" id="L124"> <span class="tok-kw">defer</span> file.close();</span>
<span class="line" id="L125"></span>
<span class="line" id="L126"> <span class="tok-kw">return</span> fromFile(allocator, &amp;file);</span>
<span class="line" id="L127">}</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"><span class="tok-comment">/// Load an image from a standard library std.fs.File</span></span>
<span class="line" id="L130"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromFile</span>(allocator: std.mem.Allocator, file: *std.fs.File) !Image {</span>
<span class="line" id="L131"> <span class="tok-kw">var</span> stream_source = std.io.StreamSource{ .file = file.* };</span>
<span class="line" id="L132"> <span class="tok-kw">return</span> internalRead(allocator, &amp;stream_source);</span>
<span class="line" id="L133">}</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"><span class="tok-comment">/// Load an image from a memory buffer</span></span>
<span class="line" id="L136"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromMemory</span>(allocator: std.mem.Allocator, buffer: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !Image {</span>
<span class="line" id="L137"> <span class="tok-kw">var</span> stream_source = std.io.StreamSource{ .const_buffer = std.io.fixedBufferStream(buffer) };</span>
<span class="line" id="L138"> <span class="tok-kw">return</span> internalRead(allocator, &amp;stream_source);</span>
<span class="line" id="L139">}</span>
<span class="line" id="L140"></span>
<span class="line" id="L141"><span class="tok-comment">/// Create a pixel surface from scratch</span></span>
<span class="line" id="L142"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">create</span>(allocator: std.mem.Allocator, width: <span class="tok-type">usize</span>, height: <span class="tok-type">usize</span>, pixel_format: PixelFormat) !Image {</span>
<span class="line" id="L143"> <span class="tok-kw">const</span> result = Image{</span>
<span class="line" id="L144"> .allocator = allocator,</span>
<span class="line" id="L145"> .width = width,</span>
<span class="line" id="L146"> .height = height,</span>
<span class="line" id="L147"> .pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, width * height),</span>
<span class="line" id="L148"> };</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L151">}</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"><span class="tok-comment">/// Return the pixel format of the image</span></span>
<span class="line" id="L154"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelFormat</span>(self: Image) PixelFormat {</span>
<span class="line" id="L155"> <span class="tok-kw">return</span> std.meta.activeTag(self.pixels);</span>
<span class="line" id="L156">}</span>
<span class="line" id="L157"></span>
<span class="line" id="L158"><span class="tok-comment">/// Return the pixel data as a const byte slice. In case of an animation, it return the pixel data of the first frame.</span></span>
<span class="line" id="L159"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">rawBytes</span>(self: Image) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L160"> <span class="tok-kw">return</span> self.pixels.asBytes();</span>
<span class="line" id="L161">}</span>
<span class="line" id="L162"></span>
<span class="line" id="L163"><span class="tok-comment">/// Return the byte size of a row in the image</span></span>
<span class="line" id="L164"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">rowByteSize</span>(self: Image) <span class="tok-type">usize</span> {</span>
<span class="line" id="L165"> <span class="tok-kw">return</span> self.imageByteSize() / self.height;</span>
<span class="line" id="L166">}</span>
<span class="line" id="L167"></span>
<span class="line" id="L168"><span class="tok-comment">/// Return the byte size of the whole image</span></span>
<span class="line" id="L169"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">imageByteSize</span>(self: Image) <span class="tok-type">usize</span> {</span>
<span class="line" id="L170"> <span class="tok-kw">return</span> self.rawBytes().len;</span>
<span class="line" id="L171">}</span>
<span class="line" id="L172"></span>
<span class="line" id="L173"><span class="tok-comment">/// Is this image is an animation?</span></span>
<span class="line" id="L174"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isAnimation</span>(self: Image) <span class="tok-type">bool</span> {</span>
<span class="line" id="L175"> <span class="tok-kw">return</span> self.animation.frames.items.len &gt; <span class="tok-number">0</span>;</span>
<span class="line" id="L176">}</span>
<span class="line" id="L177"></span>
<span class="line" id="L178"><span class="tok-comment">/// Write the image to an image format to the specified path</span></span>
<span class="line" id="L179"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeToFilePath</span>(self: Image, file_path: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, encoder_options: EncoderOptions) WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L180"> <span class="tok-kw">var</span> file = <span class="tok-kw">try</span> std.fs.cwd().createFile(file_path, .{});</span>
<span class="line" id="L181"> <span class="tok-kw">defer</span> file.close();</span>
<span class="line" id="L182"></span>
<span class="line" id="L183"> <span class="tok-kw">try</span> self.writeToFile(file, encoder_options);</span>
<span class="line" id="L184">}</span>
<span class="line" id="L185"></span>
<span class="line" id="L186"><span class="tok-comment">/// Write the image to an image format to the specified std.fs.File</span></span>
<span class="line" id="L187"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeToFile</span>(self: Image, file: std.fs.File, encoder_options: EncoderOptions) WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L188"> <span class="tok-kw">var</span> stream_source = std.io.StreamSource{ .file = file };</span>
<span class="line" id="L189"></span>
<span class="line" id="L190"> <span class="tok-kw">try</span> self.internalWrite(&amp;stream_source, encoder_options);</span>
<span class="line" id="L191">}</span>
<span class="line" id="L192"></span>
<span class="line" id="L193"><span class="tok-comment">/// Write the image to an image format in a memory buffer. The memory buffer is not grown</span></span>
<span class="line" id="L194"><span class="tok-comment">/// for you so make sure you pass a large enough buffer.</span></span>
<span class="line" id="L195"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeToMemory</span>(self: Image, write_buffer: []<span class="tok-type">u8</span>, encoder_options: EncoderOptions) WriteError![]<span class="tok-type">u8</span> {</span>
<span class="line" id="L196"> <span class="tok-kw">var</span> stream_source = std.io.StreamSource{ .buffer = std.io.fixedBufferStream(write_buffer) };</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">try</span> self.internalWrite(&amp;stream_source, encoder_options);</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"> <span class="tok-kw">return</span> stream_source.buffer.getWritten();</span>
<span class="line" id="L201">}</span>
<span class="line" id="L202"></span>
<span class="line" id="L203"><span class="tok-comment">/// Iterate the pixel in pixel-format agnostic way. In the case of an animation, it returns an iterator for the first frame. The iterator is read-only.</span></span>
<span class="line" id="L204"><span class="tok-comment">// FIXME: *const Image is a workaround for a stage2 bug because determining the pass a parameter by value or pointer depending of the size is not mature yet</span>
</span>
<span class="line" id="L205"><span class="tok-comment">// and fails. For now we are explictly requesting to access only a const pointer.</span>
</span>
<span class="line" id="L206"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">iterator</span>(self: *<span class="tok-kw">const</span> Image) color.PixelStorageIterator {</span>
<span class="line" id="L207"> <span class="tok-kw">return</span> color.PixelStorageIterator.init(&amp;self.pixels);</span>
<span class="line" id="L208">}</span>
<span class="line" id="L209"></span>
<span class="line" id="L210"><span class="tok-kw">fn</span> <span class="tok-fn">internalRead</span>(allocator: std.mem.Allocator, stream: *Stream) !Image {</span>
<span class="line" id="L211"> <span class="tok-kw">const</span> format_interface = <span class="tok-kw">try</span> findImageInterfaceFromStream(stream);</span>
<span class="line" id="L212"></span>
<span class="line" id="L213"> <span class="tok-kw">try</span> stream.seekTo(<span class="tok-number">0</span>);</span>
<span class="line" id="L214"></span>
<span class="line" id="L215"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> format_interface.readImage(allocator, stream);</span>
<span class="line" id="L216">}</span>
<span class="line" id="L217"></span>
<span class="line" id="L218"><span class="tok-kw">fn</span> <span class="tok-fn">internalWrite</span>(self: Image, stream: *Stream, encoder_options: EncoderOptions) WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L219"> <span class="tok-kw">const</span> image_format = std.meta.activeTag(encoder_options);</span>
<span class="line" id="L220"></span>
<span class="line" id="L221"> <span class="tok-kw">var</span> format_interface = <span class="tok-kw">try</span> findImageInterfaceFromImageFormat(image_format);</span>
<span class="line" id="L222"></span>
<span class="line" id="L223"> <span class="tok-kw">try</span> format_interface.writeImage(self.allocator, stream, self, encoder_options);</span>
<span class="line" id="L224">}</span>
<span class="line" id="L225"></span>
<span class="line" id="L226"><span class="tok-kw">fn</span> <span class="tok-fn">findImageInterfaceFromStream</span>(stream: *Stream) !FormatInterface {</span>
<span class="line" id="L227"> <span class="tok-kw">for</span> (all_interface_funcs) |intefaceFn| {</span>
<span class="line" id="L228"> <span class="tok-kw">const</span> formatInterface = intefaceFn();</span>
<span class="line" id="L229"></span>
<span class="line" id="L230"> <span class="tok-kw">try</span> stream.seekTo(<span class="tok-number">0</span>);</span>
<span class="line" id="L231"> <span class="tok-kw">const</span> found = <span class="tok-kw">try</span> formatInterface.formatDetect(stream);</span>
<span class="line" id="L232"> <span class="tok-kw">if</span> (found) {</span>
<span class="line" id="L233"> <span class="tok-kw">return</span> formatInterface;</span>
<span class="line" id="L234"> }</span>
<span class="line" id="L235"> }</span>
<span class="line" id="L236"></span>
<span class="line" id="L237"> <span class="tok-kw">return</span> Error.Unsupported;</span>
<span class="line" id="L238">}</span>
<span class="line" id="L239"></span>
<span class="line" id="L240"><span class="tok-kw">fn</span> <span class="tok-fn">findImageInterfaceFromImageFormat</span>(image_format: Format) !FormatInterface {</span>
<span class="line" id="L241"> <span class="tok-kw">for</span> (all_interface_funcs) |interface_fn| {</span>
<span class="line" id="L242"> <span class="tok-kw">const</span> format_interface = interface_fn();</span>
<span class="line" id="L243"></span>
<span class="line" id="L244"> <span class="tok-kw">if</span> (format_interface.format() == image_format) {</span>
<span class="line" id="L245"> <span class="tok-kw">return</span> format_interface;</span>
<span class="line" id="L246"> }</span>
<span class="line" id="L247"> }</span>
<span class="line" id="L248"></span>
<span class="line" id="L249"> <span class="tok-kw">return</span> Error.Unsupported;</span>
<span class="line" id="L250">}</span>
<span class="line" id="L251"></span>
</code></pre></body>
</html>

View file

@ -1,373 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/buffered_stream_source.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">const</span> DefaultBufferSize = <span class="tok-number">8</span> * <span class="tok-number">1024</span>;</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> DefaultBufferedStreamSourceReader = BufferedStreamSourceReader(DefaultBufferSize);</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> DefaultBufferedStreamSourceWriter = BufferedStreamSourceWriter(DefaultBufferSize);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">// An buffered stream that can read and seek StreamSource</span>
</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">BufferedStreamSourceReader</span>(<span class="tok-kw">comptime</span> BufferSize: <span class="tok-type">usize</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L10"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L11"> buffered_reader: std.io.BufferedReader(BufferSize, std.io.StreamSource.Reader),</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> ReadError = std.io.StreamSource.ReadError;</span>
<span class="line" id="L14"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SeekError = std.io.StreamSource.SeekError;</span>
<span class="line" id="L15"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> GetSeekPosError = std.io.StreamSource.GetSeekPosError;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Reader = std.io.Reader(*Self, ReadError, read);</span>
<span class="line" id="L20"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SeekableStream = std.io.SeekableStream(</span>
<span class="line" id="L21"> *Self,</span>
<span class="line" id="L22"> SeekError,</span>
<span class="line" id="L23"> GetSeekPosError,</span>
<span class="line" id="L24"> seekTo,</span>
<span class="line" id="L25"> seekBy,</span>
<span class="line" id="L26"> getPos,</span>
<span class="line" id="L27"> getEndPos,</span>
<span class="line" id="L28"> );</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *Self, dest: []<span class="tok-type">u8</span>) ReadError!<span class="tok-type">usize</span> {</span>
<span class="line" id="L31"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.buffered_reader.unbuffered_reader.context.*) {</span>
<span class="line" id="L32"> .buffer =&gt; |*actual_reader| actual_reader.read(dest),</span>
<span class="line" id="L33"> .const_buffer =&gt; |*actual_reader| actual_reader.read(dest),</span>
<span class="line" id="L34"> .file =&gt; self.buffered_reader.read(dest),</span>
<span class="line" id="L35"> };</span>
<span class="line" id="L36"> }</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekTo</span>(self: *Self, pos: <span class="tok-type">u64</span>) SeekError!<span class="tok-type">void</span> {</span>
<span class="line" id="L39"> <span class="tok-kw">switch</span> (self.buffered_reader.unbuffered_reader.context.*) {</span>
<span class="line" id="L40"> .buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L41"> <span class="tok-kw">return</span> actual_reader.seekTo(pos);</span>
<span class="line" id="L42"> },</span>
<span class="line" id="L43"> .const_buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L44"> <span class="tok-kw">return</span> actual_reader.seekTo(pos);</span>
<span class="line" id="L45"> },</span>
<span class="line" id="L46"> .file =&gt; {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> self.buffered_reader.unbuffered_reader.context.seekTo(pos);</span>
<span class="line" id="L48"> self.resetBufferedReader();</span>
<span class="line" id="L49"> },</span>
<span class="line" id="L50"> }</span>
<span class="line" id="L51"> }</span>
<span class="line" id="L52"></span>
<span class="line" id="L53"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekBy</span>(self: *Self, amt: <span class="tok-type">i64</span>) SeekError!<span class="tok-type">void</span> {</span>
<span class="line" id="L54"> <span class="tok-kw">switch</span> (self.buffered_reader.unbuffered_reader.context.*) {</span>
<span class="line" id="L55"> .buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L56"> <span class="tok-kw">return</span> actual_reader.seekBy(amt);</span>
<span class="line" id="L57"> },</span>
<span class="line" id="L58"> .const_buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L59"> <span class="tok-kw">return</span> actual_reader.seekBy(amt);</span>
<span class="line" id="L60"> },</span>
<span class="line" id="L61"> .file =&gt; {</span>
<span class="line" id="L62"> <span class="tok-kw">const</span> bytes_availables = self.buffered_reader.end - self.buffered_reader.start;</span>
<span class="line" id="L63"> <span class="tok-kw">if</span> (amt &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (amt &lt;= bytes_availables) {</span>
<span class="line" id="L65"> self.buffered_reader.start += <span class="tok-builtin">@intCast</span>(amt);</span>
<span class="line" id="L66"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L67"> <span class="tok-kw">try</span> self.buffered_reader.unbuffered_reader.context.seekBy(amt - <span class="tok-builtin">@as</span>(<span class="tok-type">i64</span>, <span class="tok-builtin">@intCast</span>(bytes_availables)));</span>
<span class="line" id="L68"> self.resetBufferedReader();</span>
<span class="line" id="L69"> }</span>
<span class="line" id="L70"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (amt &lt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L71"> <span class="tok-kw">const</span> absolute_amt = <span class="tok-builtin">@abs</span>(amt);</span>
<span class="line" id="L72"> <span class="tok-kw">const</span> absolute_amt_usize = std.math.cast(<span class="tok-type">usize</span>, absolute_amt) <span class="tok-kw">orelse</span> std.math.maxInt(<span class="tok-type">usize</span>);</span>
<span class="line" id="L73"> <span class="tok-kw">if</span> (absolute_amt_usize &lt;= self.buffered_reader.start) {</span>
<span class="line" id="L74"> self.buffered_reader.start -%= absolute_amt_usize;</span>
<span class="line" id="L75"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L76"> <span class="tok-kw">try</span> self.buffered_reader.unbuffered_reader.context.seekBy(amt - <span class="tok-builtin">@as</span>(<span class="tok-type">i64</span>, <span class="tok-builtin">@intCast</span>(bytes_availables)));</span>
<span class="line" id="L77"> self.resetBufferedReader();</span>
<span class="line" id="L78"> }</span>
<span class="line" id="L79"> }</span>
<span class="line" id="L80"> },</span>
<span class="line" id="L81"> }</span>
<span class="line" id="L82"> }</span>
<span class="line" id="L83"></span>
<span class="line" id="L84"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getEndPos</span>(self: *Self) GetSeekPosError!<span class="tok-type">u64</span> {</span>
<span class="line" id="L85"> <span class="tok-kw">return</span> self.buffered_reader.unbuffered_reader.context.getEndPos();</span>
<span class="line" id="L86"> }</span>
<span class="line" id="L87"></span>
<span class="line" id="L88"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getPos</span>(self: *Self) GetSeekPosError!<span class="tok-type">u64</span> {</span>
<span class="line" id="L89"> <span class="tok-kw">switch</span> (self.buffered_reader.unbuffered_reader.context.*) {</span>
<span class="line" id="L90"> .buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L91"> <span class="tok-kw">return</span> actual_reader.getPos();</span>
<span class="line" id="L92"> },</span>
<span class="line" id="L93"> .const_buffer =&gt; |*actual_reader| {</span>
<span class="line" id="L94"> <span class="tok-kw">return</span> actual_reader.getPos();</span>
<span class="line" id="L95"> },</span>
<span class="line" id="L96"> .file =&gt; {</span>
<span class="line" id="L97"> <span class="tok-kw">if</span> (self.buffered_reader.unbuffered_reader.context.getPos()) |position| {</span>
<span class="line" id="L98"> <span class="tok-kw">return</span> position - (self.buffered_reader.end - self.buffered_reader.start);</span>
<span class="line" id="L99"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L100"> <span class="tok-kw">return</span> err;</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"> },</span>
<span class="line" id="L103"> }</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">reader</span>(self: *Self) Reader {</span>
<span class="line" id="L107"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekableStream</span>(self: *Self) SeekableStream {</span>
<span class="line" id="L111"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L112"> }</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"> <span class="tok-kw">fn</span> <span class="tok-fn">resetBufferedReader</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L115"> self.buffered_reader.start = <span class="tok-number">0</span>;</span>
<span class="line" id="L116"> self.buffered_reader.end = <span class="tok-number">0</span>;</span>
<span class="line" id="L117"> }</span>
<span class="line" id="L118"> };</span>
<span class="line" id="L119">}</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">bufferedStreamSourceReader</span>(stream: *std.io.StreamSource) BufferedStreamSourceReader(DefaultBufferSize) {</span>
<span class="line" id="L122"> <span class="tok-kw">return</span> .{ .buffered_reader = .{ .unbuffered_reader = stream.reader() } };</span>
<span class="line" id="L123">}</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">bufferedStreamSourceReaderWithSize</span>(<span class="tok-kw">comptime</span> buffer_size: <span class="tok-type">usize</span>, stream: *std.io.StreamSource) BufferedStreamSourceReader(buffer_size) {</span>
<span class="line" id="L126"> <span class="tok-kw">return</span> .{ .buffered_reader = .{ .unbuffered_reader = stream.reader() } };</span>
<span class="line" id="L127">}</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"><span class="tok-comment">// An buffered stream that can writer and seek StreamSource</span>
</span>
<span class="line" id="L130"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">BufferedStreamSourceWriter</span>(<span class="tok-kw">comptime</span> BufferSize: <span class="tok-type">usize</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L131"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L132"> buffered_writer: std.io.BufferedWriter(BufferSize, std.io.StreamSource.Writer),</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> WriteError = std.io.StreamSource.WriteError;</span>
<span class="line" id="L135"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SeekError = std.io.StreamSource.SeekError;</span>
<span class="line" id="L136"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> GetSeekPosError = std.io.StreamSource.GetSeekPosError;</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L139"></span>
<span class="line" id="L140"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Writer = std.io.Writer(*Self, WriteError, write);</span>
<span class="line" id="L141"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> SeekableStream = std.io.SeekableStream(</span>
<span class="line" id="L142"> *Self,</span>
<span class="line" id="L143"> SeekError,</span>
<span class="line" id="L144"> GetSeekPosError,</span>
<span class="line" id="L145"> seekTo,</span>
<span class="line" id="L146"> seekBy,</span>
<span class="line" id="L147"> getPos,</span>
<span class="line" id="L148"> getEndPos,</span>
<span class="line" id="L149"> );</span>
<span class="line" id="L150"></span>
<span class="line" id="L151"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Self, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) WriteError!<span class="tok-type">usize</span> {</span>
<span class="line" id="L152"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.buffered_writer.unbuffered_writer.context.*) {</span>
<span class="line" id="L153"> .buffer =&gt; |*actual_writer| actual_writer.write(bytes),</span>
<span class="line" id="L154"> .const_buffer =&gt; <span class="tok-kw">error</span>.AccessDenied,</span>
<span class="line" id="L155"> .file =&gt; self.buffered_writer.write(bytes),</span>
<span class="line" id="L156"> };</span>
<span class="line" id="L157"> }</span>
<span class="line" id="L158"></span>
<span class="line" id="L159"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekTo</span>(self: *Self, pos: <span class="tok-type">u64</span>) SeekError!<span class="tok-type">void</span> {</span>
<span class="line" id="L160"> <span class="tok-kw">switch</span> (self.buffered_writer.unbuffered_writer.context.*) {</span>
<span class="line" id="L161"> .buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L162"> <span class="tok-kw">return</span> actual_writer.seekTo(pos);</span>
<span class="line" id="L163"> },</span>
<span class="line" id="L164"> .const_buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L165"> <span class="tok-kw">return</span> actual_writer.seekTo(pos);</span>
<span class="line" id="L166"> },</span>
<span class="line" id="L167"> .file =&gt; {</span>
<span class="line" id="L168"> <span class="tok-kw">try</span> self.buffered_writer.flush();</span>
<span class="line" id="L169"> <span class="tok-kw">try</span> self.buffered_writer.buffered_writer.context.seekTo(pos);</span>
<span class="line" id="L170"> },</span>
<span class="line" id="L171"> }</span>
<span class="line" id="L172"> }</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekBy</span>(self: *Self, amt: <span class="tok-type">i64</span>) SeekError!<span class="tok-type">void</span> {</span>
<span class="line" id="L175"> <span class="tok-kw">switch</span> (self.buffered_writer.unbuffered_writer.context.*) {</span>
<span class="line" id="L176"> .buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L177"> <span class="tok-kw">return</span> actual_writer.seekBy(amt);</span>
<span class="line" id="L178"> },</span>
<span class="line" id="L179"> .const_buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L180"> <span class="tok-kw">return</span> actual_writer.seekBy(amt);</span>
<span class="line" id="L181"> },</span>
<span class="line" id="L182"> .file =&gt; {</span>
<span class="line" id="L183"> <span class="tok-kw">if</span> (amt &lt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L184"> <span class="tok-kw">const</span> abs_amt = <span class="tok-builtin">@abs</span>(amt);</span>
<span class="line" id="L185"> <span class="tok-kw">if</span> (abs_amt &lt;= self.buffered_writer.end) {</span>
<span class="line" id="L186"> self.buffered_writer.end -= abs_amt;</span>
<span class="line" id="L187"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L188"> self.buffered_writer.flush() <span class="tok-kw">catch</span> {</span>
<span class="line" id="L189"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unseekable;</span>
<span class="line" id="L190"> };</span>
<span class="line" id="L191"> <span class="tok-kw">try</span> self.buffered_writer.unbuffered_writer.context.seekBy(amt);</span>
<span class="line" id="L192"> }</span>
<span class="line" id="L193"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L194"> <span class="tok-kw">const</span> amt_usize: <span class="tok-type">usize</span> = <span class="tok-builtin">@intCast</span>(amt);</span>
<span class="line" id="L195"></span>
<span class="line" id="L196"> <span class="tok-kw">if</span> (self.buffered_writer.end + amt_usize &lt; self.buffered_writer.buf.len) {</span>
<span class="line" id="L197"> self.buffered_writer.end += amt_usize;</span>
<span class="line" id="L198"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L199"> self.buffered_writer.flush() <span class="tok-kw">catch</span> {</span>
<span class="line" id="L200"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unseekable;</span>
<span class="line" id="L201"> };</span>
<span class="line" id="L202"> <span class="tok-kw">try</span> self.buffered_writer.unbuffered_writer.context.seekBy(amt);</span>
<span class="line" id="L203"> }</span>
<span class="line" id="L204"> }</span>
<span class="line" id="L205"> },</span>
<span class="line" id="L206"> }</span>
<span class="line" id="L207"> }</span>
<span class="line" id="L208"></span>
<span class="line" id="L209"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getEndPos</span>(self: *Self) GetSeekPosError!<span class="tok-type">u64</span> {</span>
<span class="line" id="L210"> <span class="tok-kw">return</span> self.buffered_writer.unbuffered_writer.context.getEndPos();</span>
<span class="line" id="L211"> }</span>
<span class="line" id="L212"></span>
<span class="line" id="L213"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getPos</span>(self: *Self) GetSeekPosError!<span class="tok-type">u64</span> {</span>
<span class="line" id="L214"> <span class="tok-kw">switch</span> (self.buffered_writer.unbuffered_writer.context.*) {</span>
<span class="line" id="L215"> .buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L216"> <span class="tok-kw">return</span> actual_writer.getPos();</span>
<span class="line" id="L217"> },</span>
<span class="line" id="L218"> .const_buffer =&gt; |*actual_writer| {</span>
<span class="line" id="L219"> <span class="tok-kw">return</span> actual_writer.getPos();</span>
<span class="line" id="L220"> },</span>
<span class="line" id="L221"> .file =&gt; {</span>
<span class="line" id="L222"> <span class="tok-kw">if</span> (self.buffered_writer.unbuffered_writer.context.getPos()) |position| {</span>
<span class="line" id="L223"> <span class="tok-kw">return</span> position + self.buffered_writer.end;</span>
<span class="line" id="L224"> } <span class="tok-kw">else</span> |err| {</span>
<span class="line" id="L225"> <span class="tok-kw">return</span> err;</span>
<span class="line" id="L226"> }</span>
<span class="line" id="L227"> },</span>
<span class="line" id="L228"> }</span>
<span class="line" id="L229"> }</span>
<span class="line" id="L230"></span>
<span class="line" id="L231"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writer</span>(self: *Self) Writer {</span>
<span class="line" id="L232"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L233"> }</span>
<span class="line" id="L234"></span>
<span class="line" id="L235"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">seekableStream</span>(self: *Self) SeekableStream {</span>
<span class="line" id="L236"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L237"> }</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">flush</span>(self: *Self) WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L240"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.buffered_writer.unbuffered_writer.context.*) {</span>
<span class="line" id="L241"> .file =&gt; self.buffered_writer.flush(),</span>
<span class="line" id="L242"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L243"> };</span>
<span class="line" id="L244"> }</span>
<span class="line" id="L245"> };</span>
<span class="line" id="L246">}</span>
<span class="line" id="L247"></span>
<span class="line" id="L248"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">bufferedStreamSourceWriter</span>(stream: *std.io.StreamSource) BufferedStreamSourceWriter(DefaultBufferSize) {</span>
<span class="line" id="L249"> <span class="tok-kw">return</span> .{ .buffered_writer = .{ .unbuffered_writer = stream.writer() } };</span>
<span class="line" id="L250">}</span>
<span class="line" id="L251"></span>
<span class="line" id="L252"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">bufferedStreamSourceWriterWithSize</span>(<span class="tok-kw">comptime</span> buffer_size: <span class="tok-type">usize</span>, stream: *std.io.StreamSource) BufferedStreamSourceWriter(buffer_size) {</span>
<span class="line" id="L253"> <span class="tok-kw">return</span> .{ .buffered_writer = .{ .unbuffered_writer = stream.writer() } };</span>
<span class="line" id="L254">}</span>
<span class="line" id="L255"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,295 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/compressions/lzw.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">// Implement a variable code size LZW decoder with support for clear code and end of information code required for GIF decoding</span>
</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">Decoder</span>(<span class="tok-kw">comptime</span> endian: std.builtin.Endian) <span class="tok-type">type</span> {</span>
<span class="line" id="L6"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L7"> area_allocator: std.heap.ArenaAllocator,</span>
<span class="line" id="L8"> code_size: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L9"> clear_code: <span class="tok-type">u13</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L10"> initial_code_size: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L11"> end_information_code: <span class="tok-type">u13</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L12"> next_code: <span class="tok-type">u13</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L13"> previous_code: ?<span class="tok-type">u13</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L14"> dictionary: std.AutoArrayHashMap(<span class="tok-type">u13</span>, []<span class="tok-kw">const</span> <span class="tok-type">u8</span>),</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> remaining_data: ?<span class="tok-type">u13</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L17"> remaining_bits: <span class="tok-type">u4</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> <span class="tok-kw">const</span> MaxCodeSize = <span class="tok-number">12</span>;</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: std.mem.Allocator, initial_code_size: <span class="tok-type">u8</span>) !Self {</span>
<span class="line" id="L24"> <span class="tok-kw">var</span> result = Self{</span>
<span class="line" id="L25"> .area_allocator = std.heap.ArenaAllocator.init(allocator),</span>
<span class="line" id="L26"> .code_size = initial_code_size,</span>
<span class="line" id="L27"> .dictionary = std.AutoArrayHashMap(<span class="tok-type">u13</span>, []<span class="tok-kw">const</span> <span class="tok-type">u8</span>).init(allocator),</span>
<span class="line" id="L28"> .initial_code_size = initial_code_size,</span>
<span class="line" id="L29"> .clear_code = <span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(initial_code_size),</span>
<span class="line" id="L30"> .end_information_code = (<span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(initial_code_size)) + <span class="tok-number">1</span>,</span>
<span class="line" id="L31"> .next_code = (<span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(initial_code_size)) + <span class="tok-number">2</span>,</span>
<span class="line" id="L32"> };</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"> <span class="tok-comment">// Reset dictionary and code to its default state</span>
</span>
<span class="line" id="L35"> <span class="tok-kw">try</span> result.resetDictionary();</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L38"> }</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L41"> self.area_allocator.deinit();</span>
<span class="line" id="L42"> self.dictionary.deinit();</span>
<span class="line" id="L43"> }</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">decode</span>(self: *Self, reader: Image.Stream.Reader, writer: <span class="tok-kw">anytype</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L46"> <span class="tok-kw">var</span> bit_reader = std.io.bitReader(endian, reader);</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-kw">var</span> bits_to_read = self.code_size + <span class="tok-number">1</span>;</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"> <span class="tok-kw">var</span> read_size: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L51"> <span class="tok-kw">var</span> read_code: <span class="tok-type">u13</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L52"></span>
<span class="line" id="L53"> <span class="tok-kw">if</span> (self.remaining_data) |remaining_data| {</span>
<span class="line" id="L54"> <span class="tok-kw">const</span> rest_of_data = <span class="tok-kw">try</span> bit_reader.readBits(<span class="tok-type">u13</span>, self.remaining_bits, &amp;read_size);</span>
<span class="line" id="L55"> <span class="tok-kw">if</span> (read_size &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L56"> <span class="tok-kw">switch</span> (endian) {</span>
<span class="line" id="L57"> .little =&gt; {</span>
<span class="line" id="L58"> read_code = remaining_data | (rest_of_data &lt;&lt; <span class="tok-builtin">@as</span>(<span class="tok-type">u4</span>, <span class="tok-builtin">@intCast</span>(bits_to_read - self.remaining_bits)));</span>
<span class="line" id="L59"> },</span>
<span class="line" id="L60"> .big =&gt; {</span>
<span class="line" id="L61"> read_code = (remaining_data &lt;&lt; self.remaining_bits) | rest_of_data;</span>
<span class="line" id="L62"> },</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"> }</span>
<span class="line" id="L65"> self.remaining_data = <span class="tok-null">null</span>;</span>
<span class="line" id="L66"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L67"> read_code = <span class="tok-kw">try</span> bit_reader.readBits(<span class="tok-type">u13</span>, bits_to_read, &amp;read_size);</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">var</span> allocator = self.area_allocator.allocator();</span>
<span class="line" id="L71"></span>
<span class="line" id="L72"> <span class="tok-kw">while</span> (read_size &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L73"> <span class="tok-kw">if</span> (self.dictionary.get(read_code)) |value| {</span>
<span class="line" id="L74"> _ = <span class="tok-kw">try</span> writer.write(value);</span>
<span class="line" id="L75"></span>
<span class="line" id="L76"> <span class="tok-kw">if</span> (self.previous_code) |previous_code| {</span>
<span class="line" id="L77"> <span class="tok-kw">if</span> (self.dictionary.get(previous_code)) |previous_value| {</span>
<span class="line" id="L78"> <span class="tok-kw">var</span> new_value = <span class="tok-kw">try</span> allocator.alloc(<span class="tok-type">u8</span>, previous_value.len + <span class="tok-number">1</span>);</span>
<span class="line" id="L79"> std.mem.copyForwards(<span class="tok-type">u8</span>, new_value, previous_value);</span>
<span class="line" id="L80"> new_value[previous_value.len] = value[<span class="tok-number">0</span>];</span>
<span class="line" id="L81"> <span class="tok-kw">try</span> self.dictionary.put(self.next_code, new_value);</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"> self.next_code += <span class="tok-number">1</span>;</span>
<span class="line" id="L84"></span>
<span class="line" id="L85"> <span class="tok-kw">const</span> max_code = <span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(self.code_size + <span class="tok-number">1</span>);</span>
<span class="line" id="L86"> <span class="tok-kw">if</span> (self.next_code == max_code <span class="tok-kw">and</span> (self.code_size + <span class="tok-number">1</span>) &lt; MaxCodeSize) {</span>
<span class="line" id="L87"> self.code_size += <span class="tok-number">1</span>;</span>
<span class="line" id="L88"> bits_to_read += <span class="tok-number">1</span>;</span>
<span class="line" id="L89"> }</span>
<span class="line" id="L90"> }</span>
<span class="line" id="L91"> }</span>
<span class="line" id="L92"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L93"> <span class="tok-kw">if</span> (read_code == self.clear_code) {</span>
<span class="line" id="L94"> <span class="tok-kw">try</span> self.resetDictionary();</span>
<span class="line" id="L95"> bits_to_read = self.code_size + <span class="tok-number">1</span>;</span>
<span class="line" id="L96"> self.previous_code = read_code;</span>
<span class="line" id="L97"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (read_code == self.end_information_code) {</span>
<span class="line" id="L98"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L99"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L100"> <span class="tok-kw">if</span> (self.previous_code) |previous_code| {</span>
<span class="line" id="L101"> <span class="tok-kw">if</span> (self.dictionary.get(previous_code)) |previous_value| {</span>
<span class="line" id="L102"> <span class="tok-kw">var</span> new_value = <span class="tok-kw">try</span> allocator.alloc(<span class="tok-type">u8</span>, previous_value.len + <span class="tok-number">1</span>);</span>
<span class="line" id="L103"> std.mem.copyForwards(<span class="tok-type">u8</span>, new_value, previous_value);</span>
<span class="line" id="L104"> new_value[previous_value.len] = previous_value[<span class="tok-number">0</span>];</span>
<span class="line" id="L105"> <span class="tok-kw">try</span> self.dictionary.put(self.next_code, new_value);</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"> _ = <span class="tok-kw">try</span> writer.write(new_value);</span>
<span class="line" id="L108"></span>
<span class="line" id="L109"> self.next_code += <span class="tok-number">1</span>;</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-kw">const</span> max_code = <span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(self.code_size + <span class="tok-number">1</span>);</span>
<span class="line" id="L112"> <span class="tok-kw">if</span> (self.next_code == max_code <span class="tok-kw">and</span> (self.code_size + <span class="tok-number">1</span>) &lt; MaxCodeSize) {</span>
<span class="line" id="L113"> self.code_size += <span class="tok-number">1</span>;</span>
<span class="line" id="L114"> bits_to_read += <span class="tok-number">1</span>;</span>
<span class="line" id="L115"> }</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"> }</span>
<span class="line" id="L118"> }</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"> self.previous_code = read_code;</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> read_code = <span class="tok-kw">try</span> bit_reader.readBits(<span class="tok-type">u13</span>, bits_to_read, &amp;read_size);</span>
<span class="line" id="L124"> <span class="tok-kw">if</span> (read_size != bits_to_read) {</span>
<span class="line" id="L125"> self.remaining_data = read_code;</span>
<span class="line" id="L126"> self.remaining_bits = <span class="tok-builtin">@intCast</span>(bits_to_read - read_size);</span>
<span class="line" id="L127"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L128"> }</span>
<span class="line" id="L129"> }</span>
<span class="line" id="L130"> }</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> <span class="tok-kw">fn</span> <span class="tok-fn">resetDictionary</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L133"> self.dictionary.clearRetainingCapacity();</span>
<span class="line" id="L134"> self.area_allocator.deinit();</span>
<span class="line" id="L135"></span>
<span class="line" id="L136"> self.code_size = self.initial_code_size;</span>
<span class="line" id="L137"> self.next_code = (<span class="tok-builtin">@as</span>(<span class="tok-type">u13</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(self.initial_code_size)) + <span class="tok-number">2</span>;</span>
<span class="line" id="L138"></span>
<span class="line" id="L139"> self.area_allocator = std.heap.ArenaAllocator.init(self.area_allocator.child_allocator);</span>
<span class="line" id="L140"> <span class="tok-kw">var</span> allocator = self.area_allocator.allocator();</span>
<span class="line" id="L141"></span>
<span class="line" id="L142"> <span class="tok-kw">const</span> roots_size = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@intCast</span>(self.code_size);</span>
<span class="line" id="L143"></span>
<span class="line" id="L144"> <span class="tok-kw">var</span> index: <span class="tok-type">u13</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L145"></span>
<span class="line" id="L146"> <span class="tok-kw">while</span> (index &lt; roots_size) : (index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L147"> <span class="tok-kw">var</span> data = <span class="tok-kw">try</span> allocator.alloc(<span class="tok-type">u8</span>, <span class="tok-number">1</span>);</span>
<span class="line" id="L148"> data[<span class="tok-number">0</span>] = <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@truncate</span>(index));</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"> <span class="tok-kw">try</span> self.dictionary.put(index, data);</span>
<span class="line" id="L151"> }</span>
<span class="line" id="L152"> }</span>
<span class="line" id="L153"> };</span>
<span class="line" id="L154">}</span>
<span class="line" id="L155"></span>
<span class="line" id="L156"><span class="tok-kw">test</span> <span class="tok-str">&quot;Should decode a simple LZW little-endian stream&quot;</span> {</span>
<span class="line" id="L157"> <span class="tok-kw">const</span> initial_code_size = <span class="tok-number">2</span>;</span>
<span class="line" id="L158"> <span class="tok-kw">const</span> test_data = [_]<span class="tok-type">u8</span>{ <span class="tok-number">0x4c</span>, <span class="tok-number">0x01</span> };</span>
<span class="line" id="L159"></span>
<span class="line" id="L160"> <span class="tok-kw">var</span> reader = Image.Stream{</span>
<span class="line" id="L161"> .const_buffer = std.io.fixedBufferStream(&amp;test_data),</span>
<span class="line" id="L162"> };</span>
<span class="line" id="L163"></span>
<span class="line" id="L164"> <span class="tok-kw">var</span> out_data_storage: [<span class="tok-number">256</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L165"> <span class="tok-kw">var</span> out_data_buffer = Image.Stream{</span>
<span class="line" id="L166"> .buffer = std.io.fixedBufferStream(&amp;out_data_storage),</span>
<span class="line" id="L167"> };</span>
<span class="line" id="L168"></span>
<span class="line" id="L169"> <span class="tok-kw">var</span> lzw = <span class="tok-kw">try</span> Decoder(.little).init(std.testing.allocator, initial_code_size);</span>
<span class="line" id="L170"> <span class="tok-kw">defer</span> lzw.deinit();</span>
<span class="line" id="L171"></span>
<span class="line" id="L172"> <span class="tok-kw">try</span> lzw.decode(reader.reader(), out_data_buffer.writer());</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-number">1</span>), out_data_buffer.buffer.pos);</span>
<span class="line" id="L175"> <span class="tok-kw">try</span> std.testing.expectEqual(<span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-number">1</span>), out_data_storage[<span class="tok-number">0</span>]);</span>
<span class="line" id="L176">}</span>
<span class="line" id="L177"></span>
</code></pre></body>
</html>

View file

@ -1,142 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/all.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BMP = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;bmp.zig&quot;</span>).BMP;</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> GIF = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;gif.zig&quot;</span>).GIF;</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> JPEG = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;jpeg.zig&quot;</span>).JPEG;</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PBM = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;netpbm.zig&quot;</span>).PBM;</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PCX = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;pcx.zig&quot;</span>).PCX;</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PGM = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;netpbm.zig&quot;</span>).PGM;</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PNG = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png.zig&quot;</span>).PNG;</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PPM = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;netpbm.zig&quot;</span>).PPM;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> QOI = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;qoi.zig&quot;</span>).QOI;</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TGA = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tga.zig&quot;</span>).TGA;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PAM = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;pam.zig&quot;</span>).PAM;</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ImageEncoderOptions = <span class="tok-kw">union</span>(<span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>).Format) {</span>
<span class="line" id="L14"> bmp: BMP.EncoderOptions,</span>
<span class="line" id="L15"> gif: <span class="tok-type">void</span>,</span>
<span class="line" id="L16"> jpg: <span class="tok-type">void</span>,</span>
<span class="line" id="L17"> pbm: PBM.EncoderOptions,</span>
<span class="line" id="L18"> pcx: PCX.EncoderOptions,</span>
<span class="line" id="L19"> pgm: PGM.EncoderOptions,</span>
<span class="line" id="L20"> png: PNG.EncoderOptions,</span>
<span class="line" id="L21"> ppm: PPM.EncoderOptions,</span>
<span class="line" id="L22"> qoi: QOI.EncoderOptions,</span>
<span class="line" id="L23"> tga: TGA.EncoderOptions,</span>
<span class="line" id="L24"> pam: PAM.EncoderOptions,</span>
<span class="line" id="L25">};</span>
<span class="line" id="L26"></span>
</code></pre></body>
</html>

View file

@ -1,544 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/bmp.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../utils.zig&quot;</span>);</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> BitmapMagicHeader = [_]<span class="tok-type">u8</span>{ <span class="tok-str">'B'</span>, <span class="tok-str">'M'</span> };</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapFileHeader = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L12"> magic_header: [<span class="tok-number">2</span>]<span class="tok-type">u8</span> = BitmapMagicHeader,</span>
<span class="line" id="L13"> size: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L14"> reserved: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L15"> pixel_offset: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L16">};</span>
<span class="line" id="L17"></span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CompressionMethod = <span class="tok-kw">enum</span>(<span class="tok-type">u32</span>) {</span>
<span class="line" id="L19"> none = <span class="tok-number">0</span>,</span>
<span class="line" id="L20"> rle8 = <span class="tok-number">1</span>,</span>
<span class="line" id="L21"> rle4 = <span class="tok-number">2</span>,</span>
<span class="line" id="L22"> bitfields = <span class="tok-number">3</span>,</span>
<span class="line" id="L23"> jpg = <span class="tok-number">4</span>,</span>
<span class="line" id="L24"> png = <span class="tok-number">5</span>,</span>
<span class="line" id="L25"> alpha_bit_fields = <span class="tok-number">6</span>,</span>
<span class="line" id="L26"> cmyk = <span class="tok-number">11</span>,</span>
<span class="line" id="L27"> cmyk_rle8 = <span class="tok-number">12</span>,</span>
<span class="line" id="L28"> cmyk_rle4 = <span class="tok-number">13</span>,</span>
<span class="line" id="L29">};</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapColorSpace = <span class="tok-kw">enum</span>(<span class="tok-type">u32</span>) {</span>
<span class="line" id="L32"> calibrated_rgb = <span class="tok-number">0</span>,</span>
<span class="line" id="L33"> srgb = utils.toMagicNumber(<span class="tok-str">&quot;sRGB&quot;</span>, .big),</span>
<span class="line" id="L34"> windows_color_space = utils.toMagicNumber(<span class="tok-str">&quot;Win &quot;</span>, .big),</span>
<span class="line" id="L35"> profile_linked = utils.toMagicNumber(<span class="tok-str">&quot;LINK&quot;</span>, .big),</span>
<span class="line" id="L36"> profile_embedded = utils.toMagicNumber(<span class="tok-str">&quot;MBED&quot;</span>, .big),</span>
<span class="line" id="L37">};</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapIntent = <span class="tok-kw">enum</span>(<span class="tok-type">u32</span>) {</span>
<span class="line" id="L40"> business = <span class="tok-number">1</span>,</span>
<span class="line" id="L41"> graphics = <span class="tok-number">2</span>,</span>
<span class="line" id="L42"> images = <span class="tok-number">4</span>,</span>
<span class="line" id="L43"> absolute_colorimetric = <span class="tok-number">8</span>,</span>
<span class="line" id="L44">};</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CieXyz = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L47"> x: <span class="tok-type">u32</span> = <span class="tok-number">0</span>, <span class="tok-comment">// TODO: Use FXPT2DOT30</span>
</span>
<span class="line" id="L48"> y: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L49"> z: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L50">};</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CieXyzTriple = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L53"> red: CieXyz = CieXyz{},</span>
<span class="line" id="L54"> green: CieXyz = CieXyz{},</span>
<span class="line" id="L55"> blue: CieXyz = CieXyz{},</span>
<span class="line" id="L56">};</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapInfoHeaderWindows31 = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L59"> header_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L60"> width: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L61"> height: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L62"> color_plane: <span class="tok-type">u16</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L63"> bit_count: <span class="tok-type">u16</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L64"> compression_method: CompressionMethod = .none,</span>
<span class="line" id="L65"> image_raw_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L66"> horizontal_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L67"> vertical_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L68"> palette_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L69"> important_colors: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L70"></span>
<span class="line" id="L71"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> HeaderSize = <span class="tok-builtin">@sizeOf</span>(BitmapInfoHeaderWindows31);</span>
<span class="line" id="L72">};</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapInfoHeaderV4 = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L75"> header_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L76"> width: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L77"> height: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L78"> color_plane: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L79"> bit_count: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L80"> compression_method: CompressionMethod = .none,</span>
<span class="line" id="L81"> image_raw_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L82"> horizontal_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L83"> vertical_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L84"> palette_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L85"> important_colors: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L86"> red_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L87"> green_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L88"> blue_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L89"> alpha_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L90"> color_space: BitmapColorSpace = .srgb,</span>
<span class="line" id="L91"> cie_end_points: CieXyzTriple = .{},</span>
<span class="line" id="L92"> gamma_red: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L93"> gamma_green: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L94"> gamma_blue: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L95"></span>
<span class="line" id="L96"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> HeaderSize = <span class="tok-builtin">@sizeOf</span>(BitmapInfoHeaderV4);</span>
<span class="line" id="L97">};</span>
<span class="line" id="L98"></span>
<span class="line" id="L99"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapInfoHeaderV5 = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L100"> header_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L101"> width: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L102"> height: <span class="tok-type">i32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L103"> color_plane: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L104"> bit_count: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L105"> compression_method: CompressionMethod = .none,</span>
<span class="line" id="L106"> image_raw_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L107"> horizontal_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L108"> vertical_resolution: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L109"> palette_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L110"> important_colors: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L111"> red_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L112"> green_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L113"> blue_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L114"> alpha_mask: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L115"> color_space: BitmapColorSpace = .srgb,</span>
<span class="line" id="L116"> cie_end_points: CieXyzTriple = .{},</span>
<span class="line" id="L117"> gamma_red: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L118"> gamma_green: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L119"> gamma_blue: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L120"> intent: BitmapIntent = .graphics,</span>
<span class="line" id="L121"> profile_data: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L122"> profile_size: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L123"> reserved: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> HeaderSize = <span class="tok-builtin">@sizeOf</span>(BitmapInfoHeaderV5);</span>
<span class="line" id="L126">};</span>
<span class="line" id="L127"></span>
<span class="line" id="L128"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BitmapInfoHeader = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L129"> windows31: BitmapInfoHeaderWindows31,</span>
<span class="line" id="L130"> v4: BitmapInfoHeaderV4,</span>
<span class="line" id="L131"> v5: BitmapInfoHeaderV5,</span>
<span class="line" id="L132">};</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"><span class="tok-comment">// Print resolution of the image,</span>
</span>
<span class="line" id="L135"><span class="tok-comment">// 72 DPI × 39.3701 inches per metre yields 2834.6472</span>
</span>
<span class="line" id="L136"><span class="tok-kw">const</span> PixelsPerMeterResolution = <span class="tok-number">2835</span>;</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> BMP = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L139"> file_header: BitmapFileHeader = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L140"> info_header: BitmapInfoHeader = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L141"></span>
<span class="line" id="L142"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {};</span>
<span class="line" id="L143"></span>
<span class="line" id="L144"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L145"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L146"> .format = format,</span>
<span class="line" id="L147"> .formatDetect = formatDetect,</span>
<span class="line" id="L148"> .readImage = readImage,</span>
<span class="line" id="L149"> .writeImage = writeImage,</span>
<span class="line" id="L150"> };</span>
<span class="line" id="L151"> }</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L154"> <span class="tok-kw">return</span> Image.Format.bmp;</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) Image.Stream.ReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L158"> <span class="tok-kw">var</span> magic_number_buffer: [<span class="tok-number">2</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L159"> _ = <span class="tok-kw">try</span> stream.read(magic_number_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L160"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, magic_number_buffer[<span class="tok-number">0</span>..], BitmapMagicHeader[<span class="tok-number">0</span>..])) {</span>
<span class="line" id="L161"> <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L162"> }</span>
<span class="line" id="L163"></span>
<span class="line" id="L164"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L165"> }</span>
<span class="line" id="L166"></span>
<span class="line" id="L167"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!Image {</span>
<span class="line" id="L168"> <span class="tok-kw">var</span> result = Image.init(allocator);</span>
<span class="line" id="L169"> <span class="tok-kw">errdefer</span> result.deinit();</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-kw">var</span> bmp = BMP{};</span>
<span class="line" id="L172"> <span class="tok-kw">const</span> pixels = <span class="tok-kw">try</span> bmp.read(allocator, stream);</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> result.width = <span class="tok-builtin">@intCast</span>(bmp.width());</span>
<span class="line" id="L175"> result.height = <span class="tok-builtin">@intCast</span>(bmp.height());</span>
<span class="line" id="L176"> result.pixels = pixels;</span>
<span class="line" id="L177"></span>
<span class="line" id="L178"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L179"> }</span>
<span class="line" id="L180"></span>
<span class="line" id="L181"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: std.mem.Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L182"> <span class="tok-kw">var</span> bmp = BMP{};</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-comment">// Fill header information based on pixel format</span>
</span>
<span class="line" id="L185"> <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L186"> .bgr24 =&gt; {</span>
<span class="line" id="L187"> bmp.file_header = .{</span>
<span class="line" id="L188"> .size = <span class="tok-builtin">@intCast</span>(image.width * image.height * <span class="tok-number">3</span> + <span class="tok-builtin">@sizeOf</span>(BitmapFileHeader) + BitmapInfoHeaderV4.HeaderSize),</span>
<span class="line" id="L189"> .pixel_offset = <span class="tok-builtin">@sizeOf</span>(BitmapFileHeader) + BitmapInfoHeaderV4.HeaderSize,</span>
<span class="line" id="L190"> };</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> bmp.info_header = .{</span>
<span class="line" id="L193"> .v4 = .{</span>
<span class="line" id="L194"> .header_size = BitmapInfoHeaderV4.HeaderSize,</span>
<span class="line" id="L195"> .width = <span class="tok-builtin">@intCast</span>(image.width),</span>
<span class="line" id="L196"> .height = <span class="tok-builtin">@intCast</span>(image.height),</span>
<span class="line" id="L197"> .color_plane = <span class="tok-number">1</span>,</span>
<span class="line" id="L198"> .bit_count = <span class="tok-number">24</span>,</span>
<span class="line" id="L199"> .compression_method = .none,</span>
<span class="line" id="L200"> .image_raw_size = <span class="tok-builtin">@intCast</span>(image.width * image.height * <span class="tok-number">3</span>),</span>
<span class="line" id="L201"> .horizontal_resolution = PixelsPerMeterResolution,</span>
<span class="line" id="L202"> .vertical_resolution = PixelsPerMeterResolution,</span>
<span class="line" id="L203"> .color_space = .srgb,</span>
<span class="line" id="L204"> },</span>
<span class="line" id="L205"> };</span>
<span class="line" id="L206"> },</span>
<span class="line" id="L207"> .bgra32 =&gt; {</span>
<span class="line" id="L208"> bmp.file_header = .{</span>
<span class="line" id="L209"> .size = <span class="tok-builtin">@intCast</span>(image.width * image.height * <span class="tok-number">4</span> + <span class="tok-builtin">@sizeOf</span>(BitmapFileHeader) + BitmapInfoHeaderV5.HeaderSize),</span>
<span class="line" id="L210"> .pixel_offset = <span class="tok-builtin">@sizeOf</span>(BitmapFileHeader) + BitmapInfoHeaderV5.HeaderSize,</span>
<span class="line" id="L211"> };</span>
<span class="line" id="L212"></span>
<span class="line" id="L213"> bmp.info_header = .{</span>
<span class="line" id="L214"> .v5 = .{</span>
<span class="line" id="L215"> .header_size = BitmapInfoHeaderV5.HeaderSize,</span>
<span class="line" id="L216"> .width = <span class="tok-builtin">@intCast</span>(image.width),</span>
<span class="line" id="L217"> .height = <span class="tok-builtin">@intCast</span>(image.height),</span>
<span class="line" id="L218"> .color_plane = <span class="tok-number">1</span>,</span>
<span class="line" id="L219"> .bit_count = <span class="tok-number">32</span>,</span>
<span class="line" id="L220"> .compression_method = .bitfields, <span class="tok-comment">// We must specify the color mask when using an 32-bpp bmp with V5</span>
</span>
<span class="line" id="L221"> .image_raw_size = <span class="tok-builtin">@intCast</span>(image.width * image.height * <span class="tok-number">4</span>),</span>
<span class="line" id="L222"> .horizontal_resolution = PixelsPerMeterResolution,</span>
<span class="line" id="L223"> .vertical_resolution = PixelsPerMeterResolution,</span>
<span class="line" id="L224"> .color_space = .srgb,</span>
<span class="line" id="L225"> .red_mask = <span class="tok-number">0x0000FF00</span>,</span>
<span class="line" id="L226"> .green_mask = <span class="tok-number">0x00FF0000</span>,</span>
<span class="line" id="L227"> .blue_mask = <span class="tok-number">0xFF000000</span>,</span>
<span class="line" id="L228"> .alpha_mask = <span class="tok-number">0x000000FF</span>,</span>
<span class="line" id="L229"> },</span>
<span class="line" id="L230"> };</span>
<span class="line" id="L231"> },</span>
<span class="line" id="L232"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L233"> <span class="tok-kw">return</span> Image.WriteError.InvalidData;</span>
<span class="line" id="L234"> },</span>
<span class="line" id="L235"> }</span>
<span class="line" id="L236"></span>
<span class="line" id="L237"> <span class="tok-kw">try</span> bmp.write(stream, image.pixels);</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"> _ = allocator;</span>
<span class="line" id="L240"> _ = encoder_options;</span>
<span class="line" id="L241"> }</span>
<span class="line" id="L242"></span>
<span class="line" id="L243"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">width</span>(self: BMP) <span class="tok-type">i32</span> {</span>
<span class="line" id="L244"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.info_header) {</span>
<span class="line" id="L245"> .windows31 =&gt; |win31| {</span>
<span class="line" id="L246"> <span class="tok-kw">return</span> win31.width;</span>
<span class="line" id="L247"> },</span>
<span class="line" id="L248"> .v4 =&gt; |v4Header| {</span>
<span class="line" id="L249"> <span class="tok-kw">return</span> v4Header.width;</span>
<span class="line" id="L250"> },</span>
<span class="line" id="L251"> .v5 =&gt; |v5Header| {</span>
<span class="line" id="L252"> <span class="tok-kw">return</span> v5Header.width;</span>
<span class="line" id="L253"> },</span>
<span class="line" id="L254"> };</span>
<span class="line" id="L255"> }</span>
<span class="line" id="L256"></span>
<span class="line" id="L257"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">height</span>(self: BMP) <span class="tok-type">i32</span> {</span>
<span class="line" id="L258"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.info_header) {</span>
<span class="line" id="L259"> .windows31 =&gt; |win31| {</span>
<span class="line" id="L260"> <span class="tok-kw">return</span> win31.height;</span>
<span class="line" id="L261"> },</span>
<span class="line" id="L262"> .v4 =&gt; |v4Header| {</span>
<span class="line" id="L263"> <span class="tok-kw">return</span> v4Header.height;</span>
<span class="line" id="L264"> },</span>
<span class="line" id="L265"> .v5 =&gt; |v5Header| {</span>
<span class="line" id="L266"> <span class="tok-kw">return</span> v5Header.height;</span>
<span class="line" id="L267"> },</span>
<span class="line" id="L268"> };</span>
<span class="line" id="L269"> }</span>
<span class="line" id="L270"></span>
<span class="line" id="L271"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelFormat</span>(self: BMP) Image.ReadError!PixelFormat {</span>
<span class="line" id="L272"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.info_header) {</span>
<span class="line" id="L273"> .v4 =&gt; |v4Header| <span class="tok-kw">try</span> findPixelFormat(v4Header.bit_count, v4Header.compression_method),</span>
<span class="line" id="L274"> .v5 =&gt; |v5Header| <span class="tok-kw">try</span> findPixelFormat(v5Header.bit_count, v5Header.compression_method),</span>
<span class="line" id="L275"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> Image.Error.Unsupported,</span>
<span class="line" id="L276"> };</span>
<span class="line" id="L277"> }</span>
<span class="line" id="L278"></span>
<span class="line" id="L279"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *BMP, allocator: std.mem.Allocator, stream: *Image.Stream) Image.ReadError!color.PixelStorage {</span>
<span class="line" id="L280"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L281"></span>
<span class="line" id="L282"> <span class="tok-comment">// Read file header</span>
</span>
<span class="line" id="L283"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L284"> self.file_header = <span class="tok-kw">try</span> utils.readStruct(reader, BitmapFileHeader, .little);</span>
<span class="line" id="L285"> <span class="tok-kw">if</span> (!std.mem.eql(<span class="tok-type">u8</span>, self.file_header.magic_header[<span class="tok-number">0</span>..], BitmapMagicHeader[<span class="tok-number">0</span>..])) {</span>
<span class="line" id="L286"> <span class="tok-kw">return</span> Image.ReadError.InvalidData;</span>
<span class="line" id="L287"> }</span>
<span class="line" id="L288"></span>
<span class="line" id="L289"> <span class="tok-kw">const</span> header_size = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u32</span>, .little);</span>
<span class="line" id="L290"> <span class="tok-kw">try</span> buffered_stream.seekBy(-<span class="tok-builtin">@sizeOf</span>(<span class="tok-type">u32</span>));</span>
<span class="line" id="L291"></span>
<span class="line" id="L292"> <span class="tok-comment">// Read info header</span>
</span>
<span class="line" id="L293"> self.info_header = <span class="tok-kw">switch</span> (header_size) {</span>
<span class="line" id="L294"> BitmapInfoHeaderWindows31.HeaderSize =&gt; BitmapInfoHeader{ .windows31 = <span class="tok-kw">try</span> utils.readStruct(reader, BitmapInfoHeaderWindows31, .little) },</span>
<span class="line" id="L295"> BitmapInfoHeaderV4.HeaderSize =&gt; BitmapInfoHeader{ .v4 = <span class="tok-kw">try</span> utils.readStruct(reader, BitmapInfoHeaderV4, .little) },</span>
<span class="line" id="L296"> BitmapInfoHeaderV5.HeaderSize =&gt; BitmapInfoHeader{ .v5 = <span class="tok-kw">try</span> utils.readStruct(reader, BitmapInfoHeaderV5, .little) },</span>
<span class="line" id="L297"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> Image.Error.Unsupported,</span>
<span class="line" id="L298"> };</span>
<span class="line" id="L299"></span>
<span class="line" id="L300"> <span class="tok-kw">var</span> pixels: color.PixelStorage = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L301"></span>
<span class="line" id="L302"> <span class="tok-comment">// Read pixel data</span>
</span>
<span class="line" id="L303"> _ = <span class="tok-kw">switch</span> (self.info_header) {</span>
<span class="line" id="L304"> .v4 =&gt; |v4Header| {</span>
<span class="line" id="L305"> <span class="tok-kw">const</span> pixel_width = v4Header.width;</span>
<span class="line" id="L306"> <span class="tok-kw">const</span> pixel_height = v4Header.height;</span>
<span class="line" id="L307"> <span class="tok-kw">const</span> pixel_format = <span class="tok-kw">try</span> findPixelFormat(v4Header.bit_count, v4Header.compression_method);</span>
<span class="line" id="L308"></span>
<span class="line" id="L309"> pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, <span class="tok-builtin">@intCast</span>(pixel_width * pixel_height));</span>
<span class="line" id="L310"> <span class="tok-kw">errdefer</span> pixels.deinit(allocator);</span>
<span class="line" id="L311"></span>
<span class="line" id="L312"> <span class="tok-kw">try</span> readPixels(reader, pixel_width, pixel_height, &amp;pixels);</span>
<span class="line" id="L313"> },</span>
<span class="line" id="L314"> .v5 =&gt; |v5Header| {</span>
<span class="line" id="L315"> <span class="tok-kw">const</span> pixel_width = v5Header.width;</span>
<span class="line" id="L316"> <span class="tok-kw">const</span> pixel_height = v5Header.height;</span>
<span class="line" id="L317"> <span class="tok-kw">const</span> pixel_format = <span class="tok-kw">try</span> findPixelFormat(v5Header.bit_count, v5Header.compression_method);</span>
<span class="line" id="L318"></span>
<span class="line" id="L319"> pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, <span class="tok-builtin">@intCast</span>(pixel_width * pixel_height));</span>
<span class="line" id="L320"> <span class="tok-kw">errdefer</span> pixels.deinit(allocator);</span>
<span class="line" id="L321"></span>
<span class="line" id="L322"> <span class="tok-kw">try</span> readPixels(reader, pixel_width, pixel_height, &amp;pixels);</span>
<span class="line" id="L323"> },</span>
<span class="line" id="L324"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> Image.Error.Unsupported,</span>
<span class="line" id="L325"> };</span>
<span class="line" id="L326"></span>
<span class="line" id="L327"> <span class="tok-kw">return</span> pixels;</span>
<span class="line" id="L328"> }</span>
<span class="line" id="L329"></span>
<span class="line" id="L330"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: BMP, stream: *Image.Stream, pixels: color.PixelStorage) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L331"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);</span>
<span class="line" id="L332"></span>
<span class="line" id="L333"> <span class="tok-kw">const</span> writer = buffered_stream.writer();</span>
<span class="line" id="L334"></span>
<span class="line" id="L335"> <span class="tok-kw">try</span> utils.writeStruct(writer, self.file_header, .little);</span>
<span class="line" id="L336"></span>
<span class="line" id="L337"> <span class="tok-kw">switch</span> (self.info_header) {</span>
<span class="line" id="L338"> .v4 =&gt; |v4| {</span>
<span class="line" id="L339"> <span class="tok-kw">try</span> utils.writeStruct(writer, v4, .little);</span>
<span class="line" id="L340"> },</span>
<span class="line" id="L341"> .v5 =&gt; |v5| {</span>
<span class="line" id="L342"> <span class="tok-kw">try</span> utils.writeStruct(writer, v5, .little);</span>
<span class="line" id="L343"> },</span>
<span class="line" id="L344"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L345"> <span class="tok-kw">return</span> Image.WriteError.InvalidData;</span>
<span class="line" id="L346"> },</span>
<span class="line" id="L347"> }</span>
<span class="line" id="L348"></span>
<span class="line" id="L349"> <span class="tok-kw">try</span> writePixels(writer, pixels, self.width(), self.height());</span>
<span class="line" id="L350"></span>
<span class="line" id="L351"> <span class="tok-kw">try</span> buffered_stream.flush();</span>
<span class="line" id="L352"> }</span>
<span class="line" id="L353"></span>
<span class="line" id="L354"> <span class="tok-kw">fn</span> <span class="tok-fn">findPixelFormat</span>(bit_count: <span class="tok-type">u32</span>, compression: CompressionMethod) Image.Error!PixelFormat {</span>
<span class="line" id="L355"> <span class="tok-kw">if</span> (bit_count == <span class="tok-number">32</span> <span class="tok-kw">and</span> compression == CompressionMethod.bitfields) {</span>
<span class="line" id="L356"> <span class="tok-kw">return</span> PixelFormat.bgra32;</span>
<span class="line" id="L357"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (bit_count == <span class="tok-number">24</span> <span class="tok-kw">and</span> compression == CompressionMethod.none) {</span>
<span class="line" id="L358"> <span class="tok-kw">return</span> PixelFormat.bgr24;</span>
<span class="line" id="L359"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L360"> <span class="tok-kw">return</span> Image.Error.Unsupported;</span>
<span class="line" id="L361"> }</span>
<span class="line" id="L362"> }</span>
<span class="line" id="L363"></span>
<span class="line" id="L364"> <span class="tok-kw">fn</span> <span class="tok-fn">readPixels</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixel_width: <span class="tok-type">i32</span>, pixel_height: <span class="tok-type">i32</span>, pixels: *color.PixelStorage) Image.ReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L365"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (pixels.*) {</span>
<span class="line" id="L366"> .bgr24 =&gt; {</span>
<span class="line" id="L367"> <span class="tok-kw">return</span> readPixelsInternal(pixels.bgr24, reader, pixel_width, pixel_height);</span>
<span class="line" id="L368"> },</span>
<span class="line" id="L369"> .bgra32 =&gt; {</span>
<span class="line" id="L370"> <span class="tok-kw">return</span> readPixelsInternal(pixels.bgra32, reader, pixel_width, pixel_height);</span>
<span class="line" id="L371"> },</span>
<span class="line" id="L372"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L373"> <span class="tok-kw">return</span> Image.Error.Unsupported;</span>
<span class="line" id="L374"> },</span>
<span class="line" id="L375"> };</span>
<span class="line" id="L376"> }</span>
<span class="line" id="L377"></span>
<span class="line" id="L378"> <span class="tok-kw">fn</span> <span class="tok-fn">readPixelsInternal</span>(pixels: <span class="tok-kw">anytype</span>, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixel_width: <span class="tok-type">i32</span>, pixel_height: <span class="tok-type">i32</span>) Image.ReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L379"> <span class="tok-kw">const</span> ColorBufferType = <span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(pixels)).Pointer.child;</span>
<span class="line" id="L380"></span>
<span class="line" id="L381"> <span class="tok-kw">var</span> x: <span class="tok-type">i32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L382"> <span class="tok-kw">var</span> y: <span class="tok-type">i32</span> = pixel_height - <span class="tok-number">1</span>;</span>
<span class="line" id="L383"> <span class="tok-kw">while</span> (y &gt;= <span class="tok-number">0</span>) : (y -= <span class="tok-number">1</span>) {</span>
<span class="line" id="L384"> <span class="tok-kw">const</span> scanline = y * pixel_width;</span>
<span class="line" id="L385"></span>
<span class="line" id="L386"> x = <span class="tok-number">0</span>;</span>
<span class="line" id="L387"> <span class="tok-kw">while</span> (x &lt; pixel_width) : (x += <span class="tok-number">1</span>) {</span>
<span class="line" id="L388"> pixels[<span class="tok-builtin">@intCast</span>(scanline + x)] = <span class="tok-kw">try</span> utils.readStruct(reader, ColorBufferType, .little);</span>
<span class="line" id="L389"> }</span>
<span class="line" id="L390"> }</span>
<span class="line" id="L391"> }</span>
<span class="line" id="L392"></span>
<span class="line" id="L393"> <span class="tok-kw">fn</span> <span class="tok-fn">writePixels</span>(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: color.PixelStorage, pixel_width: <span class="tok-type">i32</span>, pixel_height: <span class="tok-type">i32</span>) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L394"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L395"> .bgr24 =&gt; {</span>
<span class="line" id="L396"> <span class="tok-kw">return</span> writePixelsInternal(pixels.bgr24, writer, pixel_width, pixel_height);</span>
<span class="line" id="L397"> },</span>
<span class="line" id="L398"> .bgra32 =&gt; {</span>
<span class="line" id="L399"> <span class="tok-kw">return</span> writePixelsInternal(pixels.bgra32, writer, pixel_width, pixel_height);</span>
<span class="line" id="L400"> },</span>
<span class="line" id="L401"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L402"> <span class="tok-kw">return</span> Image.WriteError.InvalidData;</span>
<span class="line" id="L403"> },</span>
<span class="line" id="L404"> };</span>
<span class="line" id="L405"> }</span>
<span class="line" id="L406"></span>
<span class="line" id="L407"> <span class="tok-kw">fn</span> <span class="tok-fn">writePixelsInternal</span>(pixels: <span class="tok-kw">anytype</span>, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixel_width: <span class="tok-type">i32</span>, pixel_height: <span class="tok-type">i32</span>) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L408"> <span class="tok-kw">var</span> x: <span class="tok-type">i32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L409"> <span class="tok-kw">var</span> y: <span class="tok-type">i32</span> = pixel_height - <span class="tok-number">1</span>;</span>
<span class="line" id="L410"> <span class="tok-kw">while</span> (y &gt;= <span class="tok-number">0</span>) : (y -= <span class="tok-number">1</span>) {</span>
<span class="line" id="L411"> <span class="tok-kw">const</span> scanline = y * pixel_width;</span>
<span class="line" id="L412"></span>
<span class="line" id="L413"> x = <span class="tok-number">0</span>;</span>
<span class="line" id="L414"> <span class="tok-kw">while</span> (x &lt; pixel_width) : (x += <span class="tok-number">1</span>) {</span>
<span class="line" id="L415"> <span class="tok-kw">try</span> utils.writeStruct(writer, pixels[<span class="tok-builtin">@intCast</span>(scanline + x)], .little);</span>
<span class="line" id="L416"> }</span>
<span class="line" id="L417"> }</span>
<span class="line" id="L418"> }</span>
<span class="line" id="L419">};</span>
<span class="line" id="L420"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,366 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> ImageError = Image.Error;</span>
<span class="line" id="L7"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L8"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L11"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L12"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> FrameHeader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/FrameHeader.zig&quot;</span>);</span>
<span class="line" id="L15"><span class="tok-kw">const</span> JFIFHeader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/JFIFHeader.zig&quot;</span>);</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-kw">const</span> Markers = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/utils.zig&quot;</span>).Markers;</span>
<span class="line" id="L18"><span class="tok-kw">const</span> ZigzagOffsets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/utils.zig&quot;</span>).ZigzagOffsets;</span>
<span class="line" id="L19"><span class="tok-kw">const</span> IDCTMultipliers = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/utils.zig&quot;</span>).IDCTMultipliers;</span>
<span class="line" id="L20"><span class="tok-kw">const</span> QuantizationTable = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/quantization.zig&quot;</span>).Table;</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-kw">const</span> HuffmanReader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/huffman.zig&quot;</span>).Reader;</span>
<span class="line" id="L23"><span class="tok-kw">const</span> HuffmanTable = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/huffman.zig&quot;</span>).Table;</span>
<span class="line" id="L24"><span class="tok-kw">const</span> Frame = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/Frame.zig&quot;</span>);</span>
<span class="line" id="L25"><span class="tok-kw">const</span> Scan = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./jpeg/Scan.zig&quot;</span>);</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"><span class="tok-comment">// TODO: Chroma subsampling</span>
</span>
<span class="line" id="L28"><span class="tok-comment">// TODO: Progressive scans</span>
</span>
<span class="line" id="L29"><span class="tok-comment">// TODO: Non-baseline sequential DCT</span>
</span>
<span class="line" id="L30"><span class="tok-comment">// TODO: Precisions other than 8-bit</span>
</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"><span class="tok-comment">// TODO: Hierarchical mode of JPEG compression.</span>
</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L35"></span>
<span class="line" id="L36"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> JPEG = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L37"> frame: ?Frame = <span class="tok-null">null</span>,</span>
<span class="line" id="L38"> allocator: Allocator,</span>
<span class="line" id="L39"> quantization_tables: [<span class="tok-number">4</span>]?QuantizationTable,</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: Allocator) JPEG {</span>
<span class="line" id="L42"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L43"> .allocator = allocator,</span>
<span class="line" id="L44"> .quantization_tables = [_]?QuantizationTable{<span class="tok-null">null</span>} ** <span class="tok-number">4</span>,</span>
<span class="line" id="L45"> };</span>
<span class="line" id="L46"> }</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *JPEG) <span class="tok-type">void</span> {</span>
<span class="line" id="L49"> <span class="tok-kw">if</span> (self.frame) |*frame| {</span>
<span class="line" id="L50"> frame.deinit();</span>
<span class="line" id="L51"> }</span>
<span class="line" id="L52"> }</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-kw">fn</span> <span class="tok-fn">parseDefineQuantizationTables</span>(self: *JPEG, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L55"> <span class="tok-kw">var</span> segment_size = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L56"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;DefineQuantizationTables: segment size = 0x{X}\n&quot;</span>, .{segment_size});</span>
<span class="line" id="L57"> segment_size -= <span class="tok-number">2</span>;</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"> <span class="tok-kw">while</span> (segment_size &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> precision_and_destination = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L61"> <span class="tok-kw">const</span> table_precision = precision_and_destination &gt;&gt; <span class="tok-number">4</span>;</span>
<span class="line" id="L62"> <span class="tok-kw">const</span> table_destination = precision_and_destination &amp; <span class="tok-number">0b11</span>;</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> <span class="tok-kw">const</span> quantization_table = <span class="tok-kw">try</span> QuantizationTable.read(table_precision, reader);</span>
<span class="line" id="L65"> <span class="tok-kw">switch</span> (quantization_table) {</span>
<span class="line" id="L66"> .q8 =&gt; segment_size -= <span class="tok-number">64</span> + <span class="tok-number">1</span>,</span>
<span class="line" id="L67"> .q16 =&gt; segment_size -= <span class="tok-number">128</span> + <span class="tok-number">1</span>,</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> self.quantization_tables[table_destination] = quantization_table;</span>
<span class="line" id="L71"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot; Table with precision {} installed at {}\n&quot;</span>, .{ table_precision, table_destination });</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">fn</span> <span class="tok-fn">parseScan</span>(self: *JPEG, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixels_opt: *?color.PixelStorage) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L76"> <span class="tok-kw">if</span> (self.frame) |frame| {</span>
<span class="line" id="L77"> <span class="tok-kw">try</span> Scan.performScan(&amp;frame, reader, pixels_opt);</span>
<span class="line" id="L78"> } <span class="tok-kw">else</span> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L79"> }</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"> <span class="tok-kw">fn</span> <span class="tok-fn">initializePixels</span>(self: *JPEG, pixels_opt: *?color.PixelStorage) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">if</span> (self.frame) |frame| {</span>
<span class="line" id="L83"> <span class="tok-kw">var</span> pixel_format: PixelFormat = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L84"> <span class="tok-kw">switch</span> (frame.frame_header.components.len) {</span>
<span class="line" id="L85"> <span class="tok-number">1</span> =&gt; pixel_format = .grayscale8,</span>
<span class="line" id="L86"> <span class="tok-number">3</span> =&gt; pixel_format = .rgb24,</span>
<span class="line" id="L87"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L88"> }</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> <span class="tok-kw">const</span> pixel_count = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(frame.frame_header.samples_per_row)) * <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(frame.frame_header.row_count));</span>
<span class="line" id="L91"> pixels_opt.* = <span class="tok-kw">try</span> color.PixelStorage.init(self.allocator, pixel_format, pixel_count);</span>
<span class="line" id="L92"> } <span class="tok-kw">else</span> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L93"> }</span>
<span class="line" id="L94"></span>
<span class="line" id="L95"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *JPEG, stream: *Image.Stream, pixels_opt: *?color.PixelStorage) ImageReadError!Frame {</span>
<span class="line" id="L96"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L97"></span>
<span class="line" id="L98"> <span class="tok-kw">const</span> jfif_header = JFIFHeader.read(&amp;buffered_stream) <span class="tok-kw">catch</span> |err| <span class="tok-kw">switch</span> (err) {</span>
<span class="line" id="L99"> <span class="tok-kw">error</span>.App0MarkerDoesNotExist, <span class="tok-kw">error</span>.JfifIdentifierNotSet, <span class="tok-kw">error</span>.ThumbnailImagesUnsupported, <span class="tok-kw">error</span>.ExtraneousApplicationMarker =&gt; <span class="tok-kw">return</span> ImageReadError.InvalidData,</span>
<span class="line" id="L100"> <span class="tok-kw">else</span> =&gt; |e| <span class="tok-kw">return</span> e,</span>
<span class="line" id="L101"> };</span>
<span class="line" id="L102"> _ = jfif_header;</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"> <span class="tok-kw">errdefer</span> {</span>
<span class="line" id="L105"> <span class="tok-kw">if</span> (pixels_opt.*) |pixels| {</span>
<span class="line" id="L106"> pixels.deinit(self.allocator);</span>
<span class="line" id="L107"> pixels_opt.* = <span class="tok-null">null</span>;</span>
<span class="line" id="L108"> }</span>
<span class="line" id="L109"> }</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L112"> <span class="tok-kw">var</span> marker = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L113"> <span class="tok-kw">while</span> (marker != <span class="tok-builtin">@intFromEnum</span>(Markers.end_of_image)) : (marker = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big)) {</span>
<span class="line" id="L114"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;Parsing marker value: 0x{X}\n&quot;</span>, .{marker});</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-kw">if</span> (marker &gt;= <span class="tok-builtin">@intFromEnum</span>(Markers.application0) <span class="tok-kw">and</span> marker &lt; <span class="tok-builtin">@intFromEnum</span>(Markers.application0) + <span class="tok-number">16</span>) {</span>
<span class="line" id="L117"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;Skipping application data segment\n&quot;</span>, .{});</span>
<span class="line" id="L118"> <span class="tok-kw">const</span> application_data_length = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L119"> <span class="tok-kw">try</span> buffered_stream.seekBy(application_data_length - <span class="tok-number">2</span>);</span>
<span class="line" id="L120"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L121"> }</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@as</span>(Markers, <span class="tok-builtin">@enumFromInt</span>(marker))) {</span>
<span class="line" id="L124"> <span class="tok-comment">// TODO(angelo): this should be moved inside the frameheader, it's part of thet</span>
</span>
<span class="line" id="L125"> <span class="tok-comment">// and then the header just dispatches correctly what to do with it.</span>
</span>
<span class="line" id="L126"> <span class="tok-comment">// JPEG should be as clear as possible</span>
</span>
<span class="line" id="L127"> .sof0 =&gt; { <span class="tok-comment">// Baseline DCT</span>
</span>
<span class="line" id="L128"> <span class="tok-kw">if</span> (self.frame != <span class="tok-null">null</span>) {</span>
<span class="line" id="L129"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L130"> }</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> self.frame = <span class="tok-kw">try</span> Frame.read(self.allocator, &amp;self.quantization_tables, &amp;buffered_stream);</span>
<span class="line" id="L133"> },</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"> .sof1 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// extended sequential DCT Huffman coding</span>
</span>
<span class="line" id="L136"> .sof2 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// progressive DCT Huffman coding</span>
</span>
<span class="line" id="L137"> .sof3 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// lossless (sequential) Huffman coding</span>
</span>
<span class="line" id="L138"> .sof5 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L139"> .sof6 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L140"> .sof7 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L141"> .sof9 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// extended sequential DCT arithmetic coding</span>
</span>
<span class="line" id="L142"> .sof10 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// progressive DCT arithmetic coding</span>
</span>
<span class="line" id="L143"> .sof11 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported, <span class="tok-comment">// lossless (sequential) arithmetic coding</span>
</span>
<span class="line" id="L144"> .sof13 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L145"> .sof14 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L146"> .sof15 =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> .start_of_scan =&gt; {</span>
<span class="line" id="L149"> <span class="tok-kw">try</span> self.initializePixels(pixels_opt);</span>
<span class="line" id="L150"> <span class="tok-kw">try</span> self.parseScan(reader, pixels_opt);</span>
<span class="line" id="L151"> },</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"> .define_quantization_tables =&gt; {</span>
<span class="line" id="L154"> <span class="tok-kw">try</span> self.parseDefineQuantizationTables(reader);</span>
<span class="line" id="L155"> },</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"> .comment =&gt; {</span>
<span class="line" id="L158"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;Skipping comment segment\n&quot;</span>, .{});</span>
<span class="line" id="L159"></span>
<span class="line" id="L160"> <span class="tok-kw">const</span> comment_length = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L161"> <span class="tok-kw">try</span> buffered_stream.seekBy(comment_length - <span class="tok-number">2</span>);</span>
<span class="line" id="L162"> },</span>
<span class="line" id="L163"></span>
<span class="line" id="L164"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L165"> <span class="tok-comment">// TODO(angelo): raise invalid marker, more precise error.</span>
</span>
<span class="line" id="L166"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L167"> },</span>
<span class="line" id="L168"> }</span>
<span class="line" id="L169"> }</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (self.frame) |frame| frame <span class="tok-kw">else</span> ImageReadError.InvalidData;</span>
<span class="line" id="L172"> }</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> <span class="tok-comment">// Format interface</span>
</span>
<span class="line" id="L175"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L176"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L177"> .format = format,</span>
<span class="line" id="L178"> .formatDetect = formatDetect,</span>
<span class="line" id="L179"> .readImage = readImage,</span>
<span class="line" id="L180"> .writeImage = writeImage,</span>
<span class="line" id="L181"> };</span>
<span class="line" id="L182"> }</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L185"> <span class="tok-kw">return</span> Image.Format.jpg;</span>
<span class="line" id="L186"> }</span>
<span class="line" id="L187"></span>
<span class="line" id="L188"> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L189"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L190"></span>
<span class="line" id="L191"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L192"> <span class="tok-kw">const</span> maybe_start_of_image = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L193"> <span class="tok-kw">if</span> (maybe_start_of_image != <span class="tok-builtin">@intFromEnum</span>(Markers.start_of_image)) {</span>
<span class="line" id="L194"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L195"> }</span>
<span class="line" id="L196"></span>
<span class="line" id="L197"> <span class="tok-kw">try</span> buffered_stream.seekTo(<span class="tok-number">6</span>);</span>
<span class="line" id="L198"> <span class="tok-kw">var</span> identifier_buffer: [<span class="tok-number">4</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L199"> _ = <span class="tok-kw">try</span> buffered_stream.read(identifier_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L200"></span>
<span class="line" id="L201"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, identifier_buffer[<span class="tok-number">0</span>..], <span class="tok-str">&quot;JFIF&quot;</span>);</span>
<span class="line" id="L202"> }</span>
<span class="line" id="L203"></span>
<span class="line" id="L204"> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L205"> <span class="tok-kw">var</span> result = Image.init(allocator);</span>
<span class="line" id="L206"> <span class="tok-kw">errdefer</span> result.deinit();</span>
<span class="line" id="L207"> <span class="tok-kw">var</span> jpeg = JPEG.init(allocator);</span>
<span class="line" id="L208"> <span class="tok-kw">defer</span> jpeg.deinit();</span>
<span class="line" id="L209"></span>
<span class="line" id="L210"> <span class="tok-kw">var</span> pixels_opt: ?color.PixelStorage = <span class="tok-null">null</span>;</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">const</span> frame = <span class="tok-kw">try</span> jpeg.read(stream, &amp;pixels_opt);</span>
<span class="line" id="L213"></span>
<span class="line" id="L214"> result.width = frame.frame_header.samples_per_row;</span>
<span class="line" id="L215"> result.height = frame.frame_header.row_count;</span>
<span class="line" id="L216"></span>
<span class="line" id="L217"> <span class="tok-kw">if</span> (pixels_opt) |pixels| {</span>
<span class="line" id="L218"> result.pixels = pixels;</span>
<span class="line" id="L219"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L220"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L221"> }</span>
<span class="line" id="L222"></span>
<span class="line" id="L223"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L224"> }</span>
<span class="line" id="L225"></span>
<span class="line" id="L226"> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L227"> _ = allocator;</span>
<span class="line" id="L228"> _ = write_stream;</span>
<span class="line" id="L229"> _ = image;</span>
<span class="line" id="L230"> _ = encoder_options;</span>
<span class="line" id="L231"> }</span>
<span class="line" id="L232">};</span>
<span class="line" id="L233"></span>
</code></pre></body>
</html>

View file

@ -1,375 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/Frame.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> Markers = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).Markers;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> FrameHeader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;FrameHeader.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> QuantizationTable = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;quantization.zig&quot;</span>).Table;</span>
<span class="line" id="L11"><span class="tok-kw">const</span> HuffmanTable = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;huffman.zig&quot;</span>).Table;</span>
<span class="line" id="L12"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../color.zig&quot;</span>);</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> IDCTMultipliers = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).IDCTMultipliers;</span>
<span class="line" id="L15"><span class="tok-kw">const</span> MAX_COMPONENTS = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MAX_COMPONENTS;</span>
<span class="line" id="L16"><span class="tok-kw">const</span> MAX_BLOCKS = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MAX_BLOCKS;</span>
<span class="line" id="L17"><span class="tok-kw">const</span> MCU = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MCU;</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L20">allocator: Allocator,</span>
<span class="line" id="L21">frame_header: FrameHeader,</span>
<span class="line" id="L22">quantization_tables: *[<span class="tok-number">4</span>]?QuantizationTable,</span>
<span class="line" id="L23">dc_huffman_tables: [<span class="tok-number">2</span>]?HuffmanTable,</span>
<span class="line" id="L24">ac_huffman_tables: [<span class="tok-number">2</span>]?HuffmanTable,</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(allocator: Allocator, quantization_tables: *[<span class="tok-number">4</span>]?QuantizationTable, buffered_stream: *buffered_stream_source.DefaultBufferedStreamSourceReader) ImageReadError!Self {</span>
<span class="line" id="L29"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L30"> <span class="tok-kw">const</span> frame_header = <span class="tok-kw">try</span> FrameHeader.read(allocator, reader);</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"> <span class="tok-kw">var</span> self = Self{</span>
<span class="line" id="L33"> .allocator = allocator,</span>
<span class="line" id="L34"> .frame_header = frame_header,</span>
<span class="line" id="L35"> .quantization_tables = quantization_tables,</span>
<span class="line" id="L36"> .dc_huffman_tables = [_]?HuffmanTable{<span class="tok-null">null</span>} ** <span class="tok-number">2</span>,</span>
<span class="line" id="L37"> .ac_huffman_tables = [_]?HuffmanTable{<span class="tok-null">null</span>} ** <span class="tok-number">2</span>,</span>
<span class="line" id="L38"> };</span>
<span class="line" id="L39"> <span class="tok-kw">errdefer</span> self.deinit();</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">var</span> marker = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L42"> <span class="tok-kw">while</span> (marker != <span class="tok-builtin">@intFromEnum</span>(Markers.start_of_scan)) : (marker = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big)) {</span>
<span class="line" id="L43"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;Frame: Parsing marker value: 0x{X}\n&quot;</span>, .{marker});</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@as</span>(Markers, <span class="tok-builtin">@enumFromInt</span>(marker))) {</span>
<span class="line" id="L46"> .define_huffman_tables =&gt; {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> self.parseDefineHuffmanTables(reader);</span>
<span class="line" id="L48"> },</span>
<span class="line" id="L49"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L50"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L51"> },</span>
<span class="line" id="L52"> }</span>
<span class="line" id="L53"> }</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"> <span class="tok-comment">// Undo the last marker read</span>
</span>
<span class="line" id="L56"> <span class="tok-kw">try</span> buffered_stream.seekBy(-<span class="tok-number">2</span>);</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"> <span class="tok-kw">return</span> self;</span>
<span class="line" id="L59">}</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L62"> <span class="tok-kw">for</span> (&amp;self.dc_huffman_tables) |*maybe_huffman_table| {</span>
<span class="line" id="L63"> <span class="tok-kw">if</span> (maybe_huffman_table.*) |*huffman_table| {</span>
<span class="line" id="L64"> huffman_table.deinit();</span>
<span class="line" id="L65"> }</span>
<span class="line" id="L66"> }</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> <span class="tok-kw">for</span> (&amp;self.ac_huffman_tables) |*maybe_huffman_table| {</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (maybe_huffman_table.*) |*huffman_table| {</span>
<span class="line" id="L70"> huffman_table.deinit();</span>
<span class="line" id="L71"> }</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"> self.frame_header.deinit();</span>
<span class="line" id="L75">}</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"><span class="tok-kw">fn</span> <span class="tok-fn">parseDefineHuffmanTables</span>(self: *Self, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L78"> <span class="tok-kw">var</span> segment_size = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L79"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;DefineHuffmanTables: segment size = 0x{X}\n&quot;</span>, .{segment_size});</span>
<span class="line" id="L80"> segment_size -= <span class="tok-number">2</span>;</span>
<span class="line" id="L81"></span>
<span class="line" id="L82"> <span class="tok-kw">while</span> (segment_size &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L83"> <span class="tok-kw">const</span> class_and_destination = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L84"> <span class="tok-kw">const</span> table_class = class_and_destination &gt;&gt; <span class="tok-number">4</span>;</span>
<span class="line" id="L85"> <span class="tok-kw">const</span> table_destination = class_and_destination &amp; <span class="tok-number">0b1</span>;</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> <span class="tok-kw">const</span> huffman_table = <span class="tok-kw">try</span> HuffmanTable.read(self.allocator, table_class, reader);</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"> <span class="tok-kw">if</span> (table_class == <span class="tok-number">0</span>) {</span>
<span class="line" id="L90"> <span class="tok-kw">if</span> (self.dc_huffman_tables[table_destination]) |*old_huffman_table| {</span>
<span class="line" id="L91"> old_huffman_table.deinit();</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"> self.dc_huffman_tables[table_destination] = huffman_table;</span>
<span class="line" id="L94"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (self.ac_huffman_tables[table_destination]) |*old_huffman_table| {</span>
<span class="line" id="L96"> old_huffman_table.deinit();</span>
<span class="line" id="L97"> }</span>
<span class="line" id="L98"> self.ac_huffman_tables[table_destination] = huffman_table;</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"></span>
<span class="line" id="L101"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot; Table with class {} installed at {}\n&quot;</span>, .{ table_class, table_destination });</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"> <span class="tok-comment">// Class+Destination + code counts + code table</span>
</span>
<span class="line" id="L104"> segment_size -= <span class="tok-number">1</span> + <span class="tok-number">16</span> + <span class="tok-builtin">@as</span>(<span class="tok-type">u16</span>, <span class="tok-builtin">@intCast</span>(huffman_table.code_map.count()));</span>
<span class="line" id="L105"> }</span>
<span class="line" id="L106">}</span>
<span class="line" id="L107"></span>
<span class="line" id="L108"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">renderToPixels</span>(self: *<span class="tok-kw">const</span> Self, mcu_storage: *[MAX_COMPONENTS][MAX_BLOCKS]MCU, mcu_id: <span class="tok-type">usize</span>, pixels: *color.PixelStorage) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L109"> <span class="tok-kw">switch</span> (self.frame_header.components.len) {</span>
<span class="line" id="L110"> <span class="tok-number">1</span> =&gt; <span class="tok-kw">try</span> self.renderToPixelsGrayscale(&amp;mcu_storage[<span class="tok-number">0</span>][<span class="tok-number">0</span>], mcu_id, pixels.grayscale8), <span class="tok-comment">// Grayscale images is non-interleaved</span>
</span>
<span class="line" id="L111"> <span class="tok-number">3</span> =&gt; <span class="tok-kw">try</span> self.renderToPixelsRgb(mcu_storage, mcu_id, pixels.rgb24),</span>
<span class="line" id="L112"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114">}</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"><span class="tok-kw">fn</span> <span class="tok-fn">renderToPixelsGrayscale</span>(self: *<span class="tok-kw">const</span> Self, mcu_storage: *MCU, mcu_id: <span class="tok-type">usize</span>, pixels: []color.Grayscale8) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L117"> <span class="tok-kw">const</span> mcu_width = <span class="tok-number">8</span>;</span>
<span class="line" id="L118"> <span class="tok-kw">const</span> mcu_height = <span class="tok-number">8</span>;</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> width = self.frame_header.samples_per_row;</span>
<span class="line" id="L120"> <span class="tok-kw">const</span> height = pixels.len / width;</span>
<span class="line" id="L121"> <span class="tok-kw">const</span> mcus_per_row = (width + mcu_width - <span class="tok-number">1</span>) / mcu_width;</span>
<span class="line" id="L122"> <span class="tok-kw">const</span> mcu_origin_x = (mcu_id % mcus_per_row) * mcu_width;</span>
<span class="line" id="L123"> <span class="tok-kw">const</span> mcu_origin_y = (mcu_id / mcus_per_row) * mcu_height;</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..mcu_height) |mcu_y| {</span>
<span class="line" id="L126"> <span class="tok-kw">const</span> y = mcu_origin_y + mcu_y;</span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (y &gt;= height) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"> <span class="tok-comment">// y coordinates in the block</span>
</span>
<span class="line" id="L130"> <span class="tok-kw">const</span> block_y = mcu_y % <span class="tok-number">8</span>;</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> <span class="tok-kw">const</span> stride = y * width;</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..mcu_width) |mcu_x| {</span>
<span class="line" id="L135"> <span class="tok-kw">const</span> x = mcu_origin_x + mcu_x;</span>
<span class="line" id="L136"> <span class="tok-kw">if</span> (x &gt;= width) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"> <span class="tok-comment">// x coordinates in the block</span>
</span>
<span class="line" id="L139"> <span class="tok-kw">const</span> block_x = mcu_x % <span class="tok-number">8</span>;</span>
<span class="line" id="L140"></span>
<span class="line" id="L141"> <span class="tok-kw">const</span> reconstructed_Y = idct(mcu_storage, <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(block_x)), <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(block_y)), mcu_id, <span class="tok-number">0</span>);</span>
<span class="line" id="L142"> <span class="tok-kw">const</span> Y: <span class="tok-type">f32</span> = <span class="tok-builtin">@floatFromInt</span>(reconstructed_Y);</span>
<span class="line" id="L143"> pixels[stride + x] = .{</span>
<span class="line" id="L144"> .value = <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intFromFloat</span>(std.math.clamp(Y + <span class="tok-number">128.0</span>, <span class="tok-number">0.0</span>, <span class="tok-number">255.0</span>))),</span>
<span class="line" id="L145"> };</span>
<span class="line" id="L146"> }</span>
<span class="line" id="L147"> }</span>
<span class="line" id="L148">}</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"><span class="tok-kw">fn</span> <span class="tok-fn">renderToPixelsRgb</span>(self: *<span class="tok-kw">const</span> Self, mcu_storage: *[MAX_COMPONENTS][MAX_BLOCKS]MCU, mcu_id: <span class="tok-type">usize</span>, pixels: []color.Rgb24) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L151"> <span class="tok-kw">const</span> max_horizontal_sampling_factor = self.frame_header.getMaxHorizontalSamplingFactor();</span>
<span class="line" id="L152"> <span class="tok-kw">const</span> max_vertical_sampling_factor = self.frame_header.getMaxVerticalSamplingFactor();</span>
<span class="line" id="L153"> <span class="tok-kw">const</span> mcu_width = <span class="tok-number">8</span> * max_horizontal_sampling_factor;</span>
<span class="line" id="L154"> <span class="tok-kw">const</span> mcu_height = <span class="tok-number">8</span> * max_vertical_sampling_factor;</span>
<span class="line" id="L155"> <span class="tok-kw">const</span> width = self.frame_header.samples_per_row;</span>
<span class="line" id="L156"> <span class="tok-kw">const</span> height = pixels.len / width;</span>
<span class="line" id="L157"> <span class="tok-kw">const</span> mcus_per_row = (width + mcu_width - <span class="tok-number">1</span>) / mcu_width;</span>
<span class="line" id="L158"></span>
<span class="line" id="L159"> <span class="tok-kw">const</span> mcu_origin_x = (mcu_id % mcus_per_row) * mcu_width;</span>
<span class="line" id="L160"> <span class="tok-kw">const</span> mcu_origin_y = (mcu_id / mcus_per_row) * mcu_height;</span>
<span class="line" id="L161"></span>
<span class="line" id="L162"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..mcu_height) |mcu_y| {</span>
<span class="line" id="L163"> <span class="tok-kw">const</span> y = mcu_origin_y + mcu_y;</span>
<span class="line" id="L164"> <span class="tok-kw">if</span> (y &gt;= height) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L165"></span>
<span class="line" id="L166"> <span class="tok-comment">// y coordinates of each component applied to the sampling factor</span>
</span>
<span class="line" id="L167"> <span class="tok-kw">const</span> y_sampled_y = (mcu_y * self.frame_header.components[<span class="tok-number">0</span>].vertical_sampling_factor) / max_vertical_sampling_factor;</span>
<span class="line" id="L168"> <span class="tok-kw">const</span> cb_sampled_y = (mcu_y * self.frame_header.components[<span class="tok-number">1</span>].vertical_sampling_factor) / max_vertical_sampling_factor;</span>
<span class="line" id="L169"> <span class="tok-kw">const</span> cr_sampled_y = (mcu_y * self.frame_header.components[<span class="tok-number">2</span>].vertical_sampling_factor) / max_vertical_sampling_factor;</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-comment">// y coordinates of each component in the block</span>
</span>
<span class="line" id="L172"> <span class="tok-kw">const</span> y_block_y = y_sampled_y % <span class="tok-number">8</span>;</span>
<span class="line" id="L173"> <span class="tok-kw">const</span> cb_block_y = cb_sampled_y % <span class="tok-number">8</span>;</span>
<span class="line" id="L174"> <span class="tok-kw">const</span> cr_block_y = cr_sampled_y % <span class="tok-number">8</span>;</span>
<span class="line" id="L175"></span>
<span class="line" id="L176"> <span class="tok-kw">const</span> stride = y * width;</span>
<span class="line" id="L177"></span>
<span class="line" id="L178"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..mcu_width) |mcu_x| {</span>
<span class="line" id="L179"> <span class="tok-kw">const</span> x = mcu_origin_x + mcu_x;</span>
<span class="line" id="L180"> <span class="tok-kw">if</span> (x &gt;= width) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L181"></span>
<span class="line" id="L182"> <span class="tok-comment">// x coordinates of each component applied to the sampling factor</span>
</span>
<span class="line" id="L183"> <span class="tok-kw">const</span> y_sampled_x = (mcu_x * self.frame_header.components[<span class="tok-number">0</span>].horizontal_sampling_factor) / max_horizontal_sampling_factor;</span>
<span class="line" id="L184"> <span class="tok-kw">const</span> cb_sampled_x = (mcu_x * self.frame_header.components[<span class="tok-number">1</span>].horizontal_sampling_factor) / max_horizontal_sampling_factor;</span>
<span class="line" id="L185"> <span class="tok-kw">const</span> cr_sampled_x = (mcu_x * self.frame_header.components[<span class="tok-number">2</span>].horizontal_sampling_factor) / max_horizontal_sampling_factor;</span>
<span class="line" id="L186"></span>
<span class="line" id="L187"> <span class="tok-comment">// x coordinates of each component in the block</span>
</span>
<span class="line" id="L188"> <span class="tok-kw">const</span> y_block_x = y_sampled_x % <span class="tok-number">8</span>;</span>
<span class="line" id="L189"> <span class="tok-kw">const</span> cb_block_x = cb_sampled_x % <span class="tok-number">8</span>;</span>
<span class="line" id="L190"> <span class="tok-kw">const</span> cr_block_x = cr_sampled_x % <span class="tok-number">8</span>;</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> <span class="tok-kw">const</span> y_block_ind = (y_sampled_y / <span class="tok-number">8</span>) * self.frame_header.components[<span class="tok-number">0</span>].horizontal_sampling_factor + (y_sampled_x / <span class="tok-number">8</span>);</span>
<span class="line" id="L193"> <span class="tok-kw">const</span> cb_block_ind = (cb_sampled_y / <span class="tok-number">8</span>) * self.frame_header.components[<span class="tok-number">1</span>].horizontal_sampling_factor + (cb_sampled_x / <span class="tok-number">8</span>);</span>
<span class="line" id="L194"> <span class="tok-kw">const</span> cr_block_ind = (cr_sampled_y / <span class="tok-number">8</span>) * self.frame_header.components[<span class="tok-number">2</span>].horizontal_sampling_factor + (cr_sampled_x / <span class="tok-number">8</span>);</span>
<span class="line" id="L195"></span>
<span class="line" id="L196"> <span class="tok-kw">const</span> mcu_Y = &amp;mcu_storage[<span class="tok-number">0</span>][y_block_ind];</span>
<span class="line" id="L197"> <span class="tok-kw">const</span> mcu_Cb = &amp;mcu_storage[<span class="tok-number">1</span>][cb_block_ind];</span>
<span class="line" id="L198"> <span class="tok-kw">const</span> mcu_Cr = &amp;mcu_storage[<span class="tok-number">2</span>][cr_block_ind];</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"> <span class="tok-kw">const</span> reconstructed_Y = idct(mcu_Y, <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(y_block_x)), <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(y_block_y)), mcu_id, <span class="tok-number">0</span>);</span>
<span class="line" id="L201"> <span class="tok-kw">const</span> reconstructed_Cb = idct(mcu_Cb, <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(cb_block_x)), <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(cb_block_y)), mcu_id, <span class="tok-number">1</span>);</span>
<span class="line" id="L202"> <span class="tok-kw">const</span> reconstructed_Cr = idct(mcu_Cr, <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(cr_block_x)), <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(cr_block_y)), mcu_id, <span class="tok-number">2</span>);</span>
<span class="line" id="L203"></span>
<span class="line" id="L204"> <span class="tok-kw">const</span> Y: <span class="tok-type">f32</span> = <span class="tok-builtin">@floatFromInt</span>(reconstructed_Y);</span>
<span class="line" id="L205"> <span class="tok-kw">const</span> Cb: <span class="tok-type">f32</span> = <span class="tok-builtin">@floatFromInt</span>(reconstructed_Cb);</span>
<span class="line" id="L206"> <span class="tok-kw">const</span> Cr: <span class="tok-type">f32</span> = <span class="tok-builtin">@floatFromInt</span>(reconstructed_Cr);</span>
<span class="line" id="L207"></span>
<span class="line" id="L208"> <span class="tok-kw">const</span> Co_red = <span class="tok-number">0.299</span>;</span>
<span class="line" id="L209"> <span class="tok-kw">const</span> Co_green = <span class="tok-number">0.587</span>;</span>
<span class="line" id="L210"> <span class="tok-kw">const</span> Co_blue = <span class="tok-number">0.114</span>;</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">const</span> r = Cr * (<span class="tok-number">2</span> - <span class="tok-number">2</span> * Co_red) + Y;</span>
<span class="line" id="L213"> <span class="tok-kw">const</span> b = Cb * (<span class="tok-number">2</span> - <span class="tok-number">2</span> * Co_blue) + Y;</span>
<span class="line" id="L214"> <span class="tok-kw">const</span> g = (Y - Co_blue * b - Co_red * r) / Co_green;</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"> pixels[stride + x] = .{</span>
<span class="line" id="L217"> .r = <span class="tok-builtin">@intFromFloat</span>(std.math.clamp(r + <span class="tok-number">128.0</span>, <span class="tok-number">0.0</span>, <span class="tok-number">255.0</span>)),</span>
<span class="line" id="L218"> .g = <span class="tok-builtin">@intFromFloat</span>(std.math.clamp(g + <span class="tok-number">128.0</span>, <span class="tok-number">0.0</span>, <span class="tok-number">255.0</span>)),</span>
<span class="line" id="L219"> .b = <span class="tok-builtin">@intFromFloat</span>(std.math.clamp(b + <span class="tok-number">128.0</span>, <span class="tok-number">0.0</span>, <span class="tok-number">255.0</span>)),</span>
<span class="line" id="L220"> };</span>
<span class="line" id="L221"> }</span>
<span class="line" id="L222"> }</span>
<span class="line" id="L223">}</span>
<span class="line" id="L224"></span>
<span class="line" id="L225"><span class="tok-kw">fn</span> <span class="tok-fn">idct</span>(mcu: *<span class="tok-kw">const</span> MCU, x: <span class="tok-type">u3</span>, y: <span class="tok-type">u3</span>, mcu_id: <span class="tok-type">usize</span>, component_id: <span class="tok-type">usize</span>) <span class="tok-type">i8</span> {</span>
<span class="line" id="L226"> <span class="tok-comment">// TODO(angelo): if Ns &gt; 1 it is not interleaved, so the order this should be fixed...</span>
</span>
<span class="line" id="L227"> <span class="tok-comment">// FIXME is wrong for Ns &gt; 1</span>
</span>
<span class="line" id="L228"> <span class="tok-kw">var</span> reconstructed_pixel: <span class="tok-type">f32</span> = <span class="tok-number">0.0</span>;</span>
<span class="line" id="L229"></span>
<span class="line" id="L230"> <span class="tok-kw">var</span> u: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L231"> <span class="tok-kw">while</span> (u &lt; <span class="tok-number">8</span>) : (u += <span class="tok-number">1</span>) {</span>
<span class="line" id="L232"> <span class="tok-kw">var</span> v: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L233"> <span class="tok-kw">while</span> (v &lt; <span class="tok-number">8</span>) : (v += <span class="tok-number">1</span>) {</span>
<span class="line" id="L234"> <span class="tok-kw">const</span> mcu_value = mcu[v * <span class="tok-number">8</span> + u];</span>
<span class="line" id="L235"> reconstructed_pixel += IDCTMultipliers[y][x][u][v] * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(mcu_value));</span>
<span class="line" id="L236"> }</span>
<span class="line" id="L237"> }</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"> <span class="tok-kw">const</span> scaled_pixel = <span class="tok-builtin">@round</span>(reconstructed_pixel / <span class="tok-number">4.0</span>);</span>
<span class="line" id="L240"> <span class="tok-kw">if</span> (JPEG_DEBUG) {</span>
<span class="line" id="L241"> <span class="tok-kw">if</span> (scaled_pixel &lt; -<span class="tok-number">128.0</span> <span class="tok-kw">or</span> scaled_pixel &gt; <span class="tok-number">127.0</span>) {</span>
<span class="line" id="L242"> std.debug.print(<span class="tok-str">&quot;Pixel at mcu={} x={} y={} component_id={} is out of bounds with DCT: {d}!\n&quot;</span>, .{ mcu_id, x, y, component_id, scaled_pixel });</span>
<span class="line" id="L243"> }</span>
<span class="line" id="L244"> }</span>
<span class="line" id="L245"></span>
<span class="line" id="L246"> <span class="tok-kw">return</span> <span class="tok-builtin">@intFromFloat</span>(std.math.clamp(scaled_pixel, -<span class="tok-number">128.0</span>, <span class="tok-number">127.0</span>));</span>
<span class="line" id="L247">}</span>
<span class="line" id="L248"></span>
</code></pre></body>
</html>

View file

@ -1,267 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/FrameHeader.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">//! this module implements the frame header followint the t-81 specs,</span></span>
<span class="line" id="L2"><span class="tok-comment">//! section b.2.2 Frame Header Syntax</span></span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> Component = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L15"> id: <span class="tok-type">u8</span>,</span>
<span class="line" id="L16"> horizontal_sampling_factor: <span class="tok-type">u4</span>,</span>
<span class="line" id="L17"> vertical_sampling_factor: <span class="tok-type">u4</span>,</span>
<span class="line" id="L18"> quantization_table_id: <span class="tok-type">u8</span>,</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Component {</span>
<span class="line" id="L21"> <span class="tok-kw">const</span> component_id = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L22"> <span class="tok-kw">const</span> sampling_factors = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L23"> <span class="tok-kw">const</span> quantization_table_id = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> <span class="tok-kw">const</span> horizontal_sampling_factor: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(sampling_factors &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L26"> <span class="tok-kw">const</span> vertical_sampling_factor: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(sampling_factors &amp; <span class="tok-number">0xF</span>);</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"> <span class="tok-kw">if</span> (horizontal_sampling_factor &lt; <span class="tok-number">1</span> <span class="tok-kw">or</span> horizontal_sampling_factor &gt; <span class="tok-number">4</span>) {</span>
<span class="line" id="L29"> <span class="tok-comment">// TODO(angelo): error, create cusotm error</span>
</span>
<span class="line" id="L30"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L31"> }</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"> <span class="tok-kw">if</span> (vertical_sampling_factor &lt; <span class="tok-number">1</span> <span class="tok-kw">or</span> vertical_sampling_factor &gt; <span class="tok-number">4</span>) {</span>
<span class="line" id="L34"> <span class="tok-comment">// TODO(angelo): error, create custom error</span>
</span>
<span class="line" id="L35"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L36"> }</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"> <span class="tok-kw">if</span> (quantization_table_id &gt; <span class="tok-number">3</span>) {</span>
<span class="line" id="L39"> <span class="tok-comment">// TODO(angelo): error, create custom error</span>
</span>
<span class="line" id="L40"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L41"> }</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"> <span class="tok-kw">return</span> Component{</span>
<span class="line" id="L44"> .id = component_id,</span>
<span class="line" id="L45"> .horizontal_sampling_factor = horizontal_sampling_factor,</span>
<span class="line" id="L46"> .vertical_sampling_factor = vertical_sampling_factor,</span>
<span class="line" id="L47"> .quantization_table_id = quantization_table_id,</span>
<span class="line" id="L48"> };</span>
<span class="line" id="L49"> }</span>
<span class="line" id="L50">};</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L53"></span>
<span class="line" id="L54">allocator: Allocator,</span>
<span class="line" id="L55">sample_precision: <span class="tok-type">u8</span>,</span>
<span class="line" id="L56">row_count: <span class="tok-type">u16</span>,</span>
<span class="line" id="L57">samples_per_row: <span class="tok-type">u16</span>,</span>
<span class="line" id="L58">components: []Component,</span>
<span class="line" id="L59"></span>
<span class="line" id="L60"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(allocator: Allocator, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {</span>
<span class="line" id="L61"> <span class="tok-kw">const</span> segment_size = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L62"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;StartOfFrame: frame size = 0x{X}\n&quot;</span>, .{segment_size});</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> <span class="tok-kw">const</span> sample_precision = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L65"> <span class="tok-kw">const</span> row_count = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L66"> <span class="tok-kw">const</span> samples_per_row = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> <span class="tok-kw">const</span> component_count = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">if</span> (component_count != <span class="tok-number">1</span> <span class="tok-kw">and</span> component_count != <span class="tok-number">3</span>) {</span>
<span class="line" id="L71"> <span class="tok-comment">// TODO(angelo): use jpeg error here, for components</span>
</span>
<span class="line" id="L72"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot; {}x{}, precision={}, {} components\n&quot;</span>, .{ samples_per_row, row_count, sample_precision, component_count });</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"> <span class="tok-kw">var</span> components = <span class="tok-kw">try</span> allocator.alloc(Component, component_count);</span>
<span class="line" id="L78"> <span class="tok-kw">errdefer</span> allocator.free(components);</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L81"> <span class="tok-kw">while</span> (i &lt; component_count) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L82"> components[i] = <span class="tok-kw">try</span> Component.read(reader);</span>
<span class="line" id="L83"> <span class="tok-comment">// TODO(angelo): remove this</span>
</span>
<span class="line" id="L84"> <span class="tok-comment">// if (JPEG_VERY_DEBUG) {</span>
</span>
<span class="line" id="L85"> <span class="tok-comment">// std.debug.print(&quot; ID={}, Vfactor={}, Hfactor={} QtableID={}\n&quot;, .{</span>
</span>
<span class="line" id="L86"> <span class="tok-comment">// components[i].id, components[i].vertical_sampling_factor, components[i].horizontal_sampling_factor, components[i].quantization_table_id,</span>
</span>
<span class="line" id="L87"> <span class="tok-comment">// });</span>
</span>
<span class="line" id="L88"> <span class="tok-comment">// }</span>
</span>
<span class="line" id="L89"> }</span>
<span class="line" id="L90"></span>
<span class="line" id="L91"> <span class="tok-comment">// see B 8.2 table for the meaning of this check.</span>
</span>
<span class="line" id="L92"> std.debug.assert(segment_size == <span class="tok-number">8</span> + <span class="tok-number">3</span> * component_count);</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L95"> .allocator = allocator,</span>
<span class="line" id="L96"> .sample_precision = sample_precision,</span>
<span class="line" id="L97"> .row_count = row_count,</span>
<span class="line" id="L98"> .samples_per_row = samples_per_row,</span>
<span class="line" id="L99"> .components = components,</span>
<span class="line" id="L100"> };</span>
<span class="line" id="L101">}</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L104"> self.allocator.free(self.components);</span>
<span class="line" id="L105">}</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getMaxHorizontalSamplingFactor</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L108"> <span class="tok-kw">var</span> ret: <span class="tok-type">u4</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L109"> <span class="tok-kw">for</span> (self.components) |component| {</span>
<span class="line" id="L110"> <span class="tok-kw">if</span> (ret &lt; component.horizontal_sampling_factor) {</span>
<span class="line" id="L111"> ret = component.horizontal_sampling_factor;</span>
<span class="line" id="L112"> }</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114"></span>
<span class="line" id="L115"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L116">}</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getMaxVerticalSamplingFactor</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L119"> <span class="tok-kw">var</span> ret: <span class="tok-type">u4</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L120"> <span class="tok-kw">for</span> (self.components) |component| {</span>
<span class="line" id="L121"> <span class="tok-kw">if</span> (ret &lt; component.vertical_sampling_factor) {</span>
<span class="line" id="L122"> ret = component.vertical_sampling_factor;</span>
<span class="line" id="L123"> }</span>
<span class="line" id="L124"> }</span>
<span class="line" id="L125"></span>
<span class="line" id="L126"> <span class="tok-kw">return</span> ret;</span>
<span class="line" id="L127">}</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getBlockCount</span>(self: Self, component_id: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L130"> <span class="tok-comment">// MCU of non-interleaved is just one block.</span>
</span>
<span class="line" id="L131"> <span class="tok-kw">if</span> (self.components.len == <span class="tok-number">1</span>) {</span>
<span class="line" id="L132"> <span class="tok-kw">return</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L133"> }</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"> <span class="tok-kw">const</span> horizontal_block_count = self.components[component_id].horizontal_sampling_factor;</span>
<span class="line" id="L136"> <span class="tok-kw">const</span> vertical_block_count = self.components[component_id].vertical_sampling_factor;</span>
<span class="line" id="L137"> <span class="tok-kw">return</span> horizontal_block_count * vertical_block_count;</span>
<span class="line" id="L138">}</span>
<span class="line" id="L139"></span>
</code></pre></body>
</html>

View file

@ -1,202 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/JFIFHeader.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">//! this module implements the JFIF header</span></span>
<span class="line" id="L2"><span class="tok-comment">//! specified in https://www.w3.org/Graphics/JPEG/itu-t81.pdf</span></span>
<span class="line" id="L3"><span class="tok-comment">//! section B.2.1 and assumes that there will be an application0 segment.</span></span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">const</span> Markers = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./utils.zig&quot;</span>).Markers;</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-comment">/// see https://www.ecma-international.org/wp-content/uploads/ECMA_TR-98_1st_edition_june_2009.pdf</span></span>
<span class="line" id="L14"><span class="tok-comment">/// chapt 10.</span></span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> DensityUnit = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L16"> pixels = <span class="tok-number">0</span>,</span>
<span class="line" id="L17"> dots_per_inch = <span class="tok-number">1</span>,</span>
<span class="line" id="L18"> dots_per_cm = <span class="tok-number">2</span>,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
<span class="line" id="L21">jfif_revision: <span class="tok-type">u16</span>,</span>
<span class="line" id="L22">density_unit: DensityUnit,</span>
<span class="line" id="L23">x_density: <span class="tok-type">u16</span>,</span>
<span class="line" id="L24">y_density: <span class="tok-type">u16</span>,</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(buffered_stream: *buffered_stream_source.DefaultBufferedStreamSourceReader) !Self {</span>
<span class="line" id="L27"> <span class="tok-comment">// Read the first APP0 header.</span>
</span>
<span class="line" id="L28"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L29"> <span class="tok-kw">try</span> buffered_stream.seekTo(<span class="tok-number">2</span>);</span>
<span class="line" id="L30"> <span class="tok-kw">const</span> maybe_app0_marker = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L31"> <span class="tok-kw">if</span> (maybe_app0_marker != <span class="tok-builtin">@intFromEnum</span>(Markers.application0)) {</span>
<span class="line" id="L32"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.App0MarkerDoesNotExist;</span>
<span class="line" id="L33"> }</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"> <span class="tok-comment">// Header length</span>
</span>
<span class="line" id="L36"> _ = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"> <span class="tok-kw">var</span> identifier_buffer: [<span class="tok-number">4</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L39"> _ = <span class="tok-kw">try</span> reader.read(identifier_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">if</span> (!std.mem.eql(<span class="tok-type">u8</span>, identifier_buffer[<span class="tok-number">0</span>..], <span class="tok-str">&quot;JFIF&quot;</span>)) {</span>
<span class="line" id="L42"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.JfifIdentifierNotSet;</span>
<span class="line" id="L43"> }</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> <span class="tok-comment">// NUL byte after JFIF</span>
</span>
<span class="line" id="L46"> _ = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-kw">const</span> jfif_revision = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L49"> <span class="tok-kw">const</span> density_unit: DensityUnit = <span class="tok-builtin">@enumFromInt</span>(<span class="tok-kw">try</span> reader.readByte());</span>
<span class="line" id="L50"> <span class="tok-kw">const</span> x_density = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L51"> <span class="tok-kw">const</span> y_density = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L52"></span>
<span class="line" id="L53"> <span class="tok-kw">const</span> thumbnailWidth = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L54"> <span class="tok-kw">const</span> thumbnailHeight = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"> <span class="tok-kw">if</span> (thumbnailWidth != <span class="tok-number">0</span> <span class="tok-kw">or</span> thumbnailHeight != <span class="tok-number">0</span>) {</span>
<span class="line" id="L57"> <span class="tok-comment">// TODO: Support thumbnails (not important)</span>
</span>
<span class="line" id="L58"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ThumbnailImagesUnsupported;</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> <span class="tok-comment">// Make sure there are no application markers after us.</span>
</span>
<span class="line" id="L62"> <span class="tok-comment">// TODO: Support application markers, present in versions 1.02 and above.</span>
</span>
<span class="line" id="L63"> <span class="tok-comment">// see https://www.ecma-international.org/wp-content/uploads/ECMA_TR-98_1st_edition_june_2009.pdf</span>
</span>
<span class="line" id="L64"> <span class="tok-comment">// chapt 10.1</span>
</span>
<span class="line" id="L65"> <span class="tok-kw">if</span> (((<span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big)) &amp; <span class="tok-number">0xFFF0</span>) == <span class="tok-builtin">@intFromEnum</span>(Markers.application0)) {</span>
<span class="line" id="L66"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ExtraneousApplicationMarker;</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"> <span class="tok-kw">try</span> buffered_stream.seekBy(-<span class="tok-number">2</span>);</span>
<span class="line" id="L70"></span>
<span class="line" id="L71"> <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L72"> .jfif_revision = jfif_revision,</span>
<span class="line" id="L73"> .density_unit = density_unit,</span>
<span class="line" id="L74"> .x_density = x_density,</span>
<span class="line" id="L75"> .y_density = y_density,</span>
<span class="line" id="L76"> };</span>
<span class="line" id="L77">}</span>
<span class="line" id="L78"></span>
</code></pre></body>
</html>

View file

@ -1,393 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/Scan.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../color.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">const</span> FrameHeader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;FrameHeader.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">const</span> Frame = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;Frame.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> HuffmanReader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;huffman.zig&quot;</span>).Reader;</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"><span class="tok-kw">const</span> MAX_COMPONENTS = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MAX_COMPONENTS;</span>
<span class="line" id="L13"><span class="tok-kw">const</span> MAX_BLOCKS = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MAX_BLOCKS;</span>
<span class="line" id="L14"><span class="tok-kw">const</span> MCU = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).MCU;</span>
<span class="line" id="L15"><span class="tok-kw">const</span> ZigzagOffsets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;utils.zig&quot;</span>).ZigzagOffsets;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L20"><span class="tok-kw">const</span> JPEG_VERY_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L21"></span>
<span class="line" id="L22">frame: *<span class="tok-kw">const</span> Frame,</span>
<span class="line" id="L23">reader: HuffmanReader,</span>
<span class="line" id="L24">scan_header: ScanHeader,</span>
<span class="line" id="L25">mcu_storage: [MAX_COMPONENTS][MAX_BLOCKS]MCU,</span>
<span class="line" id="L26">prediction_values: [<span class="tok-number">3</span>]<span class="tok-type">i12</span>,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(frame: *<span class="tok-kw">const</span> Frame, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {</span>
<span class="line" id="L29"> <span class="tok-kw">const</span> scan_header = <span class="tok-kw">try</span> ScanHeader.read(reader);</span>
<span class="line" id="L30"> <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L31"> .frame = frame,</span>
<span class="line" id="L32"> .reader = HuffmanReader.init(reader),</span>
<span class="line" id="L33"> .scan_header = scan_header,</span>
<span class="line" id="L34"> .mcu_storage = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L35"> .prediction_values = [<span class="tok-number">3</span>]<span class="tok-type">i12</span>{ <span class="tok-number">0</span>, <span class="tok-number">0</span>, <span class="tok-number">0</span> },</span>
<span class="line" id="L36"> };</span>
<span class="line" id="L37">}</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-comment">/// Perform the scan operation.</span></span>
<span class="line" id="L40"><span class="tok-comment">/// We assume the AC and DC huffman tables are already set up, and ready to decode.</span></span>
<span class="line" id="L41"><span class="tok-comment">/// This should implement section E.2.3 of t-81 1992.</span></span>
<span class="line" id="L42"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">performScan</span>(frame: *<span class="tok-kw">const</span> Frame, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, pixels_opt: *?color.PixelStorage) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L43"> <span class="tok-kw">var</span> self = <span class="tok-kw">try</span> Self.init(frame, reader);</span>
<span class="line" id="L44"></span>
<span class="line" id="L45"> <span class="tok-kw">const</span> mcu_count = Self.calculateMCUCountInFrame(&amp;frame.frame_header);</span>
<span class="line" id="L46"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..mcu_count) |mcu_id| {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> self.decodeMCU();</span>
<span class="line" id="L48"> <span class="tok-kw">try</span> self.dequantize();</span>
<span class="line" id="L49"> <span class="tok-kw">try</span> frame.renderToPixels(&amp;self.mcu_storage, mcu_id, &amp;pixels_opt.*.?);</span>
<span class="line" id="L50"> }</span>
<span class="line" id="L51">}</span>
<span class="line" id="L52"></span>
<span class="line" id="L53"><span class="tok-kw">fn</span> <span class="tok-fn">dequantize</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L54"> <span class="tok-kw">for</span> (self.frame.frame_header.components, <span class="tok-number">0</span>..) |component, component_id| {</span>
<span class="line" id="L55"> <span class="tok-kw">const</span> block_count = self.frame.frame_header.getBlockCount(component_id);</span>
<span class="line" id="L56"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..block_count) |i| {</span>
<span class="line" id="L57"> <span class="tok-kw">const</span> block = &amp;self.mcu_storage[component_id][i];</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"> <span class="tok-kw">if</span> (self.frame.quantization_tables[component.quantization_table_id]) |quantization_table| {</span>
<span class="line" id="L60"> <span class="tok-kw">var</span> sample_id: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L61"> <span class="tok-kw">while</span> (sample_id &lt; <span class="tok-number">64</span>) : (sample_id += <span class="tok-number">1</span>) {</span>
<span class="line" id="L62"> block[sample_id] = block[sample_id] * quantization_table.q8[sample_id];</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"> } <span class="tok-kw">else</span> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L65"> }</span>
<span class="line" id="L66"> }</span>
<span class="line" id="L67">}</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"><span class="tok-kw">fn</span> <span class="tok-fn">calculateMCUCountInFrame</span>(frame_header: *<span class="tok-kw">const</span> FrameHeader) <span class="tok-type">usize</span> {</span>
<span class="line" id="L70"> <span class="tok-comment">// FIXME: This is very naive and probably only works for Baseline DCT.</span>
</span>
<span class="line" id="L71"> <span class="tok-comment">// MCU of non-interleaved is just one block.</span>
</span>
<span class="line" id="L72"> <span class="tok-kw">const</span> horizontal_block_count = <span class="tok-kw">if</span> (<span class="tok-number">1</span> &lt; frame_header.components.len) frame_header.getMaxHorizontalSamplingFactor() <span class="tok-kw">else</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L73"> <span class="tok-kw">const</span> vertical_block_count = <span class="tok-kw">if</span> (<span class="tok-number">1</span> &lt; frame_header.components.len) frame_header.getMaxVerticalSamplingFactor() <span class="tok-kw">else</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L74"> <span class="tok-kw">const</span> mcu_width = <span class="tok-number">8</span> * horizontal_block_count;</span>
<span class="line" id="L75"> <span class="tok-kw">const</span> mcu_height = <span class="tok-number">8</span> * vertical_block_count;</span>
<span class="line" id="L76"> <span class="tok-kw">const</span> mcu_count_per_row = (frame_header.samples_per_row + mcu_width - <span class="tok-number">1</span>) / mcu_width;</span>
<span class="line" id="L77"> <span class="tok-kw">const</span> mcu_count_per_column = (frame_header.row_count + mcu_height - <span class="tok-number">1</span>) / mcu_height;</span>
<span class="line" id="L78"> <span class="tok-kw">return</span> mcu_count_per_row * mcu_count_per_column;</span>
<span class="line" id="L79">}</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"><span class="tok-kw">fn</span> <span class="tok-fn">decodeMCU</span>(self: *Self) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">for</span> (self.scan_header.components, <span class="tok-number">0</span>..) |maybe_component, component_id| {</span>
<span class="line" id="L83"> _ = component_id;</span>
<span class="line" id="L84"> <span class="tok-kw">if</span> (maybe_component == <span class="tok-null">null</span>)</span>
<span class="line" id="L85"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> <span class="tok-kw">try</span> self.decodeMCUComponent(maybe_component.?);</span>
<span class="line" id="L88"> }</span>
<span class="line" id="L89">}</span>
<span class="line" id="L90"></span>
<span class="line" id="L91"><span class="tok-kw">fn</span> <span class="tok-fn">decodeMCUComponent</span>(self: *Self, component: ScanComponentSpec) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L92"> <span class="tok-comment">// The encoder might reorder components or omit one if it decides that the</span>
</span>
<span class="line" id="L93"> <span class="tok-comment">// file size can be reduced that way. Therefore we need to select the correct</span>
</span>
<span class="line" id="L94"> <span class="tok-comment">// destination for this component.</span>
</span>
<span class="line" id="L95"> <span class="tok-kw">const</span> component_destination: <span class="tok-type">usize</span> = blk: {</span>
<span class="line" id="L96"> <span class="tok-kw">for</span> (self.frame.frame_header.components, <span class="tok-number">0</span>..) |frame_component, i| {</span>
<span class="line" id="L97"> <span class="tok-kw">if</span> (frame_component.id == component.component_selector) {</span>
<span class="line" id="L98"> <span class="tok-kw">break</span> :blk i;</span>
<span class="line" id="L99"> }</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L103"> };</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"> <span class="tok-kw">const</span> block_count = self.frame.frame_header.getBlockCount(component_destination);</span>
<span class="line" id="L106"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..block_count) |i| {</span>
<span class="line" id="L107"> <span class="tok-kw">const</span> mcu = &amp;self.mcu_storage[component_destination][i];</span>
<span class="line" id="L108"></span>
<span class="line" id="L109"> <span class="tok-comment">// Decode the DC coefficient</span>
</span>
<span class="line" id="L110"> <span class="tok-kw">if</span> (self.frame.dc_huffman_tables[component.dc_table_selector] == <span class="tok-null">null</span>) <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L111"></span>
<span class="line" id="L112"> self.reader.setHuffmanTable(&amp;self.frame.dc_huffman_tables[component.dc_table_selector].?);</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"> <span class="tok-kw">const</span> dc_coefficient = <span class="tok-kw">try</span> self.decodeDCCoefficient(component_destination);</span>
<span class="line" id="L115"> mcu[<span class="tok-number">0</span>] = dc_coefficient;</span>
<span class="line" id="L116"></span>
<span class="line" id="L117"> <span class="tok-comment">// Decode the AC coefficients</span>
</span>
<span class="line" id="L118"> <span class="tok-kw">if</span> (self.frame.ac_huffman_tables[component.ac_table_selector] == <span class="tok-null">null</span>)</span>
<span class="line" id="L119"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"> self.reader.setHuffmanTable(&amp;self.frame.ac_huffman_tables[component.ac_table_selector].?);</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> <span class="tok-kw">try</span> self.decodeACCoefficients(mcu);</span>
<span class="line" id="L124"> }</span>
<span class="line" id="L125">}</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"><span class="tok-kw">fn</span> <span class="tok-fn">decodeDCCoefficient</span>(self: *Self, component_destination: <span class="tok-type">usize</span>) ImageReadError!<span class="tok-type">i12</span> {</span>
<span class="line" id="L128"> <span class="tok-kw">const</span> maybe_magnitude = <span class="tok-kw">try</span> self.reader.readCode();</span>
<span class="line" id="L129"> <span class="tok-kw">if</span> (maybe_magnitude &gt; <span class="tok-number">11</span>) <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L130"> <span class="tok-kw">const</span> magnitude: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(maybe_magnitude);</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> <span class="tok-kw">const</span> diff: <span class="tok-type">i12</span> = <span class="tok-builtin">@intCast</span>(<span class="tok-kw">try</span> self.reader.readMagnitudeCoded(magnitude));</span>
<span class="line" id="L133"> <span class="tok-comment">// TODO: check correctess after refactor</span>
</span>
<span class="line" id="L134"> <span class="tok-kw">const</span> dc_coefficient = diff + self.prediction_values[component_destination];</span>
<span class="line" id="L135"> self.prediction_values[component_destination] = dc_coefficient;</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-kw">return</span> dc_coefficient;</span>
<span class="line" id="L138">}</span>
<span class="line" id="L139"></span>
<span class="line" id="L140"><span class="tok-kw">fn</span> <span class="tok-fn">decodeACCoefficients</span>(self: *Self, mcu: *MCU) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L141"> <span class="tok-kw">var</span> ac: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L142"> <span class="tok-kw">var</span> did_see_eob = <span class="tok-null">false</span>;</span>
<span class="line" id="L143"> <span class="tok-kw">while</span> (ac &lt; <span class="tok-number">64</span>) : (ac += <span class="tok-number">1</span>) {</span>
<span class="line" id="L144"> <span class="tok-kw">if</span> (did_see_eob) {</span>
<span class="line" id="L145"> mcu[ZigzagOffsets[ac]] = <span class="tok-number">0</span>;</span>
<span class="line" id="L146"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L147"> }</span>
<span class="line" id="L148"></span>
<span class="line" id="L149"> <span class="tok-kw">const</span> zero_run_length_and_magnitude = <span class="tok-kw">try</span> self.reader.readCode();</span>
<span class="line" id="L150"> <span class="tok-comment">// 00 == EOB</span>
</span>
<span class="line" id="L151"> <span class="tok-kw">if</span> (zero_run_length_and_magnitude == <span class="tok-number">0x00</span>) {</span>
<span class="line" id="L152"> did_see_eob = <span class="tok-null">true</span>;</span>
<span class="line" id="L153"> mcu[ZigzagOffsets[ac]] = <span class="tok-number">0</span>;</span>
<span class="line" id="L154"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156"></span>
<span class="line" id="L157"> <span class="tok-kw">const</span> zero_run_length = zero_run_length_and_magnitude &gt;&gt; <span class="tok-number">4</span>;</span>
<span class="line" id="L158"></span>
<span class="line" id="L159"> <span class="tok-kw">const</span> maybe_magnitude = zero_run_length_and_magnitude &amp; <span class="tok-number">0xF</span>;</span>
<span class="line" id="L160"> <span class="tok-kw">if</span> (maybe_magnitude &gt; <span class="tok-number">10</span>) <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L161"> <span class="tok-kw">const</span> magnitude: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(maybe_magnitude);</span>
<span class="line" id="L162"></span>
<span class="line" id="L163"> <span class="tok-kw">const</span> ac_coefficient: <span class="tok-type">i11</span> = <span class="tok-builtin">@intCast</span>(<span class="tok-kw">try</span> self.reader.readMagnitudeCoded(magnitude));</span>
<span class="line" id="L164"></span>
<span class="line" id="L165"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L166"> <span class="tok-kw">while</span> (i &lt; zero_run_length) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L167"> mcu[ZigzagOffsets[ac]] = <span class="tok-number">0</span>;</span>
<span class="line" id="L168"> ac += <span class="tok-number">1</span>;</span>
<span class="line" id="L169"> }</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> mcu[ZigzagOffsets[ac]] = ac_coefficient;</span>
<span class="line" id="L172"> }</span>
<span class="line" id="L173">}</span>
<span class="line" id="L174"></span>
<span class="line" id="L175"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ScanComponentSpec = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L176"> component_selector: <span class="tok-type">u8</span>,</span>
<span class="line" id="L177"> dc_table_selector: <span class="tok-type">u4</span>,</span>
<span class="line" id="L178"> ac_table_selector: <span class="tok-type">u4</span>,</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!ScanComponentSpec {</span>
<span class="line" id="L181"> <span class="tok-kw">const</span> component_selector = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L182"> <span class="tok-kw">const</span> entropy_coding_selectors = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-kw">const</span> dc_table_selector: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(entropy_coding_selectors &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L185"> <span class="tok-kw">const</span> ac_table_selector: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(entropy_coding_selectors &amp; <span class="tok-number">0b11</span>);</span>
<span class="line" id="L186"></span>
<span class="line" id="L187"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) {</span>
<span class="line" id="L188"> std.debug.print(<span class="tok-str">&quot; Component spec: selector={}, DC table ID={}, AC table ID={}\n&quot;</span>, .{ component_selector, dc_table_selector, ac_table_selector });</span>
<span class="line" id="L189"> }</span>
<span class="line" id="L190"></span>
<span class="line" id="L191"> <span class="tok-kw">return</span> ScanComponentSpec{</span>
<span class="line" id="L192"> .component_selector = component_selector,</span>
<span class="line" id="L193"> .dc_table_selector = dc_table_selector,</span>
<span class="line" id="L194"> .ac_table_selector = ac_table_selector,</span>
<span class="line" id="L195"> };</span>
<span class="line" id="L196"> }</span>
<span class="line" id="L197">};</span>
<span class="line" id="L198"></span>
<span class="line" id="L199"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Header = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L200"> components: [<span class="tok-number">4</span>]?ScanComponentSpec,</span>
<span class="line" id="L201"></span>
<span class="line" id="L202"> <span class="tok-comment">/// first DCT coefficient in each block in zig-zag order</span></span>
<span class="line" id="L203"> start_of_spectral_selection: <span class="tok-type">u8</span>,</span>
<span class="line" id="L204"></span>
<span class="line" id="L205"> <span class="tok-comment">/// last DCT coefficient in each block in zig-zag order</span></span>
<span class="line" id="L206"> <span class="tok-comment">/// 63 for sequential DCT, 0 for lossless</span></span>
<span class="line" id="L207"> <span class="tok-comment">/// TODO(angelo) add check for this.</span></span>
<span class="line" id="L208"> end_of_spectral_selection: <span class="tok-type">u8</span>,</span>
<span class="line" id="L209"> approximation_high: <span class="tok-type">u4</span>,</span>
<span class="line" id="L210"> approximation_low: <span class="tok-type">u4</span>,</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Header {</span>
<span class="line" id="L213"> <span class="tok-kw">const</span> segment_size = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L214"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;StartOfScan: segment size = 0x{X}\n&quot;</span>, .{segment_size});</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"> <span class="tok-kw">const</span> component_count = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L217"> <span class="tok-kw">if</span> (component_count &lt; <span class="tok-number">1</span> <span class="tok-kw">or</span> component_count &gt; <span class="tok-number">4</span>) {</span>
<span class="line" id="L218"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L219"> }</span>
<span class="line" id="L220"></span>
<span class="line" id="L221"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot; Component count: {}\n&quot;</span>, .{component_count});</span>
<span class="line" id="L222"></span>
<span class="line" id="L223"> <span class="tok-kw">var</span> components = [_]?ScanComponentSpec{<span class="tok-null">null</span>} ** <span class="tok-number">4</span>;</span>
<span class="line" id="L224"></span>
<span class="line" id="L225"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) std.debug.print(<span class="tok-str">&quot; Components:\n&quot;</span>, .{});</span>
<span class="line" id="L226"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L227"> <span class="tok-kw">while</span> (i &lt; component_count) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L228"> components[i] = <span class="tok-kw">try</span> ScanComponentSpec.read(reader);</span>
<span class="line" id="L229"> }</span>
<span class="line" id="L230"></span>
<span class="line" id="L231"> <span class="tok-kw">const</span> start_of_spectral_selection = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L232"> <span class="tok-kw">const</span> end_of_spectral_selection = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L233"></span>
<span class="line" id="L234"> <span class="tok-kw">if</span> (start_of_spectral_selection &gt; <span class="tok-number">63</span>) {</span>
<span class="line" id="L235"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L236"> }</span>
<span class="line" id="L237"></span>
<span class="line" id="L238"> <span class="tok-kw">if</span> (end_of_spectral_selection &lt; start_of_spectral_selection <span class="tok-kw">or</span> end_of_spectral_selection &gt; <span class="tok-number">63</span>) {</span>
<span class="line" id="L239"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L240"> }</span>
<span class="line" id="L241"></span>
<span class="line" id="L242"> <span class="tok-comment">// If Ss = 0, then Se = 63.</span>
</span>
<span class="line" id="L243"> <span class="tok-kw">if</span> (start_of_spectral_selection == <span class="tok-number">0</span> <span class="tok-kw">and</span> end_of_spectral_selection != <span class="tok-number">63</span>) {</span>
<span class="line" id="L244"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L245"> }</span>
<span class="line" id="L246"></span>
<span class="line" id="L247"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) std.debug.print(<span class="tok-str">&quot; Spectral selection: {}-{}\n&quot;</span>, .{ start_of_spectral_selection, end_of_spectral_selection });</span>
<span class="line" id="L248"></span>
<span class="line" id="L249"> <span class="tok-kw">const</span> approximation_bits = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L250"> <span class="tok-kw">const</span> approximation_high: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(approximation_bits &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L251"> <span class="tok-kw">const</span> approximation_low: <span class="tok-type">u4</span> = <span class="tok-builtin">@intCast</span>(approximation_bits &amp; <span class="tok-number">0b1111</span>);</span>
<span class="line" id="L252"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) std.debug.print(<span class="tok-str">&quot; Approximation bit position: high={} low={}\n&quot;</span>, .{ approximation_high, approximation_low });</span>
<span class="line" id="L253"></span>
<span class="line" id="L254"> std.debug.assert(segment_size == <span class="tok-number">2</span> * component_count + <span class="tok-number">1</span> + <span class="tok-number">2</span> + <span class="tok-number">1</span> + <span class="tok-number">2</span>);</span>
<span class="line" id="L255"></span>
<span class="line" id="L256"> <span class="tok-kw">return</span> Header{</span>
<span class="line" id="L257"> .components = components,</span>
<span class="line" id="L258"> .start_of_spectral_selection = start_of_spectral_selection,</span>
<span class="line" id="L259"> .end_of_spectral_selection = end_of_spectral_selection,</span>
<span class="line" id="L260"> .approximation_high = approximation_high,</span>
<span class="line" id="L261"> .approximation_low = approximation_low,</span>
<span class="line" id="L262"> };</span>
<span class="line" id="L263"> }</span>
<span class="line" id="L264">};</span>
<span class="line" id="L265"></span>
<span class="line" id="L266"><span class="tok-kw">const</span> ScanHeader = Header;</span>
<span class="line" id="L267"></span>
</code></pre></body>
</html>

View file

@ -1,302 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/huffman.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">//! This module contains implementation of huffman table encodings</span></span>
<span class="line" id="L2"><span class="tok-comment">//! as specified by section 2.4.2 in t-81 1992</span></span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L6"></span>
<span class="line" id="L7"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> HuffmanCode = <span class="tok-kw">struct</span> { length_minus_one: <span class="tok-type">u4</span>, code: <span class="tok-type">u16</span> };</span>
<span class="line" id="L12"><span class="tok-kw">const</span> HuffmanCodeMap = std.AutoArrayHashMap(HuffmanCode, <span class="tok-type">u8</span>);</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L15"><span class="tok-kw">const</span> JPEG_VERY_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Table = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L18"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"> allocator: Allocator,</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"> code_counts: [<span class="tok-number">16</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L23"> code_map: HuffmanCodeMap,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> table_class: <span class="tok-type">u8</span>,</span>
<span class="line" id="L26"></span>
<span class="line" id="L27"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(allocator: Allocator, table_class: <span class="tok-type">u8</span>, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {</span>
<span class="line" id="L28"> <span class="tok-kw">if</span> (table_class &amp; <span class="tok-number">1</span> != table_class)</span>
<span class="line" id="L29"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"> <span class="tok-kw">var</span> code_counts: [<span class="tok-number">16</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L32"> <span class="tok-kw">if</span> ((<span class="tok-kw">try</span> reader.read(code_counts[<span class="tok-number">0</span>..])) &lt; <span class="tok-number">16</span>) {</span>
<span class="line" id="L33"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L34"> }</span>
<span class="line" id="L35"></span>
<span class="line" id="L36"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot; Code counts: {any}\n&quot;</span>, .{code_counts});</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"> <span class="tok-kw">var</span> total_huffman_codes: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L39"> <span class="tok-kw">for</span> (code_counts) |count| total_huffman_codes += count;</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">var</span> huffman_code_map = HuffmanCodeMap.init(allocator);</span>
<span class="line" id="L42"> <span class="tok-kw">errdefer</span> huffman_code_map.deinit();</span>
<span class="line" id="L43"></span>
<span class="line" id="L44"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) std.debug.print(<span class="tok-str">&quot; Decoded huffman codes map:\n&quot;</span>, .{});</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-kw">var</span> code: <span class="tok-type">u16</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L47"> <span class="tok-kw">for</span> (code_counts, <span class="tok-number">0</span>..) |count, i| {</span>
<span class="line" id="L48"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) {</span>
<span class="line" id="L49"> std.debug.print(<span class="tok-str">&quot; Length {}: &quot;</span>, .{i + <span class="tok-number">1</span>});</span>
<span class="line" id="L50"> <span class="tok-kw">if</span> (count == <span class="tok-number">0</span>) {</span>
<span class="line" id="L51"> std.debug.print(<span class="tok-str">&quot;(none)\n&quot;</span>, .{});</span>
<span class="line" id="L52"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L53"> std.debug.print(<span class="tok-str">&quot;\n&quot;</span>, .{});</span>
<span class="line" id="L54"> }</span>
<span class="line" id="L55"> }</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L58"> <span class="tok-kw">while</span> (j &lt; count) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L59"> <span class="tok-comment">// Check if we hit all 1s, i.e. 111111 for i == 6, which is an invalid value</span>
</span>
<span class="line" id="L60"> <span class="tok-kw">if</span> (code == (<span class="tok-builtin">@as</span>(<span class="tok-type">u17</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-number">1</span>)) &lt;&lt; (<span class="tok-builtin">@as</span>(<span class="tok-type">u5</span>, <span class="tok-builtin">@intCast</span>(i)) + <span class="tok-number">1</span>)) - <span class="tok-number">1</span>) {</span>
<span class="line" id="L61"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L62"> }</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> <span class="tok-kw">const</span> byte = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L65"> <span class="tok-kw">try</span> huffman_code_map.put(.{ .length_minus_one = <span class="tok-builtin">@as</span>(<span class="tok-type">u4</span>, <span class="tok-builtin">@intCast</span>(i)), .code = code }, byte);</span>
<span class="line" id="L66"></span>
<span class="line" id="L67"> <span class="tok-kw">if</span> (JPEG_VERY_DEBUG) std.debug.print(<span class="tok-str">&quot; {b} =&gt; 0x{X}\n&quot;</span>, .{ code, byte });</span>
<span class="line" id="L68"> code += <span class="tok-number">1</span>;</span>
<span class="line" id="L69"> }</span>
<span class="line" id="L70"></span>
<span class="line" id="L71"> code &lt;&lt;= <span class="tok-number">1</span>;</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"> <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L75"> .allocator = allocator,</span>
<span class="line" id="L76"> .code_counts = code_counts,</span>
<span class="line" id="L77"> .code_map = huffman_code_map,</span>
<span class="line" id="L78"> .table_class = table_class,</span>
<span class="line" id="L79"> };</span>
<span class="line" id="L80"> }</span>
<span class="line" id="L81"></span>
<span class="line" id="L82"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L83"> self.code_map.deinit();</span>
<span class="line" id="L84"> }</span>
<span class="line" id="L85">};</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Reader = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L88"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> table: ?*<span class="tok-kw">const</span> Table = <span class="tok-null">null</span>,</span>
<span class="line" id="L91"> reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,</span>
<span class="line" id="L92"> byte_buffer: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L93"> bits_left: <span class="tok-type">u4</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L94"> last_byte_was_ff: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L95"></span>
<span class="line" id="L96"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) Self {</span>
<span class="line" id="L97"> <span class="tok-kw">return</span> .{</span>
<span class="line" id="L98"> .reader = reader,</span>
<span class="line" id="L99"> };</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">setHuffmanTable</span>(self: *Self, table: *<span class="tok-kw">const</span> Table) <span class="tok-type">void</span> {</span>
<span class="line" id="L103"> self.table = table;</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105"></span>
<span class="line" id="L106"> <span class="tok-kw">fn</span> <span class="tok-fn">readBit</span>(self: *Self) ImageReadError!<span class="tok-type">u1</span> {</span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (self.bits_left == <span class="tok-number">0</span>) {</span>
<span class="line" id="L108"> self.byte_buffer = <span class="tok-kw">try</span> self.reader.readByte();</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-kw">if</span> (self.byte_buffer == <span class="tok-number">0</span> <span class="tok-kw">and</span> self.last_byte_was_ff) {</span>
<span class="line" id="L111"> <span class="tok-comment">// This was a stuffed byte, read one more.</span>
</span>
<span class="line" id="L112"> self.byte_buffer = <span class="tok-kw">try</span> self.reader.readByte();</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114"> self.last_byte_was_ff = self.byte_buffer == <span class="tok-number">0xFF</span>;</span>
<span class="line" id="L115"> self.bits_left = <span class="tok-number">8</span>;</span>
<span class="line" id="L116"> }</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> <span class="tok-kw">const</span> bit: <span class="tok-type">u1</span> = <span class="tok-builtin">@intCast</span>(self.byte_buffer &gt;&gt; <span class="tok-number">7</span>);</span>
<span class="line" id="L119"> self.byte_buffer &lt;&lt;= <span class="tok-number">1</span>;</span>
<span class="line" id="L120"> self.bits_left -= <span class="tok-number">1</span>;</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"> <span class="tok-kw">return</span> bit;</span>
<span class="line" id="L123"> }</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readCode</span>(self: *Self) ImageReadError!<span class="tok-type">u8</span> {</span>
<span class="line" id="L126"> <span class="tok-kw">var</span> code: <span class="tok-type">u16</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L127"></span>
<span class="line" id="L128"> <span class="tok-kw">var</span> i: <span class="tok-type">u5</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L129"> <span class="tok-kw">while</span> (i &lt; <span class="tok-number">16</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L130"> <span class="tok-comment">// NOTE: if the table is stored as a tree, this is O(1) to update the new node,</span>
</span>
<span class="line" id="L131"> <span class="tok-comment">// instead of O(log n), so should be faster.</span>
</span>
<span class="line" id="L132"> code = (code &lt;&lt; <span class="tok-number">1</span>) | (<span class="tok-kw">try</span> self.readBit());</span>
<span class="line" id="L133"> <span class="tok-kw">if</span> (self.table.?.code_map.get(.{ .length_minus_one = <span class="tok-builtin">@intCast</span>(i), .code = code })) |value| {</span>
<span class="line" id="L134"> <span class="tok-kw">return</span> value;</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"> }</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"> <span class="tok-kw">if</span> (JPEG_DEBUG) std.debug.print(<span class="tok-str">&quot;found unknown code: {x}\n&quot;</span>, .{code});</span>
<span class="line" id="L139"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L140"> }</span>
<span class="line" id="L141"></span>
<span class="line" id="L142"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readLiteralBits</span>(self: *Self, bitsNeeded: <span class="tok-type">u8</span>) ImageReadError!<span class="tok-type">u32</span> {</span>
<span class="line" id="L143"> <span class="tok-kw">var</span> bits: <span class="tok-type">u32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L146"> <span class="tok-kw">while</span> (i &lt; bitsNeeded) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L147"> bits = (bits &lt;&lt; <span class="tok-number">1</span>) | (<span class="tok-kw">try</span> self.readBit());</span>
<span class="line" id="L148"> }</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"> <span class="tok-kw">return</span> bits;</span>
<span class="line" id="L151"> }</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"> <span class="tok-comment">/// This function implements T.81 section F1.2.1, Huffman encoding of DC coefficients.</span></span>
<span class="line" id="L154"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readMagnitudeCoded</span>(self: *Self, magnitude: <span class="tok-type">u5</span>) ImageReadError!<span class="tok-type">i32</span> {</span>
<span class="line" id="L155"> <span class="tok-kw">if</span> (magnitude == <span class="tok-number">0</span>)</span>
<span class="line" id="L156"> <span class="tok-kw">return</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L157"></span>
<span class="line" id="L158"> <span class="tok-kw">const</span> bits = <span class="tok-kw">try</span> self.readLiteralBits(magnitude);</span>
<span class="line" id="L159"></span>
<span class="line" id="L160"> <span class="tok-comment">// The sign of the read bits value.</span>
</span>
<span class="line" id="L161"> <span class="tok-kw">const</span> bits_sign = (bits &gt;&gt; (magnitude - <span class="tok-number">1</span>)) &amp; <span class="tok-number">1</span>;</span>
<span class="line" id="L162"> <span class="tok-comment">// The mask for clearing the sign bit.</span>
</span>
<span class="line" id="L163"> <span class="tok-kw">const</span> bits_mask = (<span class="tok-builtin">@as</span>(<span class="tok-type">u32</span>, <span class="tok-number">1</span>) &lt;&lt; (magnitude - <span class="tok-number">1</span>)) - <span class="tok-number">1</span>;</span>
<span class="line" id="L164"> <span class="tok-comment">// The bits without the sign bit.</span>
</span>
<span class="line" id="L165"> <span class="tok-kw">const</span> unsigned_bits = bits &amp; bits_mask;</span>
<span class="line" id="L166"></span>
<span class="line" id="L167"> <span class="tok-comment">// The magnitude base value. This is -2^n+1 when bits_sign == 0, and</span>
</span>
<span class="line" id="L168"> <span class="tok-comment">// 2^(n-1) when bits_sign == 1.</span>
</span>
<span class="line" id="L169"> <span class="tok-kw">const</span> base = <span class="tok-kw">if</span> (bits_sign == <span class="tok-number">0</span>)</span>
<span class="line" id="L170"> -(<span class="tok-builtin">@as</span>(<span class="tok-type">i32</span>, <span class="tok-number">1</span>) &lt;&lt; magnitude) + <span class="tok-number">1</span></span>
<span class="line" id="L171"> <span class="tok-kw">else</span></span>
<span class="line" id="L172"> (<span class="tok-builtin">@as</span>(<span class="tok-type">i32</span>, <span class="tok-number">1</span>) &lt;&lt; (magnitude - <span class="tok-number">1</span>));</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> <span class="tok-kw">return</span> base + <span class="tok-builtin">@as</span>(<span class="tok-type">i32</span>, <span class="tok-builtin">@bitCast</span>(unsigned_bits));</span>
<span class="line" id="L175"> }</span>
<span class="line" id="L176">};</span>
<span class="line" id="L177"></span>
</code></pre></body>
</html>

View file

@ -1,213 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/quantization.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">//! see section 2.4.1 of the spec t-81 1992</span></span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">const</span> ZigzagOffsets = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;./utils.zig&quot;</span>).ZigzagOffsets;</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-kw">const</span> JPEG_DEBUG = <span class="tok-null">false</span>;</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Header = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L14"> <span class="tok-comment">// TODO(angelo): ! substitute this implementation to `parseDefineQuantizationTables` in jpeg.zig</span>
</span>
<span class="line" id="L15"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"> <span class="tok-comment">//// Specifies the precision of the quantization table entries.</span>
</span>
<span class="line" id="L18"> <span class="tok-comment">/// - 0 = 8 bits</span></span>
<span class="line" id="L19"> <span class="tok-comment">/// - 1 = 16 bits</span></span>
<span class="line" id="L20"> table_precision: <span class="tok-type">u4</span>,</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"> <span class="tok-comment">/// Specifies one of four possible destinations at the decoder into</span></span>
<span class="line" id="L23"> <span class="tok-comment">/// which the quantization table shall be installed.</span></span>
<span class="line" id="L24"> table_destination: <span class="tok-type">u4</span>,</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"> table: Table,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {</span>
<span class="line" id="L29"> _ = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big); <span class="tok-comment">// read the size, but we don't need it</span>
</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"> <span class="tok-kw">const</span> precision_and_destination = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L32"> <span class="tok-kw">const</span> table_precision = precision_and_destination &gt;&gt; <span class="tok-number">4</span>;</span>
<span class="line" id="L33"> <span class="tok-kw">const</span> table_destination = precision_and_destination &amp; <span class="tok-number">0b11</span>;</span>
<span class="line" id="L34"></span>
<span class="line" id="L35"> <span class="tok-kw">const</span> table = <span class="tok-kw">try</span> Table.read(table_precision, reader);</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"> <span class="tok-comment">// TODO: add check for: &quot;An 8-bit DCT-based process shall not use a 16-bit precision quantization table.&quot;</span>
</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"> <span class="tok-kw">return</span> Self{</span>
<span class="line" id="L40"> .table_precision = table_precision,</span>
<span class="line" id="L41"> .table_destination = table_destination,</span>
<span class="line" id="L42"> .table = table,</span>
<span class="line" id="L43"> };</span>
<span class="line" id="L44"> }</span>
<span class="line" id="L45">};</span>
<span class="line" id="L46"></span>
<span class="line" id="L47"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Table = <span class="tok-kw">union</span>(<span class="tok-kw">enum</span>) {</span>
<span class="line" id="L48"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L49"> q8: [<span class="tok-number">64</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L50"> q16: [<span class="tok-number">64</span>]<span class="tok-type">u16</span>,</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(precision: <span class="tok-type">u8</span>, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Self {</span>
<span class="line" id="L53"> <span class="tok-comment">// 0 = 8 bits, 1 = 16 bits</span>
</span>
<span class="line" id="L54"> <span class="tok-kw">switch</span> (precision) {</span>
<span class="line" id="L55"> <span class="tok-number">0</span> =&gt; {</span>
<span class="line" id="L56"> <span class="tok-kw">var</span> table = Self{ .q8 = <span class="tok-null">undefined</span> };</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L59"> <span class="tok-kw">while</span> (offset &lt; <span class="tok-number">64</span>) : (offset += <span class="tok-number">1</span>) {</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> value = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L61"> table.q8[ZigzagOffsets[offset]] = value;</span>
<span class="line" id="L62"> }</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> <span class="tok-kw">if</span> (JPEG_DEBUG) {</span>
<span class="line" id="L65"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L66"> <span class="tok-kw">while</span> (i &lt; <span class="tok-number">8</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L67"> <span class="tok-kw">var</span> j: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L68"> <span class="tok-kw">while</span> (j &lt; <span class="tok-number">8</span>) : (j += <span class="tok-number">1</span>) {</span>
<span class="line" id="L69"> std.debug.print(<span class="tok-str">&quot;{d:4} &quot;</span>, .{table.q8[i * <span class="tok-number">8</span> + j]});</span>
<span class="line" id="L70"> }</span>
<span class="line" id="L71"> std.debug.print(<span class="tok-str">&quot;\n&quot;</span>, .{});</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">return</span> table;</span>
<span class="line" id="L76"> },</span>
<span class="line" id="L77"> <span class="tok-number">1</span> =&gt; {</span>
<span class="line" id="L78"> <span class="tok-kw">var</span> table = Self{ .q16 = <span class="tok-null">undefined</span> };</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L81"> <span class="tok-kw">while</span> (offset &lt; <span class="tok-number">64</span>) : (offset += <span class="tok-number">1</span>) {</span>
<span class="line" id="L82"> <span class="tok-kw">const</span> value = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big);</span>
<span class="line" id="L83"> table.q16[ZigzagOffsets[offset]] = value;</span>
<span class="line" id="L84"> }</span>
<span class="line" id="L85"></span>
<span class="line" id="L86"> <span class="tok-kw">return</span> table;</span>
<span class="line" id="L87"> },</span>
<span class="line" id="L88"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageReadError.InvalidData,</span>
<span class="line" id="L89"> }</span>
<span class="line" id="L90"> }</span>
<span class="line" id="L91">};</span>
<span class="line" id="L92"></span>
</code></pre></body>
</html>

View file

@ -1,282 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/jpeg/utils.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">//! general utilizies and constants</span></span>
<span class="line" id="L2"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-comment">// See figure A.6 in T.81.</span>
</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ZigzagOffsets = blk: {</span>
<span class="line" id="L6"> <span class="tok-kw">var</span> offsets: [<span class="tok-number">64</span>]<span class="tok-type">usize</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L7"> offsets[<span class="tok-number">0</span>] = <span class="tok-number">0</span>;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"> <span class="tok-kw">var</span> current_offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L10"> <span class="tok-kw">var</span> direction: <span class="tok-kw">enum</span> { north_east, south_west } = .north_east;</span>
<span class="line" id="L11"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L12"> <span class="tok-kw">while</span> (i &lt; <span class="tok-number">64</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L13"> <span class="tok-kw">switch</span> (direction) {</span>
<span class="line" id="L14"> .north_east =&gt; {</span>
<span class="line" id="L15"> <span class="tok-kw">if</span> (current_offset &lt; <span class="tok-number">8</span>) {</span>
<span class="line" id="L16"> <span class="tok-comment">// Hit top edge</span>
</span>
<span class="line" id="L17"> current_offset += <span class="tok-number">1</span>;</span>
<span class="line" id="L18"> direction = .south_west;</span>
<span class="line" id="L19"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (current_offset % <span class="tok-number">8</span> == <span class="tok-number">7</span>) {</span>
<span class="line" id="L20"> <span class="tok-comment">// Hit right edge</span>
</span>
<span class="line" id="L21"> current_offset += <span class="tok-number">8</span>;</span>
<span class="line" id="L22"> direction = .south_west;</span>
<span class="line" id="L23"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L24"> current_offset -= <span class="tok-number">7</span>;</span>
<span class="line" id="L25"> }</span>
<span class="line" id="L26"> },</span>
<span class="line" id="L27"> .south_west =&gt; {</span>
<span class="line" id="L28"> <span class="tok-kw">if</span> (current_offset &gt;= <span class="tok-number">56</span>) {</span>
<span class="line" id="L29"> <span class="tok-comment">// Hit bottom edge</span>
</span>
<span class="line" id="L30"> current_offset += <span class="tok-number">1</span>;</span>
<span class="line" id="L31"> direction = .north_east;</span>
<span class="line" id="L32"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (current_offset % <span class="tok-number">8</span> == <span class="tok-number">0</span>) {</span>
<span class="line" id="L33"> <span class="tok-comment">// Hit left edge</span>
</span>
<span class="line" id="L34"> current_offset += <span class="tok-number">8</span>;</span>
<span class="line" id="L35"> direction = .north_east;</span>
<span class="line" id="L36"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L37"> current_offset += <span class="tok-number">7</span>;</span>
<span class="line" id="L38"> }</span>
<span class="line" id="L39"> },</span>
<span class="line" id="L40"> }</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"> <span class="tok-kw">if</span> (current_offset &gt;= <span class="tok-number">64</span>) {</span>
<span class="line" id="L43"> <span class="tok-builtin">@compileError</span>(std.fmt.comptimePrint(<span class="tok-str">&quot;ZigzagOffsets: Hit offset {} (&gt;= 64) at index {}!\n&quot;</span>, .{ current_offset, i }));</span>
<span class="line" id="L44"> }</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> offsets[i] = current_offset;</span>
<span class="line" id="L47"> }</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"> <span class="tok-kw">break</span> :blk offsets;</span>
<span class="line" id="L50">};</span>
<span class="line" id="L51"></span>
<span class="line" id="L52"><span class="tok-comment">/// The precalculated IDCT multipliers. This is possible because the only part of</span></span>
<span class="line" id="L53"><span class="tok-comment">/// the IDCT calculation that changes between runs is the coefficients.</span></span>
<span class="line" id="L54"><span class="tok-comment">/// see A.3.3 of t.81 1992</span></span>
<span class="line" id="L55"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> IDCTMultipliers = blk: {</span>
<span class="line" id="L56"> <span class="tok-kw">var</span> multipliers: [<span class="tok-number">8</span>][<span class="tok-number">8</span>][<span class="tok-number">8</span>][<span class="tok-number">8</span>]<span class="tok-type">f32</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L57"> <span class="tok-builtin">@setEvalBranchQuota</span>(<span class="tok-number">4700</span>);</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"> <span class="tok-kw">var</span> y: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L60"> <span class="tok-kw">while</span> (y &lt; <span class="tok-number">8</span>) : (y += <span class="tok-number">1</span>) {</span>
<span class="line" id="L61"> <span class="tok-kw">var</span> x: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L62"> <span class="tok-kw">while</span> (x &lt; <span class="tok-number">8</span>) : (x += <span class="tok-number">1</span>) {</span>
<span class="line" id="L63"> <span class="tok-kw">var</span> u: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L64"> <span class="tok-kw">while</span> (u &lt; <span class="tok-number">8</span>) : (u += <span class="tok-number">1</span>) {</span>
<span class="line" id="L65"> <span class="tok-kw">var</span> v: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L66"> <span class="tok-kw">while</span> (v &lt; <span class="tok-number">8</span>) : (v += <span class="tok-number">1</span>) {</span>
<span class="line" id="L67"> <span class="tok-kw">const</span> C_u: <span class="tok-type">f32</span> = <span class="tok-kw">if</span> (u == <span class="tok-number">0</span>) <span class="tok-number">1.0</span> / <span class="tok-builtin">@sqrt</span>(<span class="tok-number">2.0</span>) <span class="tok-kw">else</span> <span class="tok-number">1.0</span>;</span>
<span class="line" id="L68"> <span class="tok-kw">const</span> C_v: <span class="tok-type">f32</span> = <span class="tok-kw">if</span> (v == <span class="tok-number">0</span>) <span class="tok-number">1.0</span> / <span class="tok-builtin">@sqrt</span>(<span class="tok-number">2.0</span>) <span class="tok-kw">else</span> <span class="tok-number">1.0</span>;</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">const</span> x_cosine = <span class="tok-builtin">@cos</span>(((<span class="tok-number">2</span> * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(x)) + <span class="tok-number">1</span>) * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(u)) * std.math.pi) / <span class="tok-number">16.0</span>);</span>
<span class="line" id="L71"> <span class="tok-kw">const</span> y_cosine = <span class="tok-builtin">@cos</span>(((<span class="tok-number">2</span> * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(y)) + <span class="tok-number">1</span>) * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(v)) * std.math.pi) / <span class="tok-number">16.0</span>);</span>
<span class="line" id="L72"> <span class="tok-kw">const</span> uv_value = C_u * C_v * x_cosine * y_cosine;</span>
<span class="line" id="L73"> multipliers[y][x][u][v] = uv_value;</span>
<span class="line" id="L74"> }</span>
<span class="line" id="L75"> }</span>
<span class="line" id="L76"> }</span>
<span class="line" id="L77"> }</span>
<span class="line" id="L78"></span>
<span class="line" id="L79"> <span class="tok-kw">break</span> :blk multipliers;</span>
<span class="line" id="L80">};</span>
<span class="line" id="L81"></span>
<span class="line" id="L82"><span class="tok-comment">/// Marker codes, see t-81 section B.1.1.3</span></span>
<span class="line" id="L83"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Markers = <span class="tok-kw">enum</span>(<span class="tok-type">u16</span>) {</span>
<span class="line" id="L84"> <span class="tok-comment">// Start of Frame markers, non-differential, Huffman coding</span>
</span>
<span class="line" id="L85"> sof0 = <span class="tok-number">0xFFC0</span>, <span class="tok-comment">// Baseline DCT</span>
</span>
<span class="line" id="L86"> sof1 = <span class="tok-number">0xFFC1</span>, <span class="tok-comment">// Extended sequential DCT</span>
</span>
<span class="line" id="L87"> sof2 = <span class="tok-number">0xFFC2</span>, <span class="tok-comment">// Progressive DCT</span>
</span>
<span class="line" id="L88"> sof3 = <span class="tok-number">0xFFC3</span>, <span class="tok-comment">// Lossless sequential</span>
</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> <span class="tok-comment">// Start of Frame markers, differential, Huffman coding</span>
</span>
<span class="line" id="L91"> sof5 = <span class="tok-number">0xFFC5</span>, <span class="tok-comment">// Differential sequential DCT</span>
</span>
<span class="line" id="L92"> sof6 = <span class="tok-number">0xFFC6</span>, <span class="tok-comment">// Differential progressive DCT</span>
</span>
<span class="line" id="L93"> sof7 = <span class="tok-number">0xFFC7</span>, <span class="tok-comment">// Differential lossless sequential</span>
</span>
<span class="line" id="L94"></span>
<span class="line" id="L95"> <span class="tok-comment">// Start of Frame markers, non-differential, arithmetic coding</span>
</span>
<span class="line" id="L96"> sof9 = <span class="tok-number">0xFFC9</span>, <span class="tok-comment">// Extended sequential DCT</span>
</span>
<span class="line" id="L97"> sof10 = <span class="tok-number">0xFFCA</span>, <span class="tok-comment">// Progressive DCT</span>
</span>
<span class="line" id="L98"> sof11 = <span class="tok-number">0xFFCB</span>, <span class="tok-comment">// Lossless sequential</span>
</span>
<span class="line" id="L99"></span>
<span class="line" id="L100"> <span class="tok-comment">// Start of Frame markers, differential, arithmetic coding</span>
</span>
<span class="line" id="L101"> sof13 = <span class="tok-number">0xFFCD</span>, <span class="tok-comment">// Differential sequential DCT</span>
</span>
<span class="line" id="L102"> sof14 = <span class="tok-number">0xFFCE</span>, <span class="tok-comment">// Differential progressive DCT</span>
</span>
<span class="line" id="L103"> sof15 = <span class="tok-number">0xFFCF</span>, <span class="tok-comment">// Differential lossless sequential</span>
</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"> define_huffman_tables = <span class="tok-number">0xFFC4</span>,</span>
<span class="line" id="L106"> define_arithmetic_coding = <span class="tok-number">0xFFCC</span>,</span>
<span class="line" id="L107"></span>
<span class="line" id="L108"> <span class="tok-comment">// 0xFFD0-0xFFD7: Restart markers</span>
</span>
<span class="line" id="L109"> restart0 = <span class="tok-number">0xFFD0</span>,</span>
<span class="line" id="L110"> restart1 = <span class="tok-number">0xFFD1</span>,</span>
<span class="line" id="L111"> restart2 = <span class="tok-number">0xFFD2</span>,</span>
<span class="line" id="L112"> restart3 = <span class="tok-number">0xFFD3</span>,</span>
<span class="line" id="L113"> restart4 = <span class="tok-number">0xFFD4</span>,</span>
<span class="line" id="L114"> restart5 = <span class="tok-number">0xFFD5</span>,</span>
<span class="line" id="L115"> restart6 = <span class="tok-number">0xFFD6</span>,</span>
<span class="line" id="L116"> restart7 = <span class="tok-number">0xFFD7</span>,</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> start_of_image = <span class="tok-number">0xFFD8</span>,</span>
<span class="line" id="L119"> end_of_image = <span class="tok-number">0xFFD9</span>,</span>
<span class="line" id="L120"> start_of_scan = <span class="tok-number">0xFFDA</span>,</span>
<span class="line" id="L121"> define_quantization_tables = <span class="tok-number">0xFFDB</span>,</span>
<span class="line" id="L122"> define_number_of_lines = <span class="tok-number">0xFFDC</span>,</span>
<span class="line" id="L123"> define_restart_interval = <span class="tok-number">0xFFDD</span>,</span>
<span class="line" id="L124"> define_hierarchical_progression = <span class="tok-number">0xFFDE</span>,</span>
<span class="line" id="L125"> expand_reference_components = <span class="tok-number">0xFFDF</span>,</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"> <span class="tok-comment">// 0xFFE0-0xFFEF application segments markers add 0-15 as needed.</span>
</span>
<span class="line" id="L128"> application0 = <span class="tok-number">0xFFE0</span>,</span>
<span class="line" id="L129"></span>
<span class="line" id="L130"> <span class="tok-comment">// 0xFFF0-0xFFFD jpeg extension markers add 0-13 as needed.</span>
</span>
<span class="line" id="L131"> jpeg_extension0 = <span class="tok-number">0xFFF0</span>,</span>
<span class="line" id="L132"> comment = <span class="tok-number">0xFFFE</span>,</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> <span class="tok-comment">// reserved markers from 0xFF01-0xFFBF, add as needed</span>
</span>
<span class="line" id="L135">};</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> MAX_COMPONENTS = <span class="tok-number">3</span>;</span>
<span class="line" id="L138"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> MAX_BLOCKS = <span class="tok-number">8</span>;</span>
<span class="line" id="L139"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> MCU = [<span class="tok-number">64</span>]<span class="tok-type">i32</span>;</span>
<span class="line" id="L140"></span>
</code></pre></body>
</html>

View file

@ -1,635 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/netpbm.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Adapted from https://github.com/MasterQ32/zig-gamedev-lib/blob/master/src/netbpm.zig</span>
</span>
<span class="line" id="L2"><span class="tok-comment">// with permission from Felix Queißner</span>
</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> ImageError = Image.Error;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L10"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L11"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L12"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L13"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../utils.zig&quot;</span>);</span>
<span class="line" id="L14"></span>
<span class="line" id="L15"><span class="tok-comment">// this file implements the Portable Anymap specification provided by</span>
</span>
<span class="line" id="L16"><span class="tok-comment">// http://netpbm.sourceforge.net/doc/pbm.html // P1, P4 =&gt; bitmap</span>
</span>
<span class="line" id="L17"><span class="tok-comment">// http://netpbm.sourceforge.net/doc/pgm.html // P2, P5 =&gt; graymap</span>
</span>
<span class="line" id="L18"><span class="tok-comment">// http://netpbm.sourceforge.net/doc/ppm.html // P3, P6 =&gt; pixmap</span>
</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// one of the three types a netbpm graphic could be stored in.</span></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Format = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L22"> <span class="tok-comment">/// the image contains black-and-white pixels.</span></span>
<span class="line" id="L23"> bitmap,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> <span class="tok-comment">/// the image contains grayscale pixels.</span></span>
<span class="line" id="L26"> grayscale,</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"> <span class="tok-comment">/// the image contains RGB pixels.</span></span>
<span class="line" id="L29"> rgb,</span>
<span class="line" id="L30">};</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Header = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L33"> format: Format,</span>
<span class="line" id="L34"> binary: <span class="tok-type">bool</span>,</span>
<span class="line" id="L35"> width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L36"> height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L37"> max_value: <span class="tok-type">usize</span>,</span>
<span class="line" id="L38">};</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"><span class="tok-kw">fn</span> <span class="tok-fn">parseHeader</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!Header {</span>
<span class="line" id="L41"> <span class="tok-kw">var</span> header: Header = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"> <span class="tok-kw">var</span> magic: [<span class="tok-number">2</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L44"> _ = <span class="tok-kw">try</span> reader.read(magic[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P1&quot;</span>)) {</span>
<span class="line" id="L47"> header.binary = <span class="tok-null">false</span>;</span>
<span class="line" id="L48"> header.format = .bitmap;</span>
<span class="line" id="L49"> header.max_value = <span class="tok-number">1</span>;</span>
<span class="line" id="L50"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P2&quot;</span>)) {</span>
<span class="line" id="L51"> header.binary = <span class="tok-null">false</span>;</span>
<span class="line" id="L52"> header.format = .grayscale;</span>
<span class="line" id="L53"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P3&quot;</span>)) {</span>
<span class="line" id="L54"> header.binary = <span class="tok-null">false</span>;</span>
<span class="line" id="L55"> header.format = .rgb;</span>
<span class="line" id="L56"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P4&quot;</span>)) {</span>
<span class="line" id="L57"> header.binary = <span class="tok-null">true</span>;</span>
<span class="line" id="L58"> header.format = .bitmap;</span>
<span class="line" id="L59"> header.max_value = <span class="tok-number">1</span>;</span>
<span class="line" id="L60"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P5&quot;</span>)) {</span>
<span class="line" id="L61"> header.binary = <span class="tok-null">true</span>;</span>
<span class="line" id="L62"> header.format = .grayscale;</span>
<span class="line" id="L63"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (std.mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P6&quot;</span>)) {</span>
<span class="line" id="L64"> header.binary = <span class="tok-null">true</span>;</span>
<span class="line" id="L65"> header.format = .rgb;</span>
<span class="line" id="L66"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L67"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">var</span> read_buffer: [<span class="tok-number">16</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L71"></span>
<span class="line" id="L72"> header.width = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L73"> header.height = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L74"> <span class="tok-kw">if</span> (header.format != .bitmap) {</span>
<span class="line" id="L75"> header.max_value = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L76"> }</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-kw">return</span> header;</span>
<span class="line" id="L79">}</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"><span class="tok-kw">fn</span> <span class="tok-fn">isWhitespace</span>(b: <span class="tok-type">u8</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (b) {</span>
<span class="line" id="L83"> <span class="tok-comment">// Whitespace (blanks, TABs, CRs, LFs).</span>
</span>
<span class="line" id="L84"> <span class="tok-str">'\n'</span>, <span class="tok-str">'\r'</span>, <span class="tok-str">' '</span>, <span class="tok-str">'\t'</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L85"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L86"> };</span>
<span class="line" id="L87">}</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"><span class="tok-kw">fn</span> <span class="tok-fn">readNextByte</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">u8</span> {</span>
<span class="line" id="L90"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L91"> <span class="tok-kw">const</span> b = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L92"> <span class="tok-kw">switch</span> (b) {</span>
<span class="line" id="L93"> <span class="tok-comment">// Before the whitespace character that delimits the raster, any characters</span>
</span>
<span class="line" id="L94"> <span class="tok-comment">// from a &quot;#&quot; through the next carriage return or newline character, is a</span>
</span>
<span class="line" id="L95"> <span class="tok-comment">// comment and is ignored. Note that this is rather unconventional, because</span>
</span>
<span class="line" id="L96"> <span class="tok-comment">// a comment can actually be in the middle of what you might consider a token.</span>
</span>
<span class="line" id="L97"> <span class="tok-comment">// Note also that this means if you have a comment right before the raster,</span>
</span>
<span class="line" id="L98"> <span class="tok-comment">// the newline at the end of the comment is not sufficient to delimit the raster.</span>
</span>
<span class="line" id="L99"> <span class="tok-str">'#'</span> =&gt; {</span>
<span class="line" id="L100"> <span class="tok-comment">// eat up comment</span>
</span>
<span class="line" id="L101"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L102"> <span class="tok-kw">const</span> c = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L103"> <span class="tok-kw">switch</span> (c) {</span>
<span class="line" id="L104"> <span class="tok-str">'\r'</span>, <span class="tok-str">'\n'</span> =&gt; <span class="tok-kw">break</span>,</span>
<span class="line" id="L105"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L106"> }</span>
<span class="line" id="L107"> }</span>
<span class="line" id="L108"> },</span>
<span class="line" id="L109"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> b,</span>
<span class="line" id="L110"> }</span>
<span class="line" id="L111"> }</span>
<span class="line" id="L112">}</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"><span class="tok-comment">/// skips whitespace and comments, then reads a number from the stream.</span></span>
<span class="line" id="L115"><span class="tok-comment">/// this function reads one whitespace behind the number as a terminator.</span></span>
<span class="line" id="L116"><span class="tok-kw">fn</span> <span class="tok-fn">parseNumber</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, buffer: []<span class="tok-type">u8</span>) ImageReadError!<span class="tok-type">usize</span> {</span>
<span class="line" id="L117"> <span class="tok-kw">var</span> input_length: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L118"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> b = <span class="tok-kw">try</span> readNextByte(reader);</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (isWhitespace(b)) {</span>
<span class="line" id="L121"> <span class="tok-kw">if</span> (input_length &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L122"> <span class="tok-kw">return</span> std.fmt.parseInt(<span class="tok-type">usize</span>, buffer[<span class="tok-number">0</span>..input_length], <span class="tok-number">10</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L123"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L124"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L125"> }</span>
<span class="line" id="L126"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (input_length &gt;= buffer.len)</span>
<span class="line" id="L128"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.OutOfMemory;</span>
<span class="line" id="L129"> buffer[input_length] = b;</span>
<span class="line" id="L130"> input_length += <span class="tok-number">1</span>;</span>
<span class="line" id="L131"> }</span>
<span class="line" id="L132"> }</span>
<span class="line" id="L133">}</span>
<span class="line" id="L134"></span>
<span class="line" id="L135"><span class="tok-kw">fn</span> <span class="tok-fn">loadBinaryBitmap</span>(header: Header, data: []color.Grayscale1, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L136"> <span class="tok-kw">var</span> bit_reader = std.io.bitReader(.big, reader);</span>
<span class="line" id="L137"></span>
<span class="line" id="L138"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..header.height) |row_index| {</span>
<span class="line" id="L139"> <span class="tok-kw">for</span> (data[row_index * header.width ..][<span class="tok-number">0</span>..header.width]) |*sample| {</span>
<span class="line" id="L140"> sample.value = ~(<span class="tok-kw">try</span> bit_reader.readBitsNoEof(<span class="tok-type">u1</span>, <span class="tok-number">1</span>));</span>
<span class="line" id="L141"> }</span>
<span class="line" id="L142"> bit_reader.alignToByte();</span>
<span class="line" id="L143"> }</span>
<span class="line" id="L144">}</span>
<span class="line" id="L145"></span>
<span class="line" id="L146"><span class="tok-kw">fn</span> <span class="tok-fn">loadAsciiBitmap</span>(header: Header, data: []color.Grayscale1, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L147"> <span class="tok-kw">var</span> data_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L148"> <span class="tok-kw">const</span> data_end = header.width * header.height;</span>
<span class="line" id="L149"></span>
<span class="line" id="L150"> <span class="tok-kw">while</span> (data_index &lt; data_end) {</span>
<span class="line" id="L151"> <span class="tok-kw">const</span> b = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L152"> <span class="tok-kw">if</span> (isWhitespace(b)) {</span>
<span class="line" id="L153"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"></span>
<span class="line" id="L156"> <span class="tok-comment">// 1 is black, 0 is white in PBM spec.</span>
</span>
<span class="line" id="L157"> <span class="tok-comment">// we use 1=white, 0=black in u1 format</span>
</span>
<span class="line" id="L158"> <span class="tok-kw">const</span> pixel = <span class="tok-kw">if</span> (b == <span class="tok-str">'0'</span>) <span class="tok-builtin">@as</span>(<span class="tok-type">u1</span>, <span class="tok-number">1</span>) <span class="tok-kw">else</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u1</span>, <span class="tok-number">0</span>);</span>
<span class="line" id="L159"> data[data_index] = color.Grayscale1{ .value = pixel };</span>
<span class="line" id="L160"></span>
<span class="line" id="L161"> data_index += <span class="tok-number">1</span>;</span>
<span class="line" id="L162"> }</span>
<span class="line" id="L163">}</span>
<span class="line" id="L164"></span>
<span class="line" id="L165"><span class="tok-kw">fn</span> <span class="tok-fn">readLinearizedValue</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader, max_value: <span class="tok-type">usize</span>) ImageReadError!<span class="tok-type">u8</span> {</span>
<span class="line" id="L166"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (max_value &gt; <span class="tok-number">255</span>)</span>
<span class="line" id="L167"> <span class="tok-builtin">@truncate</span>(<span class="tok-number">255</span> * <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big)) / max_value)</span>
<span class="line" id="L168"> <span class="tok-kw">else</span></span>
<span class="line" id="L169"> <span class="tok-builtin">@truncate</span>(<span class="tok-number">255</span> * <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-kw">try</span> reader.readByte()) / max_value);</span>
<span class="line" id="L170">}</span>
<span class="line" id="L171"></span>
<span class="line" id="L172"><span class="tok-kw">fn</span> <span class="tok-fn">loadBinaryGraymap</span>(header: Header, pixels: *color.PixelStorage, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L173"> <span class="tok-kw">var</span> data_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L174"> <span class="tok-kw">const</span> data_end = header.width * header.height;</span>
<span class="line" id="L175"> <span class="tok-kw">if</span> (header.max_value &lt;= <span class="tok-number">255</span>) {</span>
<span class="line" id="L176"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L177"> pixels.grayscale8[data_index] = color.Grayscale8{ .value = <span class="tok-kw">try</span> readLinearizedValue(reader, header.max_value) };</span>
<span class="line" id="L178"> }</span>
<span class="line" id="L179"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L180"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L181"> pixels.grayscale16[data_index] = color.Grayscale16{ .value = <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .big) };</span>
<span class="line" id="L182"> }</span>
<span class="line" id="L183"> }</span>
<span class="line" id="L184">}</span>
<span class="line" id="L185"></span>
<span class="line" id="L186"><span class="tok-kw">fn</span> <span class="tok-fn">loadAsciiGraymap</span>(header: Header, pixels: *color.PixelStorage, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L187"> <span class="tok-kw">var</span> read_buffer: [<span class="tok-number">16</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-kw">var</span> data_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L190"> <span class="tok-kw">const</span> data_end = header.width * header.height;</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> <span class="tok-kw">if</span> (header.max_value &lt;= <span class="tok-number">255</span>) {</span>
<span class="line" id="L193"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L194"> pixels.grayscale8[data_index] = color.Grayscale8{ .value = <span class="tok-builtin">@truncate</span>(<span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..])) };</span>
<span class="line" id="L195"> }</span>
<span class="line" id="L196"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L197"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L198"> pixels.grayscale16[data_index] = color.Grayscale16{ .value = <span class="tok-builtin">@truncate</span>(<span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..])) };</span>
<span class="line" id="L199"> }</span>
<span class="line" id="L200"> }</span>
<span class="line" id="L201">}</span>
<span class="line" id="L202"></span>
<span class="line" id="L203"><span class="tok-kw">fn</span> <span class="tok-fn">loadBinaryRgbmap</span>(header: Header, data: []color.Rgb24, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L204"> <span class="tok-kw">var</span> data_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L205"> <span class="tok-kw">const</span> data_end = header.width * header.height;</span>
<span class="line" id="L206"></span>
<span class="line" id="L207"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L208"> data[data_index] = color.Rgb24{</span>
<span class="line" id="L209"> .r = <span class="tok-kw">try</span> readLinearizedValue(reader, header.max_value),</span>
<span class="line" id="L210"> .g = <span class="tok-kw">try</span> readLinearizedValue(reader, header.max_value),</span>
<span class="line" id="L211"> .b = <span class="tok-kw">try</span> readLinearizedValue(reader, header.max_value),</span>
<span class="line" id="L212"> };</span>
<span class="line" id="L213"> }</span>
<span class="line" id="L214">}</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"><span class="tok-kw">fn</span> <span class="tok-fn">loadAsciiRgbmap</span>(header: Header, data: []color.Rgb24, reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L217"> <span class="tok-kw">var</span> read_buffer: [<span class="tok-number">16</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L218"></span>
<span class="line" id="L219"> <span class="tok-kw">var</span> data_index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L220"> <span class="tok-kw">const</span> data_end = header.width * header.height;</span>
<span class="line" id="L221"></span>
<span class="line" id="L222"> <span class="tok-kw">while</span> (data_index &lt; data_end) : (data_index += <span class="tok-number">1</span>) {</span>
<span class="line" id="L223"> <span class="tok-kw">const</span> r = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L224"> <span class="tok-kw">const</span> g = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L225"> <span class="tok-kw">const</span> b = <span class="tok-kw">try</span> parseNumber(reader, read_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L226"></span>
<span class="line" id="L227"> data[data_index] = color.Rgb24{</span>
<span class="line" id="L228"> .r = <span class="tok-builtin">@truncate</span>(<span class="tok-number">255</span> * r / header.max_value),</span>
<span class="line" id="L229"> .g = <span class="tok-builtin">@truncate</span>(<span class="tok-number">255</span> * g / header.max_value),</span>
<span class="line" id="L230"> .b = <span class="tok-builtin">@truncate</span>(<span class="tok-number">255</span> * b / header.max_value),</span>
<span class="line" id="L231"> };</span>
<span class="line" id="L232"> }</span>
<span class="line" id="L233">}</span>
<span class="line" id="L234"></span>
<span class="line" id="L235"><span class="tok-kw">fn</span> <span class="tok-fn">Netpbm</span>(<span class="tok-kw">comptime</span> image_format: Image.Format, <span class="tok-kw">comptime</span> header_numbers: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L236"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L237"> header: Header = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L238"></span>
<span class="line" id="L239"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L240"></span>
<span class="line" id="L241"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L242"> binary: <span class="tok-type">bool</span> = <span class="tok-null">true</span>,</span>
<span class="line" id="L243"> };</span>
<span class="line" id="L244"></span>
<span class="line" id="L245"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L246"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L247"> .format = format,</span>
<span class="line" id="L248"> .formatDetect = formatDetect,</span>
<span class="line" id="L249"> .readImage = readImage,</span>
<span class="line" id="L250"> .writeImage = writeImage,</span>
<span class="line" id="L251"> };</span>
<span class="line" id="L252"> }</span>
<span class="line" id="L253"></span>
<span class="line" id="L254"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L255"> <span class="tok-kw">return</span> image_format;</span>
<span class="line" id="L256"> }</span>
<span class="line" id="L257"></span>
<span class="line" id="L258"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L259"> <span class="tok-kw">var</span> magic_number_buffer: [<span class="tok-number">2</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L260"> _ = <span class="tok-kw">try</span> stream.read(magic_number_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L261"></span>
<span class="line" id="L262"> <span class="tok-kw">if</span> (magic_number_buffer[<span class="tok-number">0</span>] != <span class="tok-str">'P'</span>) {</span>
<span class="line" id="L263"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L264"> }</span>
<span class="line" id="L265"></span>
<span class="line" id="L266"> <span class="tok-kw">var</span> found = <span class="tok-null">false</span>;</span>
<span class="line" id="L267"></span>
<span class="line" id="L268"> <span class="tok-kw">for</span> (header_numbers) |number| {</span>
<span class="line" id="L269"> <span class="tok-kw">if</span> (magic_number_buffer[<span class="tok-number">1</span>] == number) {</span>
<span class="line" id="L270"> found = <span class="tok-null">true</span>;</span>
<span class="line" id="L271"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L272"> }</span>
<span class="line" id="L273"> }</span>
<span class="line" id="L274"></span>
<span class="line" id="L275"> <span class="tok-kw">return</span> found;</span>
<span class="line" id="L276"> }</span>
<span class="line" id="L277"></span>
<span class="line" id="L278"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L279"> <span class="tok-kw">var</span> result = Image.init(allocator);</span>
<span class="line" id="L280"> <span class="tok-kw">errdefer</span> result.deinit();</span>
<span class="line" id="L281"> <span class="tok-kw">var</span> netpbm_file = Self{};</span>
<span class="line" id="L282"></span>
<span class="line" id="L283"> <span class="tok-kw">const</span> pixels = <span class="tok-kw">try</span> netpbm_file.read(allocator, stream);</span>
<span class="line" id="L284"></span>
<span class="line" id="L285"> result.width = netpbm_file.header.width;</span>
<span class="line" id="L286"> result.height = netpbm_file.header.height;</span>
<span class="line" id="L287"> result.pixels = pixels;</span>
<span class="line" id="L288"></span>
<span class="line" id="L289"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L290"> }</span>
<span class="line" id="L291"></span>
<span class="line" id="L292"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L293"> _ = allocator;</span>
<span class="line" id="L294"></span>
<span class="line" id="L295"> <span class="tok-kw">var</span> netpbm_file = Self{};</span>
<span class="line" id="L296"> netpbm_file.header.binary = <span class="tok-kw">switch</span> (encoder_options) {</span>
<span class="line" id="L297"> .pbm =&gt; |options| options.binary,</span>
<span class="line" id="L298"> .pgm =&gt; |options| options.binary,</span>
<span class="line" id="L299"> .ppm =&gt; |options| options.binary,</span>
<span class="line" id="L300"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L301"> };</span>
<span class="line" id="L302"></span>
<span class="line" id="L303"> netpbm_file.header.width = image.width;</span>
<span class="line" id="L304"> netpbm_file.header.height = image.height;</span>
<span class="line" id="L305"> netpbm_file.header.format = <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L306"> .grayscale1 =&gt; Format.bitmap,</span>
<span class="line" id="L307"> .grayscale8, .grayscale16 =&gt; Format.grayscale,</span>
<span class="line" id="L308"> .rgb24 =&gt; Format.rgb,</span>
<span class="line" id="L309"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L310"> };</span>
<span class="line" id="L311"></span>
<span class="line" id="L312"> netpbm_file.header.max_value = <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L313"> .grayscale16 =&gt; std.math.maxInt(<span class="tok-type">u16</span>),</span>
<span class="line" id="L314"> .grayscale1 =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L315"> <span class="tok-kw">else</span> =&gt; std.math.maxInt(<span class="tok-type">u8</span>),</span>
<span class="line" id="L316"> };</span>
<span class="line" id="L317"></span>
<span class="line" id="L318"> <span class="tok-kw">try</span> netpbm_file.write(write_stream, image.pixels);</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"></span>
<span class="line" id="L321"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelFormat</span>(self: Self) ImageReadError!PixelFormat {</span>
<span class="line" id="L322"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.header.format) {</span>
<span class="line" id="L323"> .bitmap =&gt; PixelFormat.grayscale1,</span>
<span class="line" id="L324"> .grayscale =&gt; <span class="tok-kw">switch</span> (self.header.max_value) {</span>
<span class="line" id="L325"> <span class="tok-number">0</span>...<span class="tok-number">255</span> =&gt; PixelFormat.grayscale8,</span>
<span class="line" id="L326"> <span class="tok-kw">else</span> =&gt; PixelFormat.grayscale16,</span>
<span class="line" id="L327"> },</span>
<span class="line" id="L328"> .rgb =&gt; PixelFormat.rgb24,</span>
<span class="line" id="L329"> };</span>
<span class="line" id="L330"> }</span>
<span class="line" id="L331"></span>
<span class="line" id="L332"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *Self, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {</span>
<span class="line" id="L333"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L334"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L335"> self.header = <span class="tok-kw">try</span> parseHeader(reader);</span>
<span class="line" id="L336"></span>
<span class="line" id="L337"> <span class="tok-kw">const</span> pixel_format = <span class="tok-kw">try</span> self.pixelFormat();</span>
<span class="line" id="L338"></span>
<span class="line" id="L339"> <span class="tok-kw">var</span> pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, self.header.width * self.header.height);</span>
<span class="line" id="L340"> <span class="tok-kw">errdefer</span> pixels.deinit(allocator);</span>
<span class="line" id="L341"></span>
<span class="line" id="L342"> <span class="tok-kw">switch</span> (self.header.format) {</span>
<span class="line" id="L343"> .bitmap =&gt; {</span>
<span class="line" id="L344"> <span class="tok-kw">if</span> (self.header.binary) {</span>
<span class="line" id="L345"> <span class="tok-kw">try</span> loadBinaryBitmap(self.header, pixels.grayscale1, reader);</span>
<span class="line" id="L346"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L347"> <span class="tok-kw">try</span> loadAsciiBitmap(self.header, pixels.grayscale1, reader);</span>
<span class="line" id="L348"> }</span>
<span class="line" id="L349"> },</span>
<span class="line" id="L350"> .grayscale =&gt; {</span>
<span class="line" id="L351"> <span class="tok-kw">if</span> (self.header.binary) {</span>
<span class="line" id="L352"> <span class="tok-kw">try</span> loadBinaryGraymap(self.header, &amp;pixels, reader);</span>
<span class="line" id="L353"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L354"> <span class="tok-kw">try</span> loadAsciiGraymap(self.header, &amp;pixels, reader);</span>
<span class="line" id="L355"> }</span>
<span class="line" id="L356"> },</span>
<span class="line" id="L357"> .rgb =&gt; {</span>
<span class="line" id="L358"> <span class="tok-kw">if</span> (self.header.binary) {</span>
<span class="line" id="L359"> <span class="tok-kw">try</span> loadBinaryRgbmap(self.header, pixels.rgb24, reader);</span>
<span class="line" id="L360"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L361"> <span class="tok-kw">try</span> loadAsciiRgbmap(self.header, pixels.rgb24, reader);</span>
<span class="line" id="L362"> }</span>
<span class="line" id="L363"> },</span>
<span class="line" id="L364"> }</span>
<span class="line" id="L365"></span>
<span class="line" id="L366"> <span class="tok-kw">return</span> pixels;</span>
<span class="line" id="L367"> }</span>
<span class="line" id="L368"></span>
<span class="line" id="L369"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Self, write_stream: *Image.Stream, pixels: color.PixelStorage) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L370"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(write_stream);</span>
<span class="line" id="L371"></span>
<span class="line" id="L372"> <span class="tok-kw">const</span> image_type = <span class="tok-kw">if</span> (self.header.binary) header_numbers[<span class="tok-number">1</span>] <span class="tok-kw">else</span> header_numbers[<span class="tok-number">0</span>];</span>
<span class="line" id="L373"> <span class="tok-kw">const</span> writer = buffered_stream.writer();</span>
<span class="line" id="L374"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;P{c}\n&quot;</span>, .{image_type});</span>
<span class="line" id="L375"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot;# Created by zigimg\n&quot;</span>);</span>
<span class="line" id="L376"></span>
<span class="line" id="L377"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{} {}\n&quot;</span>, .{ self.header.width, self.header.height });</span>
<span class="line" id="L378"></span>
<span class="line" id="L379"> <span class="tok-kw">if</span> (self.header.format != .bitmap) {</span>
<span class="line" id="L380"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{}\n&quot;</span>, .{self.header.max_value});</span>
<span class="line" id="L381"> }</span>
<span class="line" id="L382"></span>
<span class="line" id="L383"> <span class="tok-kw">if</span> (self.header.binary) {</span>
<span class="line" id="L384"> <span class="tok-kw">switch</span> (self.header.format) {</span>
<span class="line" id="L385"> .bitmap =&gt; {</span>
<span class="line" id="L386"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L387"> .grayscale1 =&gt; |samples| {</span>
<span class="line" id="L388"> <span class="tok-kw">var</span> bit_writer = std.io.bitWriter(.big, writer);</span>
<span class="line" id="L389"></span>
<span class="line" id="L390"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..self.header.height) |row_index| {</span>
<span class="line" id="L391"> <span class="tok-kw">for</span> (samples[row_index * self.header.width ..][<span class="tok-number">0</span>..self.header.width]) |sample| {</span>
<span class="line" id="L392"> <span class="tok-kw">try</span> bit_writer.writeBits(~sample.value, <span class="tok-number">1</span>);</span>
<span class="line" id="L393"> }</span>
<span class="line" id="L394"> <span class="tok-kw">try</span> bit_writer.flushBits();</span>
<span class="line" id="L395"> }</span>
<span class="line" id="L396"> },</span>
<span class="line" id="L397"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L398"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L399"> },</span>
<span class="line" id="L400"> }</span>
<span class="line" id="L401"> },</span>
<span class="line" id="L402"> .grayscale =&gt; {</span>
<span class="line" id="L403"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L404"> .grayscale16 =&gt; {</span>
<span class="line" id="L405"> <span class="tok-kw">for</span> (pixels.grayscale16) |entry| {</span>
<span class="line" id="L406"> <span class="tok-comment">// Big due to 16-bit PGM being semi standardized as big-endian</span>
</span>
<span class="line" id="L407"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, entry.value, .big);</span>
<span class="line" id="L408"> }</span>
<span class="line" id="L409"> },</span>
<span class="line" id="L410"> .grayscale8 =&gt; {</span>
<span class="line" id="L411"> <span class="tok-kw">for</span> (pixels.grayscale8) |entry| {</span>
<span class="line" id="L412"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u8</span>, entry.value, .little);</span>
<span class="line" id="L413"> }</span>
<span class="line" id="L414"> },</span>
<span class="line" id="L415"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L416"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L417"> },</span>
<span class="line" id="L418"> }</span>
<span class="line" id="L419"> },</span>
<span class="line" id="L420"> .rgb =&gt; {</span>
<span class="line" id="L421"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L422"> .rgb24 =&gt; {</span>
<span class="line" id="L423"> <span class="tok-kw">for</span> (pixels.rgb24) |entry| {</span>
<span class="line" id="L424"> <span class="tok-kw">try</span> writer.writeByte(entry.r);</span>
<span class="line" id="L425"> <span class="tok-kw">try</span> writer.writeByte(entry.g);</span>
<span class="line" id="L426"> <span class="tok-kw">try</span> writer.writeByte(entry.b);</span>
<span class="line" id="L427"> }</span>
<span class="line" id="L428"> },</span>
<span class="line" id="L429"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L430"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L431"> },</span>
<span class="line" id="L432"> }</span>
<span class="line" id="L433"> },</span>
<span class="line" id="L434"> }</span>
<span class="line" id="L435"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L436"> <span class="tok-kw">switch</span> (self.header.format) {</span>
<span class="line" id="L437"> .bitmap =&gt; {</span>
<span class="line" id="L438"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L439"> .grayscale1 =&gt; {</span>
<span class="line" id="L440"> <span class="tok-kw">for</span> (pixels.grayscale1) |entry| {</span>
<span class="line" id="L441"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{}&quot;</span>, .{~entry.value});</span>
<span class="line" id="L442"> }</span>
<span class="line" id="L443"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot;\n&quot;</span>);</span>
<span class="line" id="L444"> },</span>
<span class="line" id="L445"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L446"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L447"> },</span>
<span class="line" id="L448"> }</span>
<span class="line" id="L449"> },</span>
<span class="line" id="L450"> .grayscale =&gt; {</span>
<span class="line" id="L451"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L452"> .grayscale16 =&gt; {</span>
<span class="line" id="L453"> <span class="tok-kw">const</span> pixels_len = pixels.len();</span>
<span class="line" id="L454"> <span class="tok-kw">for</span> (pixels.grayscale16, <span class="tok-number">0</span>..) |entry, index| {</span>
<span class="line" id="L455"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{}&quot;</span>, .{entry.value});</span>
<span class="line" id="L456"></span>
<span class="line" id="L457"> <span class="tok-kw">if</span> (index != (pixels_len - <span class="tok-number">1</span>)) {</span>
<span class="line" id="L458"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot; &quot;</span>);</span>
<span class="line" id="L459"> }</span>
<span class="line" id="L460"> }</span>
<span class="line" id="L461"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot;\n&quot;</span>);</span>
<span class="line" id="L462"> },</span>
<span class="line" id="L463"> .grayscale8 =&gt; {</span>
<span class="line" id="L464"> <span class="tok-kw">const</span> pixels_len = pixels.len();</span>
<span class="line" id="L465"> <span class="tok-kw">for</span> (pixels.grayscale8, <span class="tok-number">0</span>..) |entry, index| {</span>
<span class="line" id="L466"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{}&quot;</span>, .{entry.value});</span>
<span class="line" id="L467"></span>
<span class="line" id="L468"> <span class="tok-kw">if</span> (index != (pixels_len - <span class="tok-number">1</span>)) {</span>
<span class="line" id="L469"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot; &quot;</span>);</span>
<span class="line" id="L470"> }</span>
<span class="line" id="L471"> }</span>
<span class="line" id="L472"> _ = <span class="tok-kw">try</span> writer.write(<span class="tok-str">&quot;\n&quot;</span>);</span>
<span class="line" id="L473"> },</span>
<span class="line" id="L474"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L475"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L476"> },</span>
<span class="line" id="L477"> }</span>
<span class="line" id="L478"> },</span>
<span class="line" id="L479"> .rgb =&gt; {</span>
<span class="line" id="L480"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L481"> .rgb24 =&gt; {</span>
<span class="line" id="L482"> <span class="tok-kw">for</span> (pixels.rgb24) |entry| {</span>
<span class="line" id="L483"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;{} {} {}\n&quot;</span>, .{ entry.r, entry.g, entry.b });</span>
<span class="line" id="L484"> }</span>
<span class="line" id="L485"> },</span>
<span class="line" id="L486"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L487"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L488"> },</span>
<span class="line" id="L489"> }</span>
<span class="line" id="L490"> },</span>
<span class="line" id="L491"> }</span>
<span class="line" id="L492"> }</span>
<span class="line" id="L493"></span>
<span class="line" id="L494"> <span class="tok-kw">try</span> buffered_stream.flush();</span>
<span class="line" id="L495"> }</span>
<span class="line" id="L496"> };</span>
<span class="line" id="L497">}</span>
<span class="line" id="L498"></span>
<span class="line" id="L499"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PBM = Netpbm(Image.Format.pbm, &amp;[_]<span class="tok-type">u8</span>{ <span class="tok-str">'1'</span>, <span class="tok-str">'4'</span> });</span>
<span class="line" id="L500"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PGM = Netpbm(Image.Format.pgm, &amp;[_]<span class="tok-type">u8</span>{ <span class="tok-str">'2'</span>, <span class="tok-str">'5'</span> });</span>
<span class="line" id="L501"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PPM = Netpbm(Image.Format.ppm, &amp;[_]<span class="tok-type">u8</span>{ <span class="tok-str">'3'</span>, <span class="tok-str">'6'</span> });</span>
<span class="line" id="L502"></span>
</code></pre></body>
</html>

View file

@ -1,694 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/pam.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> io = std.io;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> mem = std.mem;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> math = std.math;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> ascii = std.ascii;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> fmt = std.fmt;</span>
<span class="line" id="L7"><span class="tok-kw">const</span> meta = std.meta;</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L11"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L12"><span class="tok-kw">const</span> PixelStorage = color.PixelStorage;</span>
<span class="line" id="L13"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L14"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L15"><span class="tok-kw">const</span> ImageError = Image.Error;</span>
<span class="line" id="L16"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L17"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L18"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../utils.zig&quot;</span>);</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-comment">/// Represents all supported values for `TUPLTYPE`.</span></span>
<span class="line" id="L21"><span class="tok-kw">const</span> TupleType = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L22"> mono,</span>
<span class="line" id="L23"> mono_a,</span>
<span class="line" id="L24"> gray,</span>
<span class="line" id="L25"> gray_a,</span>
<span class="line" id="L26"> rgb,</span>
<span class="line" id="L27"> rgb_a,</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"> <span class="tok-comment">/// Returns the `TupleType` corresponding to `string`, or</span></span>
<span class="line" id="L30"> <span class="tok-comment">/// `error.Unsupported` if it is unknown.</span></span>
<span class="line" id="L31"> <span class="tok-kw">fn</span> <span class="tok-fn">fromString</span>(string: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-kw">error</span>{Unsupported}!TupleType {</span>
<span class="line" id="L32"> <span class="tok-comment">// zig fmt: off</span>
</span>
<span class="line" id="L33"> <span class="tok-kw">return</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;BLACKANDWHITE&quot;</span>)) .mono</span>
<span class="line" id="L34"> <span class="tok-kw">else</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;BLACKANDWHITE_ALPHA&quot;</span>)) .mono_a</span>
<span class="line" id="L35"> <span class="tok-kw">else</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;GRAYSCALE&quot;</span>)) .gray</span>
<span class="line" id="L36"> <span class="tok-kw">else</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;GRAYSCALE_ALPHA&quot;</span>)) .gray_a</span>
<span class="line" id="L37"> <span class="tok-kw">else</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;RGB&quot;</span>)) .rgb</span>
<span class="line" id="L38"> <span class="tok-kw">else</span> <span class="tok-kw">if</span>(mem.eql(<span class="tok-type">u8</span>, string, <span class="tok-str">&quot;RGB_ALPHA&quot;</span>)) .rgb_a</span>
<span class="line" id="L39"> <span class="tok-kw">else</span> <span class="tok-kw">error</span>.Unsupported; <span class="tok-comment">// Unknown tuple type</span>
</span>
<span class="line" id="L40"> <span class="tok-comment">// zig fmt: on</span>
</span>
<span class="line" id="L41"> }</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"> <span class="tok-comment">/// Returns the `TUPLTYPE` string representation of `tuple_type`.</span></span>
<span class="line" id="L44"> <span class="tok-kw">fn</span> <span class="tok-fn">toString</span>(tuple_type: TupleType) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L45"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (tuple_type) {</span>
<span class="line" id="L46"> .mono =&gt; <span class="tok-str">&quot;BLACKANDWHITE&quot;</span>,</span>
<span class="line" id="L47"> .mono_a =&gt; <span class="tok-str">&quot;BLACKANDWHITE_ALPHA&quot;</span>,</span>
<span class="line" id="L48"> .gray =&gt; <span class="tok-str">&quot;GRAYSCALE&quot;</span>,</span>
<span class="line" id="L49"> .gray_a =&gt; <span class="tok-str">&quot;GRAYSCALE_ALPHA&quot;</span>,</span>
<span class="line" id="L50"> .rgb =&gt; <span class="tok-str">&quot;RGB&quot;</span>,</span>
<span class="line" id="L51"> .rgb_a =&gt; <span class="tok-str">&quot;RGB_ALPHA&quot;</span>,</span>
<span class="line" id="L52"> };</span>
<span class="line" id="L53"> }</span>
<span class="line" id="L54">};</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"><span class="tok-comment">/// Represents a PAM header.</span></span>
<span class="line" id="L57"><span class="tok-kw">const</span> Header = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L58"> <span class="tok-comment">/// Number of pixels in a row.</span></span>
<span class="line" id="L59"> width: <span class="tok-type">usize</span>,</span>
<span class="line" id="L60"> <span class="tok-comment">/// Number of rows.</span></span>
<span class="line" id="L61"> height: <span class="tok-type">usize</span>,</span>
<span class="line" id="L62"> <span class="tok-comment">/// Number of components per pixels.</span></span>
<span class="line" id="L63"> depth: <span class="tok-type">usize</span>,</span>
<span class="line" id="L64"> <span class="tok-comment">/// Maximum value of a component.</span></span>
<span class="line" id="L65"> maxval: <span class="tok-type">u16</span>,</span>
<span class="line" id="L66"> <span class="tok-comment">/// Tuple type of the image.</span></span>
<span class="line" id="L67"> tuple_type: TupleType,</span>
<span class="line" id="L68"> <span class="tok-comment">/// Arbitrary text comments. Note that comment position inside the</span></span>
<span class="line" id="L69"> <span class="tok-comment">/// header is not preserved.</span></span>
<span class="line" id="L70"> comments: []<span class="tok-kw">const</span> []<span class="tok-kw">const</span> <span class="tok-type">u8</span>,</span>
<span class="line" id="L71"></span>
<span class="line" id="L72"> <span class="tok-comment">/// Reads a header from `reader`, using `allocator` to allocate</span></span>
<span class="line" id="L73"> <span class="tok-comment">/// memory. Returns that header, `error.Unsupported` if the tuple</span></span>
<span class="line" id="L74"> <span class="tok-comment">/// type is not known to us, `error.OutOfMemory` if allocation</span></span>
<span class="line" id="L75"> <span class="tok-comment">/// fails, `error.InvalidData` if the header does not conform to</span></span>
<span class="line" id="L76"> <span class="tok-comment">/// the PAM specification, or another error specific to `reader`</span></span>
<span class="line" id="L77"> <span class="tok-comment">/// if reading fails.</span></span>
<span class="line" id="L78"> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(allocator: Allocator, reader: <span class="tok-kw">anytype</span>) (<span class="tok-kw">error</span>{ InvalidData, Unsupported, OutOfMemory, EndOfStream, StreamTooLong } || <span class="tok-builtin">@TypeOf</span>(reader).Error)!Header {</span>
<span class="line" id="L79"> <span class="tok-kw">var</span> maybe_width: ?<span class="tok-type">usize</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L80"> <span class="tok-kw">var</span> maybe_height: ?<span class="tok-type">usize</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L81"> <span class="tok-kw">var</span> maybe_depth: ?<span class="tok-type">usize</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L82"> <span class="tok-kw">var</span> maybe_maxval: ?<span class="tok-type">u16</span> = <span class="tok-null">null</span>;</span>
<span class="line" id="L83"> <span class="tok-kw">var</span> maybe_tuple_type: ?TupleType = <span class="tok-null">null</span>;</span>
<span class="line" id="L84"> <span class="tok-kw">var</span> comments = std.ArrayListUnmanaged([]<span class="tok-kw">const</span> <span class="tok-type">u8</span>){};</span>
<span class="line" id="L85"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L86"> <span class="tok-kw">for</span> (comments.items) |comment| allocator.free(comment);</span>
<span class="line" id="L87"> comments.deinit(allocator);</span>
<span class="line" id="L88"> }</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> {</span>
<span class="line" id="L91"> <span class="tok-kw">var</span> buf = <span class="tok-kw">try</span> std.ArrayList(<span class="tok-type">u8</span>).initCapacity(allocator, <span class="tok-number">32</span>);</span>
<span class="line" id="L92"> <span class="tok-kw">defer</span> buf.deinit();</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L95"> <span class="tok-comment">// we fail on EOS here because a valid pam header must end with ENDHDR</span>
</span>
<span class="line" id="L96"> <span class="tok-kw">try</span> reader.readUntilDelimiterArrayList(&amp;buf, <span class="tok-str">'\n'</span>, math.maxInt(<span class="tok-type">usize</span>));</span>
<span class="line" id="L97"> <span class="tok-kw">const</span> line = buf.items; <span class="tok-comment">// empty lines are meaningless</span>
</span>
<span class="line" id="L98"> <span class="tok-kw">if</span> (line.len == <span class="tok-number">0</span>) <span class="tok-kw">continue</span>;</span>
<span class="line" id="L99"> <span class="tok-kw">if</span> (line[<span class="tok-number">0</span>] == <span class="tok-str">'#'</span>) { <span class="tok-comment">// comment</span>
</span>
<span class="line" id="L100"> <span class="tok-kw">try</span> comments.append(allocator, <span class="tok-kw">try</span> allocator.dupe(<span class="tok-type">u8</span>, line[<span class="tok-number">1</span>..]));</span>
<span class="line" id="L101"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"> <span class="tok-kw">var</span> tok_iter = mem.tokenize(<span class="tok-type">u8</span>, line, &amp;ascii.whitespace);</span>
<span class="line" id="L105"> <span class="tok-kw">const</span> first_token = tok_iter.next() <span class="tok-kw">orelse</span> <span class="tok-kw">continue</span>; <span class="tok-comment">// lines with 0 tokens are meaningless</span>
</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (first_token.len &gt; <span class="tok-number">8</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// the first token must be at most 8 bytes</span>
</span>
<span class="line" id="L108"></span>
<span class="line" id="L109"> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;ENDHDR&quot;</span>)) <span class="tok-kw">break</span>;</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;TUPLTYPE&quot;</span>)) {</span>
<span class="line" id="L112"> maybe_tuple_type = <span class="tok-kw">try</span> TupleType.fromString(tok_iter.rest());</span>
<span class="line" id="L113"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L114"> }</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-kw">const</span> second_token = tok_iter.next() <span class="tok-kw">orelse</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad token</span>
</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;WIDTH&quot;</span>)) {</span>
<span class="line" id="L119"> maybe_width = fmt.parseUnsigned(<span class="tok-type">usize</span>, second_token, <span class="tok-number">10</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad width</span>
</span>
<span class="line" id="L120"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;HEIGHT&quot;</span>)) {</span>
<span class="line" id="L121"> maybe_height = fmt.parseUnsigned(<span class="tok-type">usize</span>, second_token, <span class="tok-number">10</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad height</span>
</span>
<span class="line" id="L122"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;DEPTH&quot;</span>)) {</span>
<span class="line" id="L123"> maybe_depth = fmt.parseUnsigned(<span class="tok-type">usize</span>, second_token, <span class="tok-number">10</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad depth</span>
</span>
<span class="line" id="L124"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (mem.eql(<span class="tok-type">u8</span>, first_token, <span class="tok-str">&quot;MAXVAL&quot;</span>)) {</span>
<span class="line" id="L125"> maybe_maxval = fmt.parseUnsigned(<span class="tok-type">u16</span>, second_token, <span class="tok-number">10</span>) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad maxval</span>
</span>
<span class="line" id="L126"> } <span class="tok-kw">else</span> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// invalid first token</span>
</span>
<span class="line" id="L127"> }</span>
<span class="line" id="L128"> }</span>
<span class="line" id="L129"></span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (maybe_height == <span class="tok-null">null</span> <span class="tok-kw">or</span> maybe_width == <span class="tok-null">null</span> <span class="tok-kw">or</span> maybe_maxval == <span class="tok-null">null</span> <span class="tok-kw">or</span> maybe_depth == <span class="tok-null">null</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// missing values</span>
</span>
<span class="line" id="L131"> <span class="tok-kw">if</span> (maybe_height.? &lt; <span class="tok-number">1</span> <span class="tok-kw">or</span> maybe_width.? &lt; <span class="tok-number">1</span> <span class="tok-kw">or</span> maybe_maxval.? &lt; <span class="tok-number">1</span>) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// bad width, height, or maxval</span>
</span>
<span class="line" id="L132"> <span class="tok-kw">if</span> (maybe_tuple_type == <span class="tok-null">null</span>) { <span class="tok-comment">// guess tuple type</span>
</span>
<span class="line" id="L133"> <span class="tok-kw">const</span> depth = maybe_depth.?;</span>
<span class="line" id="L134"> <span class="tok-kw">const</span> maxval = maybe_maxval.?;</span>
<span class="line" id="L135"> maybe_tuple_type = <span class="tok-kw">switch</span> (depth) {</span>
<span class="line" id="L136"> <span class="tok-number">1</span> =&gt; <span class="tok-kw">if</span> (maxval == <span class="tok-number">1</span>) TupleType.mono <span class="tok-kw">else</span> TupleType.gray,</span>
<span class="line" id="L137"> <span class="tok-number">2</span> =&gt; <span class="tok-kw">if</span> (maxval == <span class="tok-number">1</span>) TupleType.mono_a <span class="tok-kw">else</span> TupleType.gray_a,</span>
<span class="line" id="L138"> <span class="tok-number">3</span> =&gt; TupleType.rgb,</span>
<span class="line" id="L139"> <span class="tok-number">4</span> =&gt; TupleType.rgb_a,</span>
<span class="line" id="L140"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported, <span class="tok-comment">// can't guess tuple type</span>
</span>
<span class="line" id="L141"> };</span>
<span class="line" id="L142"> }</span>
<span class="line" id="L143"></span>
<span class="line" id="L144"> <span class="tok-kw">const</span> tuple_type_matches = <span class="tok-kw">if</span> (maybe_depth) |depth| <span class="tok-kw">if</span> (maybe_maxval) |maxval| <span class="tok-kw">switch</span> (maybe_tuple_type.?) {</span>
<span class="line" id="L145"> .mono =&gt; depth == <span class="tok-number">1</span> <span class="tok-kw">and</span> maxval == <span class="tok-number">1</span>,</span>
<span class="line" id="L146"> .mono_a =&gt; depth == <span class="tok-number">2</span> <span class="tok-kw">and</span> maxval == <span class="tok-number">1</span>,</span>
<span class="line" id="L147"> .gray =&gt; depth == <span class="tok-number">1</span>,</span>
<span class="line" id="L148"> .gray_a =&gt; depth == <span class="tok-number">2</span>,</span>
<span class="line" id="L149"> .rgb =&gt; depth == <span class="tok-number">3</span>,</span>
<span class="line" id="L150"> .rgb_a =&gt; depth == <span class="tok-number">4</span>,</span>
<span class="line" id="L151"> } <span class="tok-kw">else</span> <span class="tok-kw">unreachable</span> <span class="tok-kw">else</span> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L152"></span>
<span class="line" id="L153"> <span class="tok-kw">if</span> (!tuple_type_matches) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// tuple type does not match</span>
</span>
<span class="line" id="L154"></span>
<span class="line" id="L155"> <span class="tok-kw">return</span> Header{</span>
<span class="line" id="L156"> .width = maybe_width.?,</span>
<span class="line" id="L157"> .height = maybe_height.?,</span>
<span class="line" id="L158"> .maxval = maybe_maxval.?,</span>
<span class="line" id="L159"> .depth = maybe_depth.?,</span>
<span class="line" id="L160"> .tuple_type = maybe_tuple_type.?,</span>
<span class="line" id="L161"> .comments = <span class="tok-kw">try</span> comments.toOwnedSlice(allocator),</span>
<span class="line" id="L162"> };</span>
<span class="line" id="L163"> }</span>
<span class="line" id="L164"></span>
<span class="line" id="L165"> <span class="tok-comment">/// Writes the PAM representation of `header` to `writer`. If</span></span>
<span class="line" id="L166"> <span class="tok-comment">/// writing fails, returns an error specific to `writer`.</span></span>
<span class="line" id="L167"> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(header: Header, writer: <span class="tok-kw">anytype</span>) <span class="tok-builtin">@TypeOf</span>(writer).Error!<span class="tok-type">void</span> {</span>
<span class="line" id="L168"> <span class="tok-kw">try</span> writer.writeAll(<span class="tok-str">&quot;P7\n&quot;</span>);</span>
<span class="line" id="L169"></span>
<span class="line" id="L170"> <span class="tok-kw">for</span> (header.comments) |comment|</span>
<span class="line" id="L171"> <span class="tok-kw">try</span> writer.print(<span class="tok-str">&quot;#{s}\n&quot;</span>, .{comment});</span>
<span class="line" id="L172"></span>
<span class="line" id="L173"> <span class="tok-kw">const</span> fmtstr =</span>
<span class="line" id="L174"> <span class="tok-str">\\WIDTH {d}</span></span>
<span class="line" id="L175"> <span class="tok-str">\\HEIGHT {d}</span></span>
<span class="line" id="L176"> <span class="tok-str">\\DEPTH {d}</span></span>
<span class="line" id="L177"> <span class="tok-str">\\MAXVAL {d}</span></span>
<span class="line" id="L178"> <span class="tok-str">\\TUPLTYPE {s}</span></span>
<span class="line" id="L179"> <span class="tok-str">\\ENDHDR</span></span>
<span class="line" id="L180"> <span class="tok-str">\\</span></span>
<span class="line" id="L181"> ;</span>
<span class="line" id="L182"> <span class="tok-kw">try</span> writer.print(fmtstr, .{ header.width, header.height, header.depth, header.maxval, header.tuple_type.toString() });</span>
<span class="line" id="L183"> }</span>
<span class="line" id="L184"></span>
<span class="line" id="L185"> <span class="tok-comment">/// Invalidates `header` and frees all comments with `allocator`.</span></span>
<span class="line" id="L186"> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(header: *Header, allocator: Allocator) <span class="tok-type">void</span> {</span>
<span class="line" id="L187"> <span class="tok-kw">for</span> (header.comments) |comment| {</span>
<span class="line" id="L188"> allocator.free(comment);</span>
<span class="line" id="L189"> }</span>
<span class="line" id="L190"> allocator.free(header.comments);</span>
<span class="line" id="L191"> header.* = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L192"> }</span>
<span class="line" id="L193"></span>
<span class="line" id="L194"> <span class="tok-kw">fn</span> <span class="tok-fn">hasTwoBytesPerComponent</span>(header: Header) <span class="tok-type">bool</span> {</span>
<span class="line" id="L195"> <span class="tok-kw">return</span> header.maxval &gt; math.maxInt(<span class="tok-type">u8</span>);</span>
<span class="line" id="L196"> }</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">fn</span> <span class="tok-fn">getPixelFormat</span>(header: Header) PixelFormat {</span>
<span class="line" id="L199"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (header.tuple_type) {</span>
<span class="line" id="L200"> .mono =&gt; .grayscale1,</span>
<span class="line" id="L201"> <span class="tok-comment">// TODO: is this conversion acceptable?</span>
</span>
<span class="line" id="L202"> .mono_a =&gt; .grayscale1,</span>
<span class="line" id="L203"> .gray =&gt; <span class="tok-kw">if</span> (header.hasTwoBytesPerComponent()) .grayscale16 <span class="tok-kw">else</span> .grayscale8,</span>
<span class="line" id="L204"> .gray_a =&gt; <span class="tok-kw">if</span> (header.hasTwoBytesPerComponent()) .grayscale16Alpha <span class="tok-kw">else</span> .grayscale8Alpha,</span>
<span class="line" id="L205"> .rgb =&gt; <span class="tok-kw">if</span> (header.hasTwoBytesPerComponent()) .rgb48 <span class="tok-kw">else</span> .rgb24,</span>
<span class="line" id="L206"> .rgb_a =&gt; <span class="tok-kw">if</span> (header.hasTwoBytesPerComponent()) .rgba64 <span class="tok-kw">else</span> .rgba32,</span>
<span class="line" id="L207"> };</span>
<span class="line" id="L208"> }</span>
<span class="line" id="L209"></span>
<span class="line" id="L210"> <span class="tok-comment">/// Initializes an `Image` with the values that `header`</span></span>
<span class="line" id="L211"> <span class="tok-comment">/// contains. Returns `error.OutOfMemory` if allocation fails.</span></span>
<span class="line" id="L212"> <span class="tok-kw">fn</span> <span class="tok-fn">initImage</span>(header: Header, allocator: Allocator) <span class="tok-kw">error</span>{OutOfMemory}!Image {</span>
<span class="line" id="L213"> <span class="tok-kw">var</span> image = Image.init(allocator);</span>
<span class="line" id="L214"> image.width = header.width;</span>
<span class="line" id="L215"> image.height = header.height;</span>
<span class="line" id="L216"> image.pixels = <span class="tok-kw">try</span> PixelStorage.init(allocator, header.getPixelFormat(), header.width * header.height);</span>
<span class="line" id="L217"> <span class="tok-kw">return</span> image;</span>
<span class="line" id="L218"> }</span>
<span class="line" id="L219"></span>
<span class="line" id="L220"> <span class="tok-comment">/// Initializes a `Header` from `image`. Returns</span></span>
<span class="line" id="L221"> <span class="tok-comment">/// `error.Unsupported` if the pixel format of `image` cannot be</span></span>
<span class="line" id="L222"> <span class="tok-comment">/// easily represented in PAM.</span></span>
<span class="line" id="L223"> <span class="tok-kw">fn</span> <span class="tok-fn">fromImage</span>(image: Image) <span class="tok-kw">error</span>{Unsupported}!Header {</span>
<span class="line" id="L224"> <span class="tok-kw">var</span> header: Header = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L225"> <span class="tok-kw">switch</span> (image.pixelFormat()) {</span>
<span class="line" id="L226"> .invalid,</span>
<span class="line" id="L227"> .indexed1,</span>
<span class="line" id="L228"> .indexed2,</span>
<span class="line" id="L229"> .indexed4,</span>
<span class="line" id="L230"> .indexed8,</span>
<span class="line" id="L231"> .indexed16,</span>
<span class="line" id="L232"> .float32,</span>
<span class="line" id="L233"> .rgb565,</span>
<span class="line" id="L234"> =&gt; <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported, <span class="tok-comment">// unsupported pixel format</span>
</span>
<span class="line" id="L235"></span>
<span class="line" id="L236"> .grayscale1 =&gt; {</span>
<span class="line" id="L237"> header.depth = <span class="tok-number">1</span>;</span>
<span class="line" id="L238"> header.maxval = <span class="tok-number">1</span>;</span>
<span class="line" id="L239"> header.tuple_type = .mono;</span>
<span class="line" id="L240"> },</span>
<span class="line" id="L241"> .grayscale2 =&gt; {</span>
<span class="line" id="L242"> header.depth = <span class="tok-number">1</span>;</span>
<span class="line" id="L243"> header.maxval = math.maxInt(<span class="tok-type">u2</span>);</span>
<span class="line" id="L244"> header.tuple_type = .gray;</span>
<span class="line" id="L245"> },</span>
<span class="line" id="L246"> .grayscale4 =&gt; {</span>
<span class="line" id="L247"> header.depth = <span class="tok-number">1</span>;</span>
<span class="line" id="L248"> header.maxval = math.maxInt(<span class="tok-type">u4</span>);</span>
<span class="line" id="L249"> header.tuple_type = .gray;</span>
<span class="line" id="L250"> },</span>
<span class="line" id="L251"> .grayscale8 =&gt; {</span>
<span class="line" id="L252"> header.depth = <span class="tok-number">1</span>;</span>
<span class="line" id="L253"> header.maxval = math.maxInt(<span class="tok-type">u8</span>);</span>
<span class="line" id="L254"> header.tuple_type = .gray;</span>
<span class="line" id="L255"> },</span>
<span class="line" id="L256"> .grayscale8Alpha =&gt; {</span>
<span class="line" id="L257"> header.depth = <span class="tok-number">2</span>;</span>
<span class="line" id="L258"> header.maxval = math.maxInt(<span class="tok-type">u8</span>);</span>
<span class="line" id="L259"> header.tuple_type = .gray_a;</span>
<span class="line" id="L260"> },</span>
<span class="line" id="L261"> .grayscale16 =&gt; {</span>
<span class="line" id="L262"> header.depth = <span class="tok-number">1</span>;</span>
<span class="line" id="L263"> header.maxval = math.maxInt(<span class="tok-type">u16</span>);</span>
<span class="line" id="L264"> header.tuple_type = .gray;</span>
<span class="line" id="L265"> },</span>
<span class="line" id="L266"> .grayscale16Alpha =&gt; {</span>
<span class="line" id="L267"> header.depth = <span class="tok-number">2</span>;</span>
<span class="line" id="L268"> header.maxval = math.maxInt(<span class="tok-type">u16</span>);</span>
<span class="line" id="L269"> header.tuple_type = .gray_a;</span>
<span class="line" id="L270"> },</span>
<span class="line" id="L271"> .rgb555, .bgr555 =&gt; {</span>
<span class="line" id="L272"> header.depth = <span class="tok-number">3</span>;</span>
<span class="line" id="L273"> header.maxval = math.maxInt(<span class="tok-type">u5</span>);</span>
<span class="line" id="L274"> header.tuple_type = .rgb;</span>
<span class="line" id="L275"> },</span>
<span class="line" id="L276"> .rgb24, .bgr24 =&gt; {</span>
<span class="line" id="L277"> header.depth = <span class="tok-number">3</span>;</span>
<span class="line" id="L278"> header.maxval = math.maxInt(<span class="tok-type">u8</span>);</span>
<span class="line" id="L279"> header.tuple_type = .rgb;</span>
<span class="line" id="L280"> },</span>
<span class="line" id="L281"> .rgba32, .bgra32 =&gt; {</span>
<span class="line" id="L282"> header.depth = <span class="tok-number">4</span>;</span>
<span class="line" id="L283"> header.maxval = math.maxInt(<span class="tok-type">u8</span>);</span>
<span class="line" id="L284"> header.tuple_type = .rgb_a;</span>
<span class="line" id="L285"> },</span>
<span class="line" id="L286"> .rgb48 =&gt; {</span>
<span class="line" id="L287"> header.depth = <span class="tok-number">3</span>;</span>
<span class="line" id="L288"> header.maxval = math.maxInt(<span class="tok-type">u16</span>);</span>
<span class="line" id="L289"> header.tuple_type = .rgb;</span>
<span class="line" id="L290"> },</span>
<span class="line" id="L291"> .rgba64 =&gt; {</span>
<span class="line" id="L292"> header.depth = <span class="tok-number">4</span>;</span>
<span class="line" id="L293"> header.maxval = math.maxInt(<span class="tok-type">u16</span>);</span>
<span class="line" id="L294"> header.tuple_type = .rgb_a;</span>
<span class="line" id="L295"> },</span>
<span class="line" id="L296"> }</span>
<span class="line" id="L297"> header.comments = &amp;.{};</span>
<span class="line" id="L298"> header.width = image.width;</span>
<span class="line" id="L299"> header.height = image.height;</span>
<span class="line" id="L300"> <span class="tok-kw">return</span> header;</span>
<span class="line" id="L301"> }</span>
<span class="line" id="L302">};</span>
<span class="line" id="L303"></span>
<span class="line" id="L304"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PAM = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L305"> <span class="tok-comment">//! Portable AnyMap</span></span>
<span class="line" id="L306"> <span class="tok-comment">//! currently, this only supports a subset of PAMs where:</span></span>
<span class="line" id="L307"> <span class="tok-comment">//! - the tuple type is official (see `man 5 pam`) or easily inferred (and</span></span>
<span class="line" id="L308"> <span class="tok-comment">//! by extension, depth is 4 or less)</span></span>
<span class="line" id="L309"> <span class="tok-comment">//! - all images in a sequence have the same dimensions and maxval (it is</span></span>
<span class="line" id="L310"> <span class="tok-comment">//! technically possible to support animations with different maxvals and</span></span>
<span class="line" id="L311"> <span class="tok-comment">//! tuple types as each `AnimationFrame` has its own `PixelStorage`, however,</span></span>
<span class="line" id="L312"> <span class="tok-comment">//! this is likely not expected by users of the library.</span></span>
<span class="line" id="L313"> <span class="tok-comment">//! supported input pixel formats: `grayscale{1, 8, 16}, `grayscale{1, 8, 16}Alpha`, `rgb555`, `{rgb, bgr}{24, 48}`, `{bgr, rgb}a{32, 64}`</span></span>
<span class="line" id="L314"></span>
<span class="line" id="L315"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L316"> <span class="tok-comment">/// Free-form comments to be added to the header.</span></span>
<span class="line" id="L317"> comments: []<span class="tok-kw">const</span> []<span class="tok-kw">const</span> <span class="tok-type">u8</span> = &amp;.{},</span>
<span class="line" id="L318"> <span class="tok-comment">/// Whether to add the duration of each `Image.AnimationFrame`</span></span>
<span class="line" id="L319"> <span class="tok-comment">/// and the `loop_count` of `Image.Animation` to the written file as a comment.</span></span>
<span class="line" id="L320"> add_duration_as_comment: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L321"> };</span>
<span class="line" id="L322"></span>
<span class="line" id="L323"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L324"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L325"> .format = format,</span>
<span class="line" id="L326"> .formatDetect = formatDetect,</span>
<span class="line" id="L327"> .readImage = readImage,</span>
<span class="line" id="L328"> .writeImage = writeImage,</span>
<span class="line" id="L329"> };</span>
<span class="line" id="L330"> }</span>
<span class="line" id="L331"></span>
<span class="line" id="L332"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L333"> <span class="tok-kw">return</span> Image.Format.pam;</span>
<span class="line" id="L334"> }</span>
<span class="line" id="L335"></span>
<span class="line" id="L336"> <span class="tok-comment">/// Returns `true` if the image will be able to be decoded, or a</span></span>
<span class="line" id="L337"> <span class="tok-comment">/// `stream`-specific error if reading fails.</span></span>
<span class="line" id="L338"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L339"> <span class="tok-kw">const</span> magic = <span class="tok-kw">try</span> stream.reader().readBytesNoEof(<span class="tok-number">3</span>);</span>
<span class="line" id="L340"> <span class="tok-kw">return</span> mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P7\n&quot;</span>); <span class="tok-comment">// no possibility of misdetecting xv thumbnails (magic &quot;P7 332&quot;)</span>
</span>
<span class="line" id="L341"> }</span>
<span class="line" id="L342"></span>
<span class="line" id="L343"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L344"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L345"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L346"> <span class="tok-kw">var</span> image: Image = <span class="tok-kw">try</span> readFrame(allocator, reader) <span class="tok-kw">orelse</span> <span class="tok-kw">return</span> ImageReadError.InvalidData; <span class="tok-comment">// empty stream</span>
</span>
<span class="line" id="L347"> <span class="tok-kw">errdefer</span> image.deinit();</span>
<span class="line" id="L348"></span>
<span class="line" id="L349"> <span class="tok-kw">while</span> (<span class="tok-kw">try</span> readFrame(allocator, reader)) |frame| {</span>
<span class="line" id="L350"> <span class="tok-kw">if</span> (frame.width != image.width <span class="tok-kw">or</span> frame.height != image.height <span class="tok-kw">or</span> meta.activeTag(frame.pixels) != meta.activeTag(image.pixels)) {</span>
<span class="line" id="L351"> <span class="tok-kw">return</span> ImageReadError.Unsupported; <span class="tok-comment">// no obvious way to have multiple frames with different dimensions</span>
</span>
<span class="line" id="L352"> }</span>
<span class="line" id="L353"> <span class="tok-kw">try</span> image.animation.frames.append(allocator, Image.AnimationFrame{ .pixels = frame.pixels, .duration = <span class="tok-number">0</span> });</span>
<span class="line" id="L354"> }</span>
<span class="line" id="L355"> <span class="tok-kw">return</span> image;</span>
<span class="line" id="L356"> }</span>
<span class="line" id="L357"></span>
<span class="line" id="L358"> <span class="tok-comment">/// Linearly maps `val` from [0..`src_maxval`] to</span></span>
<span class="line" id="L359"> <span class="tok-comment">/// [0..`dst_maxval`]. If `val` is greater than `src_maxval`,</span></span>
<span class="line" id="L360"> <span class="tok-comment">/// `error.OutOfBounds` is returned. If `val == src_maxval`,</span></span>
<span class="line" id="L361"> <span class="tok-comment">/// `dst_maxval` is returned.</span></span>
<span class="line" id="L362"> <span class="tok-kw">fn</span> <span class="tok-fn">mapValue</span>(<span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, val: T, src_maxval: T, dst_maxval: T) <span class="tok-kw">error</span>{InvalidData}!T {</span>
<span class="line" id="L363"> <span class="tok-kw">if</span> (val &gt; src_maxval) <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidData; <span class="tok-comment">// component value exceeded maxval</span>
</span>
<span class="line" id="L364"></span>
<span class="line" id="L365"> <span class="tok-kw">if</span> (src_maxval == dst_maxval) <span class="tok-kw">return</span> val;</span>
<span class="line" id="L366"></span>
<span class="line" id="L367"> <span class="tok-kw">const</span> W = meta.Int(.unsigned, <span class="tok-builtin">@bitSizeOf</span>(T) * <span class="tok-number">2</span>);</span>
<span class="line" id="L368"> <span class="tok-kw">return</span> <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@min</span>(math.maxInt(T), <span class="tok-builtin">@as</span>(W, dst_maxval) * <span class="tok-builtin">@as</span>(W, val) / <span class="tok-builtin">@as</span>(W, src_maxval)));</span>
<span class="line" id="L369"> }</span>
<span class="line" id="L370"></span>
<span class="line" id="L371"> <span class="tok-kw">fn</span> <span class="tok-fn">readFrame</span>(allocator: Allocator, reader: <span class="tok-kw">anytype</span>) ImageReadError!?Image {</span>
<span class="line" id="L372"> <span class="tok-comment">// we don't use catch switch here because error.EndOfStream</span>
</span>
<span class="line" id="L373"> <span class="tok-comment">// might be the only possible error (and would thus trigger a</span>
</span>
<span class="line" id="L374"> <span class="tok-comment">// compile error because of an unreachable else prong)</span>
</span>
<span class="line" id="L375"> <span class="tok-kw">const</span> magic = reader.readBytesNoEof(<span class="tok-number">3</span>) <span class="tok-kw">catch</span> |e| <span class="tok-kw">return</span> <span class="tok-kw">if</span> (e == <span class="tok-kw">error</span>.EndOfStream) <span class="tok-null">null</span> <span class="tok-kw">else</span> e;</span>
<span class="line" id="L376"> <span class="tok-kw">const</span> is_pam = mem.eql(<span class="tok-type">u8</span>, &amp;magic, <span class="tok-str">&quot;P7\n&quot;</span>);</span>
<span class="line" id="L377"> <span class="tok-kw">if</span> (!is_pam) <span class="tok-kw">return</span> ImageReadError.InvalidData; <span class="tok-comment">// invalid magic number or extraneous data at eof</span>
</span>
<span class="line" id="L378"></span>
<span class="line" id="L379"> <span class="tok-kw">var</span> header = <span class="tok-kw">try</span> Header.read(allocator, reader);</span>
<span class="line" id="L380"> <span class="tok-kw">defer</span> header.deinit(allocator);</span>
<span class="line" id="L381"></span>
<span class="line" id="L382"> <span class="tok-kw">var</span> image: Image = <span class="tok-kw">try</span> header.initImage(allocator);</span>
<span class="line" id="L383"> <span class="tok-kw">errdefer</span> image.deinit();</span>
<span class="line" id="L384"></span>
<span class="line" id="L385"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image.height) |row| {</span>
<span class="line" id="L386"> <span class="tok-kw">const</span> offset = row * image.width;</span>
<span class="line" id="L387"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image.width) |column| {</span>
<span class="line" id="L388"> <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L389"> .grayscale1 =&gt; |g| g[offset + column].value = <span class="tok-builtin">@intCast</span>(<span class="tok-kw">if</span> (header.tuple_type == .mono) <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-number">1</span>, <span class="tok-number">1</span>) <span class="tok-kw">else</span> <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-number">1</span>, <span class="tok-number">1</span>) &amp; <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-number">1</span>, <span class="tok-number">1</span>)),</span>
<span class="line" id="L390"> .grayscale8 =&gt; |g| g[offset + column].value = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L391"> .grayscale8Alpha =&gt; |g| g[offset + column] = .{</span>
<span class="line" id="L392"> .value = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L393"> .alpha = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L394"> },</span>
<span class="line" id="L395"> .grayscale16 =&gt; |g| g[offset + column].value = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L396"> .grayscale16Alpha =&gt; |g| g[offset + column] = .{</span>
<span class="line" id="L397"> .value = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L398"> .alpha = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L399"> },</span>
<span class="line" id="L400"> .rgb24 =&gt; |x| x[offset + column] = .{</span>
<span class="line" id="L401"> .r = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L402"> .g = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L403"> .b = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L404"> },</span>
<span class="line" id="L405"> .rgba32 =&gt; |x| x[offset + column] = .{</span>
<span class="line" id="L406"> .r = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L407"> .g = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L408"> .b = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L409"> .a = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u8</span>, <span class="tok-kw">try</span> reader.readByte(), <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@intCast</span>(header.maxval)), math.maxInt(<span class="tok-type">u8</span>)),</span>
<span class="line" id="L410"> },</span>
<span class="line" id="L411"> .rgb48 =&gt; |x| x[offset + column] = .{</span>
<span class="line" id="L412"> .r = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L413"> .g = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L414"> .b = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L415"> },</span>
<span class="line" id="L416"> .rgba64 =&gt; |x| x[offset + column] = .{</span>
<span class="line" id="L417"> .r = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L418"> .g = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L419"> .b = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L420"> .a = <span class="tok-kw">try</span> mapValue(<span class="tok-type">u16</span>, <span class="tok-kw">try</span> reader.readInt(<span class="tok-type">u16</span>, .little), header.maxval, math.maxInt(<span class="tok-type">u16</span>)),</span>
<span class="line" id="L421"> },</span>
<span class="line" id="L422"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L423"> }</span>
<span class="line" id="L424"> }</span>
<span class="line" id="L425"> }</span>
<span class="line" id="L426"> <span class="tok-kw">return</span> image;</span>
<span class="line" id="L427"> }</span>
<span class="line" id="L428"></span>
<span class="line" id="L429"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L430"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);</span>
<span class="line" id="L431"> <span class="tok-kw">const</span> writer = buffered_stream.writer();</span>
<span class="line" id="L432"></span>
<span class="line" id="L433"> <span class="tok-kw">var</span> comments = std.ArrayList([]<span class="tok-kw">const</span> <span class="tok-type">u8</span>).init(allocator);</span>
<span class="line" id="L434"> <span class="tok-kw">defer</span> comments.deinit();</span>
<span class="line" id="L435"> <span class="tok-kw">try</span> comments.appendSlice(<span class="tok-kw">switch</span> (encoder_options) {</span>
<span class="line" id="L436"> .pam =&gt; |p| p.comments,</span>
<span class="line" id="L437"> <span class="tok-kw">else</span> =&gt; &amp;.{},</span>
<span class="line" id="L438"> });</span>
<span class="line" id="L439"></span>
<span class="line" id="L440"> <span class="tok-kw">var</span> duration_buffer: [<span class="tok-number">128</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L441"> <span class="tok-kw">const</span> add_duration_as_comment = <span class="tok-kw">switch</span> (encoder_options) {</span>
<span class="line" id="L442"> .pam =&gt; |p| p.add_duration_as_comment,</span>
<span class="line" id="L443"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L444"> };</span>
<span class="line" id="L445"></span>
<span class="line" id="L446"> {</span>
<span class="line" id="L447"> <span class="tok-kw">if</span> (add_duration_as_comment <span class="tok-kw">and</span> image.isAnimation()) {</span>
<span class="line" id="L448"> <span class="tok-kw">try</span> comments.append(<span class="tok-kw">try</span> fmt.bufPrint(&amp;duration_buffer, <span class="tok-str">&quot;loop count: {d}&quot;</span>, .{image.animation.loop_count}));</span>
<span class="line" id="L449"> }</span>
<span class="line" id="L450"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L451"> <span class="tok-kw">if</span> (add_duration_as_comment <span class="tok-kw">and</span> image.isAnimation()) _ = comments.pop();</span>
<span class="line" id="L452"> }</span>
<span class="line" id="L453"></span>
<span class="line" id="L454"> <span class="tok-kw">try</span> writeFrame(writer, image, .{ .pam = .{ .comments = comments.items } });</span>
<span class="line" id="L455"> }</span>
<span class="line" id="L456"></span>
<span class="line" id="L457"> <span class="tok-kw">for</span> (image.animation.frames.items) |frame| {</span>
<span class="line" id="L458"> <span class="tok-kw">if</span> (add_duration_as_comment)</span>
<span class="line" id="L459"> <span class="tok-kw">try</span> comments.append(<span class="tok-kw">try</span> fmt.bufPrint(&amp;duration_buffer, <span class="tok-str">&quot;duration: {d}&quot;</span>, .{frame.duration}));</span>
<span class="line" id="L460"> <span class="tok-kw">defer</span> {</span>
<span class="line" id="L461"> <span class="tok-kw">if</span> (add_duration_as_comment) _ = comments.pop();</span>
<span class="line" id="L462"> }</span>
<span class="line" id="L463"></span>
<span class="line" id="L464"> <span class="tok-kw">const</span> frame_img = Image{ .pixels = frame.pixels, .width = image.width, .height = image.height, .allocator = image.allocator };</span>
<span class="line" id="L465"></span>
<span class="line" id="L466"> <span class="tok-kw">try</span> writeFrame(writer, frame_img, .{ .pam = .{ .comments = comments.items } });</span>
<span class="line" id="L467"> }</span>
<span class="line" id="L468"></span>
<span class="line" id="L469"> <span class="tok-kw">try</span> buffered_stream.flush();</span>
<span class="line" id="L470"> }</span>
<span class="line" id="L471"></span>
<span class="line" id="L472"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeFrame</span>(writer: <span class="tok-kw">anytype</span>, frame: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L473"> <span class="tok-kw">var</span> header = <span class="tok-kw">try</span> Header.fromImage(frame);</span>
<span class="line" id="L474"> header.comments = encoder_options.pam.comments;</span>
<span class="line" id="L475"> <span class="tok-kw">try</span> header.write(writer);</span>
<span class="line" id="L476"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..frame.height) |row| {</span>
<span class="line" id="L477"> <span class="tok-kw">const</span> offset = row * frame.width;</span>
<span class="line" id="L478"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..frame.width) |column| {</span>
<span class="line" id="L479"> <span class="tok-kw">switch</span> (frame.pixels) {</span>
<span class="line" id="L480"> .grayscale1 =&gt; |x| <span class="tok-kw">try</span> writer.writeByte(x[offset + column].value),</span>
<span class="line" id="L481"> .grayscale4 =&gt; |x| <span class="tok-kw">try</span> writer.writeByte(x[offset + column].value),</span>
<span class="line" id="L482"> .grayscale8 =&gt; |x| <span class="tok-kw">try</span> writer.writeByte(x[offset + column].value),</span>
<span class="line" id="L483"> .grayscale16 =&gt; |x| <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].value, .little),</span>
<span class="line" id="L484"> .grayscale8Alpha =&gt; |x| {</span>
<span class="line" id="L485"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].value);</span>
<span class="line" id="L486"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].alpha);</span>
<span class="line" id="L487"> },</span>
<span class="line" id="L488"> .grayscale16Alpha =&gt; |x| {</span>
<span class="line" id="L489"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].value, .little);</span>
<span class="line" id="L490"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].alpha, .little);</span>
<span class="line" id="L491"> },</span>
<span class="line" id="L492"> .bgr555 =&gt; |x| {</span>
<span class="line" id="L493"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L494"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L495"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L496"> },</span>
<span class="line" id="L497"> .rgb555 =&gt; |x| {</span>
<span class="line" id="L498"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L499"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L500"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L501"> },</span>
<span class="line" id="L502"> .rgb24 =&gt; |x| {</span>
<span class="line" id="L503"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L504"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L505"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L506"> },</span>
<span class="line" id="L507"> .rgba32 =&gt; |x| {</span>
<span class="line" id="L508"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L509"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L510"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L511"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].a);</span>
<span class="line" id="L512"> },</span>
<span class="line" id="L513"> .bgr24 =&gt; |x| {</span>
<span class="line" id="L514"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L515"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L516"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L517"> },</span>
<span class="line" id="L518"> .bgra32 =&gt; |x| {</span>
<span class="line" id="L519"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].r);</span>
<span class="line" id="L520"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].g);</span>
<span class="line" id="L521"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].b);</span>
<span class="line" id="L522"> <span class="tok-kw">try</span> writer.writeByte(x[offset + column].a);</span>
<span class="line" id="L523"> },</span>
<span class="line" id="L524"> .rgb48 =&gt; |x| {</span>
<span class="line" id="L525"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].r, .little);</span>
<span class="line" id="L526"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].g, .little);</span>
<span class="line" id="L527"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].b, .little);</span>
<span class="line" id="L528"> },</span>
<span class="line" id="L529"> .rgba64 =&gt; |x| {</span>
<span class="line" id="L530"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].r, .little);</span>
<span class="line" id="L531"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].g, .little);</span>
<span class="line" id="L532"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].b, .little);</span>
<span class="line" id="L533"> <span class="tok-kw">try</span> writer.writeInt(<span class="tok-type">u16</span>, x[offset + column].a, .little);</span>
<span class="line" id="L534"> },</span>
<span class="line" id="L535"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>, <span class="tok-comment">// can't happen, already handled in fromImage</span>
</span>
<span class="line" id="L536"> }</span>
<span class="line" id="L537"> }</span>
<span class="line" id="L538"> }</span>
<span class="line" id="L539"> }</span>
<span class="line" id="L540">};</span>
<span class="line" id="L541"></span>
</code></pre></body>
</html>

View file

@ -1,862 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/pcx.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Adapted from https://github.com/MasterQ32/zig-gamedev-lib/blob/master/src/pcx.zig</span>
</span>
<span class="line" id="L2"><span class="tok-comment">// with permission from Felix Queißner</span>
</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> ImageError = Image.Error;</span>
<span class="line" id="L9"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L10"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L11"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L12"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L13"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../utils.zig&quot;</span>);</span>
<span class="line" id="L14"><span class="tok-kw">const</span> simd = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../simd.zig&quot;</span>);</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">const</span> MagicHeader: <span class="tok-type">u8</span> = <span class="tok-number">0x0A</span>;</span>
<span class="line" id="L17"><span class="tok-kw">const</span> Version: <span class="tok-type">u8</span> = <span class="tok-number">5</span>;</span>
<span class="line" id="L18"><span class="tok-kw">const</span> VGAPaletteIdentifier: <span class="tok-type">u8</span> = <span class="tok-number">0x0C</span>;</span>
<span class="line" id="L19"></span>
<span class="line" id="L20"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Compression = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L21"> none,</span>
<span class="line" id="L22"> rle,</span>
<span class="line" id="L23">};</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PaletteInfo = <span class="tok-kw">enum</span>(<span class="tok-type">u16</span>) {</span>
<span class="line" id="L26"> color = <span class="tok-number">1</span>,</span>
<span class="line" id="L27"> grayscale = <span class="tok-number">2</span>,</span>
<span class="line" id="L28"> _,</span>
<span class="line" id="L29">};</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PCXHeader = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L32"> id: <span class="tok-type">u8</span> = MagicHeader,</span>
<span class="line" id="L33"> version: <span class="tok-type">u8</span> = Version,</span>
<span class="line" id="L34"> compression: Compression = .rle,</span>
<span class="line" id="L35"> bpp: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L36"> xmin: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L37"> ymin: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L38"> xmax: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L39"> ymax: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L40"> horizontal_dpi: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">320</span>, <span class="tok-comment">// Default values found in the PCX image in the test suite</span>
</span>
<span class="line" id="L41"> vertical_dpi: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">200</span>, <span class="tok-comment">// Default values found in the PCX image in the test suite</span>
</span>
<span class="line" id="L42"> builtin_palette: [<span class="tok-number">16</span>]color.Rgb24 = [_]color.Rgb24{.{ .r = <span class="tok-number">0</span>, .g = <span class="tok-number">0</span>, .b = <span class="tok-number">0</span> }} ** <span class="tok-number">16</span>,</span>
<span class="line" id="L43"> _reserved0: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L44"> planes: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L45"> stride: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L46"> palette_information: PaletteInfo <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = .color,</span>
<span class="line" id="L47"> screen_width: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L48"> screen_height: <span class="tok-type">u16</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0</span>,</span>
<span class="line" id="L49"> padding: [<span class="tok-number">54</span>]<span class="tok-type">u8</span> = [_]<span class="tok-type">u8</span>{<span class="tok-number">0</span>} ** <span class="tok-number">54</span>,</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"> <span class="tok-kw">comptime</span> {</span>
<span class="line" id="L52"> std.debug.assert(<span class="tok-builtin">@sizeOf</span>(PCXHeader) == <span class="tok-number">128</span>);</span>
<span class="line" id="L53"> }</span>
<span class="line" id="L54">};</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"><span class="tok-kw">const</span> RLEPairMask = <span class="tok-number">0xC0</span>;</span>
<span class="line" id="L57"><span class="tok-kw">const</span> RLELengthMask = <span class="tok-number">0xFF</span> - RLEPairMask;</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"><span class="tok-kw">const</span> RLEDecoder = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> Run = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L61"> value: <span class="tok-type">u8</span>,</span>
<span class="line" id="L62"> remaining: <span class="tok-type">usize</span>,</span>
<span class="line" id="L63"> };</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader,</span>
<span class="line" id="L66"> current_run: ?Run,</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(reader: buffered_stream_source.DefaultBufferedStreamSourceReader.Reader) RLEDecoder {</span>
<span class="line" id="L69"> <span class="tok-kw">return</span> RLEDecoder{</span>
<span class="line" id="L70"> .reader = reader,</span>
<span class="line" id="L71"> .current_run = <span class="tok-null">null</span>,</span>
<span class="line" id="L72"> };</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">fn</span> <span class="tok-fn">readByte</span>(self: *RLEDecoder) ImageReadError!<span class="tok-type">u8</span> {</span>
<span class="line" id="L76"> <span class="tok-kw">if</span> (self.current_run) |*run| {</span>
<span class="line" id="L77"> <span class="tok-kw">const</span> result = run.value;</span>
<span class="line" id="L78"> run.remaining -= <span class="tok-number">1</span>;</span>
<span class="line" id="L79"> <span class="tok-kw">if</span> (run.remaining == <span class="tok-number">0</span>) {</span>
<span class="line" id="L80"> self.current_run = <span class="tok-null">null</span>;</span>
<span class="line" id="L81"> }</span>
<span class="line" id="L82"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L83"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L84"> <span class="tok-kw">while</span> (<span class="tok-null">true</span>) {</span>
<span class="line" id="L85"> <span class="tok-kw">const</span> byte = <span class="tok-kw">try</span> self.reader.readByte();</span>
<span class="line" id="L86"> <span class="tok-kw">if</span> (byte == RLEPairMask) <span class="tok-comment">// skip over &quot;zero length runs&quot;</span>
</span>
<span class="line" id="L87"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L88"> <span class="tok-kw">if</span> ((byte &amp; RLEPairMask) == RLEPairMask) {</span>
<span class="line" id="L89"> <span class="tok-kw">const</span> len = byte &amp; RLELengthMask;</span>
<span class="line" id="L90"> std.debug.assert(len &gt; <span class="tok-number">0</span>);</span>
<span class="line" id="L91"> <span class="tok-kw">const</span> result = <span class="tok-kw">try</span> self.reader.readByte();</span>
<span class="line" id="L92"> <span class="tok-kw">if</span> (len &gt; <span class="tok-number">1</span>) {</span>
<span class="line" id="L93"> <span class="tok-comment">// we only need to store a run in the decoder if it is longer than 1</span>
</span>
<span class="line" id="L94"> self.current_run = .{</span>
<span class="line" id="L95"> .value = result,</span>
<span class="line" id="L96"> .remaining = len - <span class="tok-number">1</span>,</span>
<span class="line" id="L97"> };</span>
<span class="line" id="L98"> }</span>
<span class="line" id="L99"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L100"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L101"> <span class="tok-kw">return</span> byte;</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103"> }</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105"> }</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"> <span class="tok-kw">fn</span> <span class="tok-fn">finish</span>(decoder: RLEDecoder) ImageReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L108"> <span class="tok-kw">if</span> (decoder.current_run != <span class="tok-null">null</span>) {</span>
<span class="line" id="L109"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L110"> }</span>
<span class="line" id="L111"> }</span>
<span class="line" id="L112">};</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"><span class="tok-kw">const</span> RLEPair = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L115"> length: <span class="tok-type">u6</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L116"> identifier: <span class="tok-type">u2</span> = (<span class="tok-number">1</span> &lt;&lt; <span class="tok-number">2</span>) - <span class="tok-number">1</span>,</span>
<span class="line" id="L117">};</span>
<span class="line" id="L118"></span>
<span class="line" id="L119"><span class="tok-kw">const</span> RLEMinLength = <span class="tok-number">2</span>;</span>
<span class="line" id="L120"><span class="tok-kw">const</span> RLEMaxLength = (<span class="tok-number">1</span> &lt;&lt; <span class="tok-number">6</span>) - <span class="tok-number">1</span>;</span>
<span class="line" id="L121"></span>
<span class="line" id="L122"><span class="tok-kw">fn</span> <span class="tok-fn">flushRLE</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-type">u8</span>, count: <span class="tok-type">usize</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L123"> <span class="tok-kw">var</span> current_count = count;</span>
<span class="line" id="L124"> <span class="tok-kw">while</span> (current_count &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L125"> <span class="tok-kw">const</span> length_to_write = <span class="tok-builtin">@min</span>(current_count, RLEMaxLength);</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (length_to_write &gt;= RLEMinLength) {</span>
<span class="line" id="L128"> <span class="tok-kw">try</span> flushRlePair(writer, value, length_to_write);</span>
<span class="line" id="L129"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L130"> <span class="tok-kw">try</span> flushRawBytes(writer, value, length_to_write);</span>
<span class="line" id="L131"> }</span>
<span class="line" id="L132"></span>
<span class="line" id="L133"> current_count -= length_to_write;</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135">}</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"><span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">flushRlePair</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-type">u8</span>, count: <span class="tok-type">usize</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L138"> <span class="tok-kw">const</span> rle_pair = RLEPair{</span>
<span class="line" id="L139"> .length = <span class="tok-builtin">@truncate</span>(count),</span>
<span class="line" id="L140"> };</span>
<span class="line" id="L141"> <span class="tok-kw">try</span> writer.writeByte(<span class="tok-builtin">@bitCast</span>(rle_pair));</span>
<span class="line" id="L142"> <span class="tok-kw">try</span> writer.writeByte(value);</span>
<span class="line" id="L143">}</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"><span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">flushRawBytes</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-type">u8</span>, count: <span class="tok-type">usize</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L146"> <span class="tok-comment">// Must flush byte greater than 192 (0xC0) as a RLE pair</span>
</span>
<span class="line" id="L147"> <span class="tok-kw">if</span> ((value &amp; RLEPairMask) == RLEPairMask) {</span>
<span class="line" id="L148"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..count) |_| {</span>
<span class="line" id="L149"> <span class="tok-kw">try</span> flushRlePair(writer, value, <span class="tok-number">1</span>);</span>
<span class="line" id="L150"> }</span>
<span class="line" id="L151"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L152"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..count) |_| {</span>
<span class="line" id="L153"> <span class="tok-kw">try</span> writer.writeByte(value);</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"> }</span>
<span class="line" id="L156">}</span>
<span class="line" id="L157"></span>
<span class="line" id="L158"><span class="tok-kw">const</span> RLEFastEncoder = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L159"> <span class="tok-kw">const</span> LengthToCheck = <span class="tok-number">16</span>;</span>
<span class="line" id="L160"> <span class="tok-kw">const</span> VectorType = <span class="tok-builtin">@Vector</span>(LengthToCheck, <span class="tok-type">u8</span>);</span>
<span class="line" id="L161"></span>
<span class="line" id="L162"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">encode</span>(source_data: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, writer: <span class="tok-kw">anytype</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L163"> <span class="tok-kw">if</span> (source_data.len == <span class="tok-number">0</span>) {</span>
<span class="line" id="L164"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L165"> }</span>
<span class="line" id="L166"></span>
<span class="line" id="L167"> <span class="tok-kw">var</span> index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L168"></span>
<span class="line" id="L169"> <span class="tok-kw">var</span> total_similar_count: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-kw">var</span> current_byte: <span class="tok-type">u8</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L172"></span>
<span class="line" id="L173"> <span class="tok-kw">while</span> (index &lt; source_data.len <span class="tok-kw">and</span> (index + LengthToCheck) &lt;= source_data.len) {</span>
<span class="line" id="L174"> <span class="tok-comment">// Read current byte</span>
</span>
<span class="line" id="L175"> current_byte = source_data[index];</span>
<span class="line" id="L176"></span>
<span class="line" id="L177"> <span class="tok-kw">const</span> current_byte_splatted: VectorType = <span class="tok-builtin">@splat</span>(current_byte);</span>
<span class="line" id="L178"> <span class="tok-kw">const</span> compare_chunk = simd.load(source_data[index..], VectorType, <span class="tok-number">0</span>);</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-kw">const</span> compare_mask = (current_byte_splatted == compare_chunk);</span>
<span class="line" id="L181"> <span class="tok-kw">const</span> inverted_mask = ~<span class="tok-builtin">@as</span>(<span class="tok-type">u16</span>, <span class="tok-builtin">@bitCast</span>(compare_mask));</span>
<span class="line" id="L182"> <span class="tok-kw">const</span> current_similar_count = <span class="tok-builtin">@ctz</span>(inverted_mask);</span>
<span class="line" id="L183"></span>
<span class="line" id="L184"> <span class="tok-kw">if</span> (current_similar_count == LengthToCheck) {</span>
<span class="line" id="L185"> total_similar_count += current_similar_count;</span>
<span class="line" id="L186"> index += current_similar_count;</span>
<span class="line" id="L187"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L188"> total_similar_count += current_similar_count;</span>
<span class="line" id="L189"></span>
<span class="line" id="L190"> <span class="tok-kw">try</span> flushRLE(writer, current_byte, total_similar_count);</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> total_similar_count = <span class="tok-number">0</span>;</span>
<span class="line" id="L193"></span>
<span class="line" id="L194"> index += current_similar_count;</span>
<span class="line" id="L195"> }</span>
<span class="line" id="L196"> }</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">try</span> flushRLE(writer, current_byte, total_similar_count);</span>
<span class="line" id="L199"></span>
<span class="line" id="L200"> <span class="tok-comment">// Process the rest sequentially</span>
</span>
<span class="line" id="L201"> total_similar_count = <span class="tok-number">0</span>;</span>
<span class="line" id="L202"> <span class="tok-kw">if</span> (index &lt; source_data.len) {</span>
<span class="line" id="L203"> current_byte = source_data[index];</span>
<span class="line" id="L204"></span>
<span class="line" id="L205"> <span class="tok-kw">while</span> (index &lt; source_data.len) {</span>
<span class="line" id="L206"> <span class="tok-kw">const</span> read_byte = source_data[index];</span>
<span class="line" id="L207"> <span class="tok-kw">if</span> (read_byte == current_byte) {</span>
<span class="line" id="L208"> total_similar_count += <span class="tok-number">1</span>;</span>
<span class="line" id="L209"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L210"> <span class="tok-kw">try</span> flushRLE(writer, current_byte, total_similar_count);</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> current_byte = read_byte;</span>
<span class="line" id="L213"> total_similar_count = <span class="tok-number">1</span>;</span>
<span class="line" id="L214"> }</span>
<span class="line" id="L215"></span>
<span class="line" id="L216"> index += <span class="tok-number">1</span>;</span>
<span class="line" id="L217"> }</span>
<span class="line" id="L218"></span>
<span class="line" id="L219"> <span class="tok-kw">try</span> flushRLE(writer, current_byte, total_similar_count);</span>
<span class="line" id="L220"> }</span>
<span class="line" id="L221"> }</span>
<span class="line" id="L222">};</span>
<span class="line" id="L223"></span>
<span class="line" id="L224"><span class="tok-kw">test</span> <span class="tok-str">&quot;PCX RLE Fast encoder&quot;</span> {</span>
<span class="line" id="L225"> <span class="tok-kw">const</span> uncompressed_data = [_]<span class="tok-type">u8</span>{ <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">1</span>, <span class="tok-number">64</span>, <span class="tok-number">64</span>, <span class="tok-number">2</span>, <span class="tok-number">2</span>, <span class="tok-number">2</span>, <span class="tok-number">2</span>, <span class="tok-number">2</span>, <span class="tok-number">215</span>, <span class="tok-number">215</span>, <span class="tok-number">215</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">3</span>, <span class="tok-number">200</span>, <span class="tok-number">200</span>, <span class="tok-number">200</span>, <span class="tok-number">200</span>, <span class="tok-number">210</span>, <span class="tok-number">210</span> };</span>
<span class="line" id="L226"> <span class="tok-kw">const</span> compressed_data = [_]<span class="tok-type">u8</span>{ <span class="tok-number">0xC9</span>, <span class="tok-number">0x01</span>, <span class="tok-number">0xC2</span>, <span class="tok-number">0x40</span>, <span class="tok-number">0xC5</span>, <span class="tok-number">0x02</span>, <span class="tok-number">0xC3</span>, <span class="tok-number">0xD7</span>, <span class="tok-number">0xCA</span>, <span class="tok-number">0x03</span>, <span class="tok-number">0xC4</span>, <span class="tok-number">0xC8</span>, <span class="tok-number">0xC2</span>, <span class="tok-number">0xD2</span> };</span>
<span class="line" id="L227"></span>
<span class="line" id="L228"> <span class="tok-kw">var</span> result_list = std.ArrayList(<span class="tok-type">u8</span>).init(std.testing.allocator);</span>
<span class="line" id="L229"> <span class="tok-kw">defer</span> result_list.deinit();</span>
<span class="line" id="L230"></span>
<span class="line" id="L231"> <span class="tok-kw">const</span> writer = result_list.writer();</span>
<span class="line" id="L232"></span>
<span class="line" id="L233"> <span class="tok-kw">try</span> RLEFastEncoder.encode(uncompressed_data[<span class="tok-number">0</span>..], writer);</span>
<span class="line" id="L234"></span>
<span class="line" id="L235"> <span class="tok-kw">try</span> std.testing.expectEqualSlices(<span class="tok-type">u8</span>, compressed_data[<span class="tok-number">0</span>..], result_list.items);</span>
<span class="line" id="L236">}</span>
<span class="line" id="L237"></span>
<span class="line" id="L238"><span class="tok-kw">test</span> <span class="tok-str">&quot;PCX RLE Fast encoder should encore more than 63 bytes similar&quot;</span> {</span>
<span class="line" id="L239"> <span class="tok-kw">const</span> first_uncompressed_part = [_]<span class="tok-type">u8</span>{<span class="tok-number">0x45</span>} ** <span class="tok-number">65</span>;</span>
<span class="line" id="L240"> <span class="tok-kw">const</span> second_uncompresse_part = [_]<span class="tok-type">u8</span>{ <span class="tok-number">0x1</span>, <span class="tok-number">0x1</span>, <span class="tok-number">0x1</span>, <span class="tok-number">0x1</span> };</span>
<span class="line" id="L241"> <span class="tok-kw">const</span> uncompressed_data = first_uncompressed_part ++ second_uncompresse_part;</span>
<span class="line" id="L242"></span>
<span class="line" id="L243"> <span class="tok-kw">const</span> compressed_data = [_]<span class="tok-type">u8</span>{ <span class="tok-number">0xFF</span>, <span class="tok-number">0x45</span>, <span class="tok-number">0x45</span>, <span class="tok-number">0x45</span>, <span class="tok-number">0xC4</span>, <span class="tok-number">0x1</span> };</span>
<span class="line" id="L244"></span>
<span class="line" id="L245"> <span class="tok-kw">var</span> result_list = std.ArrayList(<span class="tok-type">u8</span>).init(std.testing.allocator);</span>
<span class="line" id="L246"> <span class="tok-kw">defer</span> result_list.deinit();</span>
<span class="line" id="L247"></span>
<span class="line" id="L248"> <span class="tok-kw">const</span> writer = result_list.writer();</span>
<span class="line" id="L249"></span>
<span class="line" id="L250"> <span class="tok-kw">try</span> RLEFastEncoder.encode(uncompressed_data[<span class="tok-number">0</span>..], writer);</span>
<span class="line" id="L251"></span>
<span class="line" id="L252"> <span class="tok-kw">try</span> std.testing.expectEqualSlices(<span class="tok-type">u8</span>, compressed_data[<span class="tok-number">0</span>..], result_list.items);</span>
<span class="line" id="L253">}</span>
<span class="line" id="L254"></span>
<span class="line" id="L255"><span class="tok-kw">const</span> RLEStreamEncoder = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L256"> rle_byte: ?<span class="tok-type">u8</span> = <span class="tok-null">null</span>,</span>
<span class="line" id="L257"> length: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L258"></span>
<span class="line" id="L259"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">encode</span>(self: *RLEStreamEncoder, writer: <span class="tok-kw">anytype</span>, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L260"> <span class="tok-kw">for</span> (bytes) |byte| {</span>
<span class="line" id="L261"> <span class="tok-kw">try</span> self.encodeByte(writer, byte);</span>
<span class="line" id="L262"> }</span>
<span class="line" id="L263"> }</span>
<span class="line" id="L264"></span>
<span class="line" id="L265"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">encodeByte</span>(self: *RLEStreamEncoder, writer: <span class="tok-kw">anytype</span>, byte: <span class="tok-type">u8</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L266"> <span class="tok-kw">if</span> (self.rle_byte == <span class="tok-null">null</span>) {</span>
<span class="line" id="L267"> self.rle_byte = byte;</span>
<span class="line" id="L268"> self.length = <span class="tok-number">1</span>;</span>
<span class="line" id="L269"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L270"> }</span>
<span class="line" id="L271"></span>
<span class="line" id="L272"> <span class="tok-kw">if</span> (self.rle_byte) |rle_byte| {</span>
<span class="line" id="L273"> <span class="tok-kw">if</span> (rle_byte == byte) {</span>
<span class="line" id="L274"> self.length += <span class="tok-number">1</span>;</span>
<span class="line" id="L275"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L276"> <span class="tok-kw">try</span> flushRLE(writer, rle_byte, self.length);</span>
<span class="line" id="L277"></span>
<span class="line" id="L278"> self.length = <span class="tok-number">1</span>;</span>
<span class="line" id="L279"> self.rle_byte = byte;</span>
<span class="line" id="L280"> }</span>
<span class="line" id="L281"> }</span>
<span class="line" id="L282"> }</span>
<span class="line" id="L283"></span>
<span class="line" id="L284"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">flush</span>(self: *RLEStreamEncoder, writer: <span class="tok-kw">anytype</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L285"> <span class="tok-kw">if</span> (self.length == <span class="tok-number">0</span>) {</span>
<span class="line" id="L286"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L287"> }</span>
<span class="line" id="L288"></span>
<span class="line" id="L289"> <span class="tok-kw">if</span> (self.rle_byte) |check_byte| {</span>
<span class="line" id="L290"> <span class="tok-kw">try</span> flushRLE(writer, check_byte, self.length);</span>
<span class="line" id="L291"> }</span>
<span class="line" id="L292"> }</span>
<span class="line" id="L293">};</span>
<span class="line" id="L294"></span>
<span class="line" id="L295"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PCX = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L296"> header: PCXHeader = .{},</span>
<span class="line" id="L297"></span>
<span class="line" id="L298"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {};</span>
<span class="line" id="L299"></span>
<span class="line" id="L300"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L301"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L302"> .format = format,</span>
<span class="line" id="L303"> .formatDetect = formatDetect,</span>
<span class="line" id="L304"> .readImage = readImage,</span>
<span class="line" id="L305"> .writeImage = writeImage,</span>
<span class="line" id="L306"> };</span>
<span class="line" id="L307"> }</span>
<span class="line" id="L308"></span>
<span class="line" id="L309"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L310"> <span class="tok-kw">return</span> Image.Format.pcx;</span>
<span class="line" id="L311"> }</span>
<span class="line" id="L312"></span>
<span class="line" id="L313"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L314"> <span class="tok-kw">var</span> magic_number_bufffer: [<span class="tok-number">2</span>]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L315"> _ = <span class="tok-kw">try</span> stream.read(magic_number_bufffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L316"></span>
<span class="line" id="L317"> <span class="tok-kw">if</span> (magic_number_bufffer[<span class="tok-number">0</span>] != MagicHeader) {</span>
<span class="line" id="L318"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"></span>
<span class="line" id="L321"> <span class="tok-kw">if</span> (magic_number_bufffer[<span class="tok-number">1</span>] &gt; Version) {</span>
<span class="line" id="L322"> <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L323"> }</span>
<span class="line" id="L324"></span>
<span class="line" id="L325"> <span class="tok-kw">return</span> <span class="tok-null">true</span>;</span>
<span class="line" id="L326"> }</span>
<span class="line" id="L327"></span>
<span class="line" id="L328"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L329"> <span class="tok-kw">var</span> result = Image.init(allocator);</span>
<span class="line" id="L330"> <span class="tok-kw">errdefer</span> result.deinit();</span>
<span class="line" id="L331"> <span class="tok-kw">var</span> pcx = PCX{};</span>
<span class="line" id="L332"></span>
<span class="line" id="L333"> <span class="tok-kw">const</span> pixels = <span class="tok-kw">try</span> pcx.read(allocator, stream);</span>
<span class="line" id="L334"></span>
<span class="line" id="L335"> result.width = pcx.width();</span>
<span class="line" id="L336"> result.height = pcx.height();</span>
<span class="line" id="L337"> result.pixels = pixels;</span>
<span class="line" id="L338"></span>
<span class="line" id="L339"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L340"> }</span>
<span class="line" id="L341"></span>
<span class="line" id="L342"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: Allocator, stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L343"> _ = allocator;</span>
<span class="line" id="L344"> _ = encoder_options;</span>
<span class="line" id="L345"></span>
<span class="line" id="L346"> <span class="tok-kw">var</span> pcx = PCX{};</span>
<span class="line" id="L347"></span>
<span class="line" id="L348"> <span class="tok-kw">if</span> (image.width &gt; std.math.maxInt(<span class="tok-type">u16</span>) <span class="tok-kw">or</span> image.height &gt; std.math.maxInt(<span class="tok-type">u16</span>)) {</span>
<span class="line" id="L349"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L350"> }</span>
<span class="line" id="L351"></span>
<span class="line" id="L352"> pcx.header.xmax = <span class="tok-builtin">@truncate</span>(image.width - <span class="tok-number">1</span>);</span>
<span class="line" id="L353"> pcx.header.ymax = <span class="tok-builtin">@truncate</span>(image.height - <span class="tok-number">1</span>);</span>
<span class="line" id="L354"></span>
<span class="line" id="L355"> <span class="tok-comment">// Fill header info based on image</span>
</span>
<span class="line" id="L356"> <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L357"> .indexed1 =&gt; |pixels| {</span>
<span class="line" id="L358"> pcx.header.bpp = <span class="tok-number">1</span>;</span>
<span class="line" id="L359"> pcx.header.planes = <span class="tok-number">1</span>;</span>
<span class="line" id="L360"></span>
<span class="line" id="L361"> pcx.fillPalette(pixels.palette);</span>
<span class="line" id="L362"> },</span>
<span class="line" id="L363"> .indexed4 =&gt; |pixels| {</span>
<span class="line" id="L364"> pcx.header.bpp = <span class="tok-number">4</span>;</span>
<span class="line" id="L365"> pcx.header.planes = <span class="tok-number">1</span>;</span>
<span class="line" id="L366"></span>
<span class="line" id="L367"> pcx.fillPalette(pixels.palette);</span>
<span class="line" id="L368"> },</span>
<span class="line" id="L369"> .indexed8 =&gt; {</span>
<span class="line" id="L370"> pcx.header.bpp = <span class="tok-number">8</span>;</span>
<span class="line" id="L371"> pcx.header.planes = <span class="tok-number">1</span>;</span>
<span class="line" id="L372"> },</span>
<span class="line" id="L373"> .rgb24 =&gt; {</span>
<span class="line" id="L374"> pcx.header.bpp = <span class="tok-number">8</span>;</span>
<span class="line" id="L375"> pcx.header.planes = <span class="tok-number">3</span>;</span>
<span class="line" id="L376"> },</span>
<span class="line" id="L377"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L378"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L379"> },</span>
<span class="line" id="L380"> }</span>
<span class="line" id="L381"></span>
<span class="line" id="L382"> pcx.header.stride = <span class="tok-builtin">@as</span>(<span class="tok-type">u16</span>, <span class="tok-builtin">@intFromFloat</span>((<span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(image.width)) / <span class="tok-number">8.0</span>) * <span class="tok-builtin">@as</span>(<span class="tok-type">f32</span>, <span class="tok-builtin">@floatFromInt</span>(pcx.header.bpp))));</span>
<span class="line" id="L383"> <span class="tok-comment">// Add one if the result is a odd number</span>
</span>
<span class="line" id="L384"> pcx.header.stride += (pcx.header.stride &amp; <span class="tok-number">0x1</span>);</span>
<span class="line" id="L385"></span>
<span class="line" id="L386"> <span class="tok-kw">try</span> pcx.write(stream, image.pixels);</span>
<span class="line" id="L387"> }</span>
<span class="line" id="L388"></span>
<span class="line" id="L389"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelFormat</span>(self: PCX) ImageReadError!PixelFormat {</span>
<span class="line" id="L390"> <span class="tok-kw">if</span> (self.header.planes == <span class="tok-number">1</span>) {</span>
<span class="line" id="L391"> <span class="tok-kw">switch</span> (self.header.bpp) {</span>
<span class="line" id="L392"> <span class="tok-number">1</span> =&gt; <span class="tok-kw">return</span> PixelFormat.indexed1,</span>
<span class="line" id="L393"> <span class="tok-number">4</span> =&gt; <span class="tok-kw">return</span> PixelFormat.indexed4,</span>
<span class="line" id="L394"> <span class="tok-number">8</span> =&gt; <span class="tok-kw">return</span> PixelFormat.indexed8,</span>
<span class="line" id="L395"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L396"> }</span>
<span class="line" id="L397"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (self.header.planes == <span class="tok-number">3</span>) {</span>
<span class="line" id="L398"> <span class="tok-kw">switch</span> (self.header.bpp) {</span>
<span class="line" id="L399"> <span class="tok-number">8</span> =&gt; <span class="tok-kw">return</span> PixelFormat.rgb24,</span>
<span class="line" id="L400"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L401"> }</span>
<span class="line" id="L402"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L403"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L404"> }</span>
<span class="line" id="L405"> }</span>
<span class="line" id="L406"></span>
<span class="line" id="L407"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">width</span>(self: PCX) <span class="tok-type">usize</span> {</span>
<span class="line" id="L408"> <span class="tok-kw">return</span> self.header.xmax - self.header.xmin + <span class="tok-number">1</span>;</span>
<span class="line" id="L409"> }</span>
<span class="line" id="L410"></span>
<span class="line" id="L411"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">height</span>(self: PCX) <span class="tok-type">usize</span> {</span>
<span class="line" id="L412"> <span class="tok-kw">return</span> self.header.ymax - self.header.ymin + <span class="tok-number">1</span>;</span>
<span class="line" id="L413"> }</span>
<span class="line" id="L414"></span>
<span class="line" id="L415"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *PCX, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {</span>
<span class="line" id="L416"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L417"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L418"> self.header = <span class="tok-kw">try</span> utils.readStruct(reader, PCXHeader, .little);</span>
<span class="line" id="L419"></span>
<span class="line" id="L420"> <span class="tok-kw">if</span> (self.header.id != <span class="tok-number">0x0A</span>) {</span>
<span class="line" id="L421"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L422"> }</span>
<span class="line" id="L423"></span>
<span class="line" id="L424"> <span class="tok-kw">if</span> (self.header.version &gt; <span class="tok-number">0x05</span>) {</span>
<span class="line" id="L425"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L426"> }</span>
<span class="line" id="L427"></span>
<span class="line" id="L428"> <span class="tok-kw">if</span> (self.header.planes &gt; <span class="tok-number">3</span>) {</span>
<span class="line" id="L429"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L430"> }</span>
<span class="line" id="L431"></span>
<span class="line" id="L432"> <span class="tok-kw">const</span> pixel_format = <span class="tok-kw">try</span> self.pixelFormat();</span>
<span class="line" id="L433"></span>
<span class="line" id="L434"> <span class="tok-kw">const</span> image_width = self.width();</span>
<span class="line" id="L435"> <span class="tok-kw">const</span> image_height = self.height();</span>
<span class="line" id="L436"></span>
<span class="line" id="L437"> <span class="tok-kw">const</span> has_dummy_byte = (<span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, <span class="tok-builtin">@bitCast</span>(self.header.stride)) - <span class="tok-builtin">@as</span>(<span class="tok-type">isize</span>, <span class="tok-builtin">@bitCast</span>(image_width))) == <span class="tok-number">1</span>;</span>
<span class="line" id="L438"> <span class="tok-kw">const</span> actual_width = <span class="tok-kw">if</span> (has_dummy_byte) image_width + <span class="tok-number">1</span> <span class="tok-kw">else</span> image_width;</span>
<span class="line" id="L439"></span>
<span class="line" id="L440"> <span class="tok-kw">var</span> pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, image_width * image_height);</span>
<span class="line" id="L441"> <span class="tok-kw">errdefer</span> pixels.deinit(allocator);</span>
<span class="line" id="L442"></span>
<span class="line" id="L443"> <span class="tok-kw">var</span> decoder = RLEDecoder.init(reader);</span>
<span class="line" id="L444"></span>
<span class="line" id="L445"> <span class="tok-kw">const</span> scanline_length = (self.header.stride * self.header.planes);</span>
<span class="line" id="L446"></span>
<span class="line" id="L447"> <span class="tok-kw">var</span> y: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L448"> <span class="tok-kw">while</span> (y &lt; image_height) : (y += <span class="tok-number">1</span>) {</span>
<span class="line" id="L449"> <span class="tok-kw">var</span> offset: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L450"> <span class="tok-kw">var</span> x: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L451"></span>
<span class="line" id="L452"> <span class="tok-kw">const</span> y_stride = y * image_width;</span>
<span class="line" id="L453"></span>
<span class="line" id="L454"> <span class="tok-comment">// read all pixels from the current row</span>
</span>
<span class="line" id="L455"> <span class="tok-kw">while</span> (offset &lt; scanline_length <span class="tok-kw">and</span> x &lt; image_width) : (offset += <span class="tok-number">1</span>) {</span>
<span class="line" id="L456"> <span class="tok-kw">const</span> byte = <span class="tok-kw">try</span> decoder.readByte();</span>
<span class="line" id="L457"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L458"> .indexed1 =&gt; |storage| {</span>
<span class="line" id="L459"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L460"> <span class="tok-kw">while</span> (i &lt; <span class="tok-number">8</span>) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L461"> <span class="tok-kw">if</span> (x &lt; image_width) {</span>
<span class="line" id="L462"> storage.indices[y_stride + x] = <span class="tok-builtin">@intCast</span>((byte &gt;&gt; (<span class="tok-number">7</span> - <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(i)))) &amp; <span class="tok-number">0x01</span>);</span>
<span class="line" id="L463"> x += <span class="tok-number">1</span>;</span>
<span class="line" id="L464"> }</span>
<span class="line" id="L465"> }</span>
<span class="line" id="L466"> },</span>
<span class="line" id="L467"> .indexed4 =&gt; |storage| {</span>
<span class="line" id="L468"> storage.indices[y_stride + x] = <span class="tok-builtin">@truncate</span>(byte &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L469"> x += <span class="tok-number">1</span>;</span>
<span class="line" id="L470"> <span class="tok-kw">if</span> (x &lt; image_width) {</span>
<span class="line" id="L471"> storage.indices[y_stride + x] = <span class="tok-builtin">@truncate</span>(byte);</span>
<span class="line" id="L472"> x += <span class="tok-number">1</span>;</span>
<span class="line" id="L473"> }</span>
<span class="line" id="L474"> },</span>
<span class="line" id="L475"> .indexed8 =&gt; |storage| {</span>
<span class="line" id="L476"> storage.indices[y_stride + x] = byte;</span>
<span class="line" id="L477"> x += <span class="tok-number">1</span>;</span>
<span class="line" id="L478"> },</span>
<span class="line" id="L479"> .rgb24 =&gt; |storage| {</span>
<span class="line" id="L480"> <span class="tok-kw">if</span> (has_dummy_byte <span class="tok-kw">and</span> byte == <span class="tok-number">0x00</span>) {</span>
<span class="line" id="L481"> <span class="tok-kw">continue</span>;</span>
<span class="line" id="L482"> }</span>
<span class="line" id="L483"> <span class="tok-kw">const</span> pixel_x = offset % (actual_width);</span>
<span class="line" id="L484"> <span class="tok-kw">const</span> current_color = offset / (actual_width);</span>
<span class="line" id="L485"> <span class="tok-kw">switch</span> (current_color) {</span>
<span class="line" id="L486"> <span class="tok-number">0</span> =&gt; {</span>
<span class="line" id="L487"> storage[y_stride + pixel_x].r = byte;</span>
<span class="line" id="L488"> },</span>
<span class="line" id="L489"> <span class="tok-number">1</span> =&gt; {</span>
<span class="line" id="L490"> storage[y_stride + pixel_x].g = byte;</span>
<span class="line" id="L491"> },</span>
<span class="line" id="L492"> <span class="tok-number">2</span> =&gt; {</span>
<span class="line" id="L493"> storage[y_stride + pixel_x].b = byte;</span>
<span class="line" id="L494"> },</span>
<span class="line" id="L495"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L496"> }</span>
<span class="line" id="L497"></span>
<span class="line" id="L498"> <span class="tok-kw">if</span> (pixel_x &gt; <span class="tok-number">0</span> <span class="tok-kw">and</span> (pixel_x % self.header.planes) == <span class="tok-number">0</span>) {</span>
<span class="line" id="L499"> x += <span class="tok-number">1</span>;</span>
<span class="line" id="L500"> }</span>
<span class="line" id="L501"> },</span>
<span class="line" id="L502"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L503"> }</span>
<span class="line" id="L504"> }</span>
<span class="line" id="L505"></span>
<span class="line" id="L506"> <span class="tok-comment">// discard the rest of the bytes in the current row</span>
</span>
<span class="line" id="L507"> <span class="tok-kw">while</span> (offset &lt; self.header.stride) : (offset += <span class="tok-number">1</span>) {</span>
<span class="line" id="L508"> _ = <span class="tok-kw">try</span> decoder.readByte();</span>
<span class="line" id="L509"> }</span>
<span class="line" id="L510"> }</span>
<span class="line" id="L511"></span>
<span class="line" id="L512"> <span class="tok-kw">try</span> decoder.finish();</span>
<span class="line" id="L513"></span>
<span class="line" id="L514"> <span class="tok-kw">if</span> (pixel_format == .indexed1 <span class="tok-kw">or</span> pixel_format == .indexed4 <span class="tok-kw">or</span> pixel_format == .indexed8) {</span>
<span class="line" id="L515"> <span class="tok-kw">var</span> palette = <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L516"> .indexed1 =&gt; |*storage| storage.palette[<span class="tok-number">0</span>..],</span>
<span class="line" id="L517"> .indexed4 =&gt; |*storage| storage.palette[<span class="tok-number">0</span>..],</span>
<span class="line" id="L518"> .indexed8 =&gt; |*storage| storage.palette[<span class="tok-number">0</span>..],</span>
<span class="line" id="L519"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">undefined</span>,</span>
<span class="line" id="L520"> };</span>
<span class="line" id="L521"></span>
<span class="line" id="L522"> <span class="tok-kw">const</span> effective_len = <span class="tok-builtin">@min</span>(palette.len, self.header.builtin_palette.len);</span>
<span class="line" id="L523"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..effective_len) |index| {</span>
<span class="line" id="L524"> palette[index].r = self.header.builtin_palette[index].r;</span>
<span class="line" id="L525"> palette[index].g = self.header.builtin_palette[index].g;</span>
<span class="line" id="L526"> palette[index].b = self.header.builtin_palette[index].b;</span>
<span class="line" id="L527"> palette[index].a = <span class="tok-number">255</span>;</span>
<span class="line" id="L528"> }</span>
<span class="line" id="L529"></span>
<span class="line" id="L530"> <span class="tok-kw">if</span> (pixels == .indexed8) {</span>
<span class="line" id="L531"> <span class="tok-kw">const</span> end_pos = <span class="tok-kw">try</span> buffered_stream.getEndPos();</span>
<span class="line" id="L532"> <span class="tok-kw">try</span> buffered_stream.seekTo(end_pos - <span class="tok-number">769</span>);</span>
<span class="line" id="L533"></span>
<span class="line" id="L534"> <span class="tok-kw">if</span> ((<span class="tok-kw">try</span> reader.readByte()) != VGAPaletteIdentifier) {</span>
<span class="line" id="L535"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L536"> }</span>
<span class="line" id="L537"></span>
<span class="line" id="L538"> <span class="tok-kw">for</span> (palette) |*current_entry| {</span>
<span class="line" id="L539"> current_entry.r = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L540"> current_entry.g = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L541"> current_entry.b = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L542"> current_entry.a = <span class="tok-number">255</span>;</span>
<span class="line" id="L543"> }</span>
<span class="line" id="L544"> }</span>
<span class="line" id="L545"> }</span>
<span class="line" id="L546"></span>
<span class="line" id="L547"> <span class="tok-kw">return</span> pixels;</span>
<span class="line" id="L548"> }</span>
<span class="line" id="L549"></span>
<span class="line" id="L550"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: PCX, stream: *Image.Stream, pixels: color.PixelStorage) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L551"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L552"> .indexed1,</span>
<span class="line" id="L553"> .indexed4,</span>
<span class="line" id="L554"> .indexed8,</span>
<span class="line" id="L555"> .rgb24,</span>
<span class="line" id="L556"> =&gt; {</span>
<span class="line" id="L557"> <span class="tok-comment">// Do nothing</span>
</span>
<span class="line" id="L558"> },</span>
<span class="line" id="L559"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L560"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L561"> },</span>
<span class="line" id="L562"> }</span>
<span class="line" id="L563"></span>
<span class="line" id="L564"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);</span>
<span class="line" id="L565"></span>
<span class="line" id="L566"> <span class="tok-kw">const</span> writer = buffered_stream.writer();</span>
<span class="line" id="L567"></span>
<span class="line" id="L568"> <span class="tok-kw">try</span> utils.writeStruct(writer, self.header, .little);</span>
<span class="line" id="L569"></span>
<span class="line" id="L570"> <span class="tok-kw">const</span> actual_width = self.width();</span>
<span class="line" id="L571"> <span class="tok-kw">const</span> is_even = ((actual_width &amp; <span class="tok-number">0x1</span>) == <span class="tok-number">0</span>);</span>
<span class="line" id="L572"></span>
<span class="line" id="L573"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L574"> .indexed1 =&gt; |indexed| {</span>
<span class="line" id="L575"> <span class="tok-kw">try</span> self.writeIndexed1(writer, indexed);</span>
<span class="line" id="L576"> },</span>
<span class="line" id="L577"> .indexed4 =&gt; |indexed| {</span>
<span class="line" id="L578"> <span class="tok-kw">try</span> self.writeIndexed4(writer, indexed);</span>
<span class="line" id="L579"> },</span>
<span class="line" id="L580"> .indexed8 =&gt; |indexed| {</span>
<span class="line" id="L581"> <span class="tok-kw">if</span> (is_even) {</span>
<span class="line" id="L582"> <span class="tok-kw">try</span> writeIndexed8Even(writer, indexed);</span>
<span class="line" id="L583"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L584"> <span class="tok-kw">try</span> self.writeIndexed8Odd(writer, indexed);</span>
<span class="line" id="L585"> }</span>
<span class="line" id="L586"></span>
<span class="line" id="L587"> <span class="tok-comment">// Write VGA palette</span>
</span>
<span class="line" id="L588"> <span class="tok-kw">try</span> writer.writeByte(VGAPaletteIdentifier);</span>
<span class="line" id="L589"> <span class="tok-kw">for</span> (pixels.indexed8.palette) |current_entry| {</span>
<span class="line" id="L590"> <span class="tok-kw">const</span> rgb24_color = color.Rgb24.fromU32Rgba(current_entry.toU32Rgba());</span>
<span class="line" id="L591"> <span class="tok-kw">try</span> utils.writeStruct(writer, rgb24_color, .little);</span>
<span class="line" id="L592"> }</span>
<span class="line" id="L593"> },</span>
<span class="line" id="L594"> .rgb24 =&gt; |data| {</span>
<span class="line" id="L595"> <span class="tok-kw">try</span> self.writeRgb24(writer, data);</span>
<span class="line" id="L596"> },</span>
<span class="line" id="L597"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L598"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L599"> },</span>
<span class="line" id="L600"> }</span>
<span class="line" id="L601"></span>
<span class="line" id="L602"> <span class="tok-kw">try</span> buffered_stream.flush();</span>
<span class="line" id="L603"> }</span>
<span class="line" id="L604"></span>
<span class="line" id="L605"> <span class="tok-kw">fn</span> <span class="tok-fn">fillPalette</span>(self: *PCX, palette: []<span class="tok-kw">const</span> color.Rgba32) <span class="tok-type">void</span> {</span>
<span class="line" id="L606"> <span class="tok-kw">const</span> effective_len = <span class="tok-builtin">@min</span>(palette.len, self.header.builtin_palette.len);</span>
<span class="line" id="L607"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..effective_len) |index| {</span>
<span class="line" id="L608"> self.header.builtin_palette[index].r = palette[index].r;</span>
<span class="line" id="L609"> self.header.builtin_palette[index].g = palette[index].g;</span>
<span class="line" id="L610"> self.header.builtin_palette[index].b = palette[index].b;</span>
<span class="line" id="L611"> }</span>
<span class="line" id="L612"> }</span>
<span class="line" id="L613"></span>
<span class="line" id="L614"> <span class="tok-kw">fn</span> <span class="tok-fn">writeIndexed1</span>(self: *<span class="tok-kw">const</span> PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage1) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L615"> <span class="tok-kw">var</span> rle_encoder = RLEStreamEncoder{};</span>
<span class="line" id="L616"></span>
<span class="line" id="L617"> <span class="tok-kw">const</span> image_width = self.width();</span>
<span class="line" id="L618"> <span class="tok-kw">const</span> image_height = self.height();</span>
<span class="line" id="L619"></span>
<span class="line" id="L620"> <span class="tok-kw">const</span> is_even = ((image_width &amp; <span class="tok-number">0x1</span>) == <span class="tok-number">0</span>);</span>
<span class="line" id="L621"></span>
<span class="line" id="L622"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_height) |y| {</span>
<span class="line" id="L623"> <span class="tok-kw">const</span> stride = y * image_width;</span>
<span class="line" id="L624"></span>
<span class="line" id="L625"> <span class="tok-kw">var</span> current_byte: <span class="tok-type">u8</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L626"></span>
<span class="line" id="L627"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_width) |x| {</span>
<span class="line" id="L628"> <span class="tok-kw">const</span> pixel = indexed.indices[stride + x];</span>
<span class="line" id="L629"></span>
<span class="line" id="L630"> <span class="tok-kw">const</span> bit = <span class="tok-builtin">@as</span>(<span class="tok-type">u3</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-number">7</span> - (x % <span class="tok-number">8</span>)));</span>
<span class="line" id="L631"></span>
<span class="line" id="L632"> current_byte |= <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, pixel) &lt;&lt; bit;</span>
<span class="line" id="L633"> <span class="tok-kw">if</span> (bit == <span class="tok-number">0</span>) {</span>
<span class="line" id="L634"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_byte);</span>
<span class="line" id="L635"> current_byte = <span class="tok-number">0</span>;</span>
<span class="line" id="L636"> }</span>
<span class="line" id="L637"> }</span>
<span class="line" id="L638"></span>
<span class="line" id="L639"> <span class="tok-kw">if</span> (!is_even) {</span>
<span class="line" id="L640"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_byte);</span>
<span class="line" id="L641"> }</span>
<span class="line" id="L642"> }</span>
<span class="line" id="L643"></span>
<span class="line" id="L644"> <span class="tok-kw">try</span> rle_encoder.flush(writer);</span>
<span class="line" id="L645"> }</span>
<span class="line" id="L646"></span>
<span class="line" id="L647"> <span class="tok-kw">fn</span> <span class="tok-fn">writeIndexed4</span>(self: *<span class="tok-kw">const</span> PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage4) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L648"> <span class="tok-kw">var</span> rle_encoder = RLEStreamEncoder{};</span>
<span class="line" id="L649"></span>
<span class="line" id="L650"> <span class="tok-kw">const</span> image_width = self.width();</span>
<span class="line" id="L651"> <span class="tok-kw">const</span> image_height = self.height();</span>
<span class="line" id="L652"></span>
<span class="line" id="L653"> <span class="tok-kw">const</span> is_even = ((image_width &amp; <span class="tok-number">0x1</span>) == <span class="tok-number">0</span>);</span>
<span class="line" id="L654"></span>
<span class="line" id="L655"> <span class="tok-kw">var</span> current_byte: <span class="tok-type">u8</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L656"></span>
<span class="line" id="L657"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_height) |y| {</span>
<span class="line" id="L658"> <span class="tok-kw">const</span> stride = y * image_width;</span>
<span class="line" id="L659"></span>
<span class="line" id="L660"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_width) |x| {</span>
<span class="line" id="L661"> <span class="tok-kw">const</span> pixel = indexed.indices[stride + x];</span>
<span class="line" id="L662"></span>
<span class="line" id="L663"> <span class="tok-kw">if</span> ((x &amp; <span class="tok-number">0x1</span>) == <span class="tok-number">0x1</span>) {</span>
<span class="line" id="L664"> current_byte |= pixel;</span>
<span class="line" id="L665"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_byte);</span>
<span class="line" id="L666"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L667"> current_byte = <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, pixel) &lt;&lt; <span class="tok-number">4</span>;</span>
<span class="line" id="L668"> }</span>
<span class="line" id="L669"> }</span>
<span class="line" id="L670"></span>
<span class="line" id="L671"> <span class="tok-kw">if</span> (!is_even) {</span>
<span class="line" id="L672"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_byte);</span>
<span class="line" id="L673"> }</span>
<span class="line" id="L674"> }</span>
<span class="line" id="L675"></span>
<span class="line" id="L676"> <span class="tok-kw">try</span> rle_encoder.flush(writer);</span>
<span class="line" id="L677"> }</span>
<span class="line" id="L678"></span>
<span class="line" id="L679"> <span class="tok-kw">fn</span> <span class="tok-fn">writeIndexed8Even</span>(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L680"> <span class="tok-kw">try</span> RLEFastEncoder.encode(indexed.indices, writer);</span>
<span class="line" id="L681"> }</span>
<span class="line" id="L682"></span>
<span class="line" id="L683"> <span class="tok-kw">fn</span> <span class="tok-fn">writeIndexed8Odd</span>(self: *<span class="tok-kw">const</span> PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, indexed: color.IndexedStorage8) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L684"> <span class="tok-kw">var</span> rle_encoder = RLEStreamEncoder{};</span>
<span class="line" id="L685"></span>
<span class="line" id="L686"> <span class="tok-kw">const</span> image_width = self.width();</span>
<span class="line" id="L687"> <span class="tok-kw">const</span> image_height = self.height();</span>
<span class="line" id="L688"></span>
<span class="line" id="L689"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_height) |y| {</span>
<span class="line" id="L690"> <span class="tok-kw">const</span> y_stride = y * image_width;</span>
<span class="line" id="L691"></span>
<span class="line" id="L692"> <span class="tok-kw">const</span> pixel_stride = indexed.indices[y_stride..(y_stride + image_width)];</span>
<span class="line" id="L693"> <span class="tok-kw">try</span> rle_encoder.encode(writer, pixel_stride);</span>
<span class="line" id="L694"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, <span class="tok-number">0x00</span>);</span>
<span class="line" id="L695"> }</span>
<span class="line" id="L696"></span>
<span class="line" id="L697"> <span class="tok-kw">try</span> rle_encoder.flush(writer);</span>
<span class="line" id="L698"> }</span>
<span class="line" id="L699"></span>
<span class="line" id="L700"> <span class="tok-kw">fn</span> <span class="tok-fn">writeRgb24</span>(self: *<span class="tok-kw">const</span> PCX, writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels: []<span class="tok-kw">const</span> color.Rgb24) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L701"> <span class="tok-kw">var</span> rle_encoder = RLEStreamEncoder{};</span>
<span class="line" id="L702"></span>
<span class="line" id="L703"> <span class="tok-kw">const</span> image_width = self.width();</span>
<span class="line" id="L704"> <span class="tok-kw">const</span> image_height = self.height();</span>
<span class="line" id="L705"></span>
<span class="line" id="L706"> <span class="tok-kw">const</span> is_even = ((image_width &amp; <span class="tok-number">0x1</span>) == <span class="tok-number">0</span>);</span>
<span class="line" id="L707"></span>
<span class="line" id="L708"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_height) |y| {</span>
<span class="line" id="L709"> <span class="tok-kw">const</span> stride = y * image_width;</span>
<span class="line" id="L710"></span>
<span class="line" id="L711"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..<span class="tok-number">3</span>) |plane| {</span>
<span class="line" id="L712"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..image_width) |x| {</span>
<span class="line" id="L713"> <span class="tok-kw">const</span> current_color = pixels[stride + x];</span>
<span class="line" id="L714"> <span class="tok-kw">switch</span> (plane) {</span>
<span class="line" id="L715"> <span class="tok-number">0</span> =&gt; <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_color.r),</span>
<span class="line" id="L716"> <span class="tok-number">1</span> =&gt; <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_color.g),</span>
<span class="line" id="L717"> <span class="tok-number">2</span> =&gt; <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, current_color.b),</span>
<span class="line" id="L718"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L719"> }</span>
<span class="line" id="L720"> }</span>
<span class="line" id="L721"></span>
<span class="line" id="L722"> <span class="tok-kw">if</span> (!is_even) {</span>
<span class="line" id="L723"> <span class="tok-kw">try</span> rle_encoder.encodeByte(writer, <span class="tok-number">0x00</span>);</span>
<span class="line" id="L724"> }</span>
<span class="line" id="L725"> }</span>
<span class="line" id="L726"> }</span>
<span class="line" id="L727"></span>
<span class="line" id="L728"> <span class="tok-kw">try</span> rle_encoder.flush(writer);</span>
<span class="line" id="L729"> }</span>
<span class="line" id="L730">};</span>
<span class="line" id="L731"></span>
</code></pre></body>
</html>

View file

@ -1,351 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/png.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Implement PNG image format according to W3C Portable Network Graphics (PNG) specification second edition (ISO/IEC 15948:2003 (E))</span>
</span>
<span class="line" id="L2"><span class="tok-comment">// Last version: https://www.w3.org/TR/PNG/</span>
</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> chunk_writer = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png/chunk_writer.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> filter = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png/filtering.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L11"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L12"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L13"><span class="tok-kw">const</span> reader = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png/reader.zig&quot;</span>);</span>
<span class="line" id="L14"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L15"><span class="tok-kw">const</span> types = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png/types.zig&quot;</span>);</span>
<span class="line" id="L16"><span class="tok-kw">const</span> ZlibCompressor = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;png/zlib_compressor.zig&quot;</span>).ZlibCompressor;</span>
<span class="line" id="L17"></span>
<span class="line" id="L18"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HeaderData = types.HeaderData;</span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ColorType = types.ColorType;</span>
<span class="line" id="L20"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CompressionMethod = types.CompressionMethod;</span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterMethod = types.FilterMethod;</span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterType = types.FilterType;</span>
<span class="line" id="L23"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> InterlaceMethod = types.InterlaceMethod;</span>
<span class="line" id="L24"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Chunks = types.Chunks;</span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> isChunkCritical = reader.isChunkCritical;</span>
<span class="line" id="L26"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> load = reader.load;</span>
<span class="line" id="L27"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> loadHeader = reader.loadHeader;</span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> loadWithHeader = reader.loadWithHeader;</span>
<span class="line" id="L29"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ChunkProcessData = reader.ChunkProcessData;</span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PaletteProcessData = reader.PaletteProcessData;</span>
<span class="line" id="L31"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> RowProcessData = reader.RowProcessData;</span>
<span class="line" id="L32"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ReaderProcessor = reader.ReaderProcessor;</span>
<span class="line" id="L33"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> TrnsProcessor = reader.TrnsProcessor;</span>
<span class="line" id="L34"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PlteProcessor = reader.PlteProcessor;</span>
<span class="line" id="L35"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ReaderOptions = reader.ReaderOptions;</span>
<span class="line" id="L36"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> DefaultProcessors = reader.DefaultProcessors;</span>
<span class="line" id="L37"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> DefaultOptions = reader.DefaultOptions;</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PNG = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L40"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L43"> <span class="tok-comment">// For progressive rendering of big images</span>
</span>
<span class="line" id="L44"> interlaced: <span class="tok-type">bool</span> = <span class="tok-null">false</span>,</span>
<span class="line" id="L45"> <span class="tok-comment">// Changing this can affect performance positively or negatively</span>
</span>
<span class="line" id="L46"> filter_choice: filter.FilterChoice = .heuristic,</span>
<span class="line" id="L47"> };</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L50"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L51"> .format = format,</span>
<span class="line" id="L52"> .formatDetect = formatDetect,</span>
<span class="line" id="L53"> .readImage = readImage,</span>
<span class="line" id="L54"> .writeImage = writeImage,</span>
<span class="line" id="L55"> };</span>
<span class="line" id="L56"> }</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L59"> <span class="tok-kw">return</span> Image.Format.png;</span>
<span class="line" id="L60"> }</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L63"> <span class="tok-kw">var</span> magic_buffer: [types.magic_header.len]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> _ = <span class="tok-kw">try</span> stream.reader().readAll(magic_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L66"></span>
<span class="line" id="L67"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, magic_buffer[<span class="tok-number">0</span>..], types.magic_header[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L71"> <span class="tok-kw">var</span> default_options = DefaultOptions{};</span>
<span class="line" id="L72"> <span class="tok-kw">return</span> load(stream, allocator, default_options.get());</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(_: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L76"> <span class="tok-kw">const</span> options = encoder_options.png;</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-kw">try</span> ensureWritable(image);</span>
<span class="line" id="L79"></span>
<span class="line" id="L80"> <span class="tok-kw">const</span> header = HeaderData{</span>
<span class="line" id="L81"> .width = <span class="tok-builtin">@truncate</span>(image.width),</span>
<span class="line" id="L82"> .height = <span class="tok-builtin">@truncate</span>(image.height),</span>
<span class="line" id="L83"> .bit_depth = image.pixelFormat().bitsPerChannel(),</span>
<span class="line" id="L84"> .color_type = <span class="tok-kw">try</span> types.ColorType.fromPixelFormat(image.pixelFormat()),</span>
<span class="line" id="L85"> .compression_method = .deflate,</span>
<span class="line" id="L86"> .filter_method = .adaptive,</span>
<span class="line" id="L87"> .interlace_method = <span class="tok-kw">if</span> (options.interlaced) .adam7 <span class="tok-kw">else</span> .none,</span>
<span class="line" id="L88"> };</span>
<span class="line" id="L89"></span>
<span class="line" id="L90"> std.debug.assert(header.isValid());</span>
<span class="line" id="L91"></span>
<span class="line" id="L92"> <span class="tok-kw">try</span> write(write_stream, image.pixels, header, options.filter_choice);</span>
<span class="line" id="L93"> }</span>
<span class="line" id="L94"></span>
<span class="line" id="L95"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(write_stream: *Image.Stream, pixels: color.PixelStorage, header: HeaderData, filter_choice: filter.FilterChoice) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L96"> <span class="tok-kw">if</span> (header.interlace_method != .none)</span>
<span class="line" id="L97"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L98"> <span class="tok-kw">if</span> (header.compression_method != .deflate)</span>
<span class="line" id="L99"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L100"> <span class="tok-kw">if</span> (header.filter_method != .adaptive)</span>
<span class="line" id="L101"> <span class="tok-kw">return</span> ImageWriteError.Unsupported;</span>
<span class="line" id="L102"></span>
<span class="line" id="L103"> <span class="tok-kw">const</span> writer = write_stream.writer();</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"> <span class="tok-kw">try</span> writeSignature(writer);</span>
<span class="line" id="L106"> <span class="tok-kw">try</span> writeHeader(writer, header);</span>
<span class="line" id="L107"> <span class="tok-kw">if</span> (PixelFormat.isIndexed(pixels)) {</span>
<span class="line" id="L108"> <span class="tok-kw">try</span> writePalette(writer, pixels);</span>
<span class="line" id="L109"> <span class="tok-kw">try</span> writeTransparencyInfo(writer, pixels); <span class="tok-comment">// TODO: pixel format where there is no transparency</span>
</span>
<span class="line" id="L110"> }</span>
<span class="line" id="L111"> <span class="tok-kw">try</span> writeData(writer, pixels, header, filter_choice);</span>
<span class="line" id="L112"> <span class="tok-kw">try</span> writeTrailer(writer);</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114"></span>
<span class="line" id="L115"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">ensureWritable</span>(image: Image) !<span class="tok-type">void</span> {</span>
<span class="line" id="L116"> <span class="tok-kw">if</span> (image.width &gt; std.math.maxInt(<span class="tok-type">u31</span>))</span>
<span class="line" id="L117"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported;</span>
<span class="line" id="L118"> <span class="tok-kw">if</span> (image.height &gt; std.math.maxInt(<span class="tok-type">u31</span>))</span>
<span class="line" id="L119"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported;</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"> <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L122"> .rgb24, .rgb48, .rgba32, .rgba64, .grayscale8, .grayscale16, .grayscale8Alpha, .grayscale16Alpha, .indexed8 =&gt; {},</span>
<span class="line" id="L123"></span>
<span class="line" id="L124"> .grayscale1, .grayscale2, .grayscale4, .indexed1, .indexed2, .indexed4 =&gt; <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported, <span class="tok-comment">// TODO</span>
</span>
<span class="line" id="L125"></span>
<span class="line" id="L126"> <span class="tok-comment">// Should bgr be supported with swapping operations during the filtering?</span>
</span>
<span class="line" id="L127"></span>
<span class="line" id="L128"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported,</span>
<span class="line" id="L129"> }</span>
<span class="line" id="L130"> }</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> <span class="tok-kw">fn</span> <span class="tok-fn">writeSignature</span>(writer: <span class="tok-kw">anytype</span>) !<span class="tok-type">void</span> {</span>
<span class="line" id="L133"> <span class="tok-kw">try</span> writer.writeAll(types.magic_header);</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"></span>
<span class="line" id="L136"> <span class="tok-comment">// IHDR</span>
</span>
<span class="line" id="L137"> <span class="tok-kw">fn</span> <span class="tok-fn">writeHeader</span>(writer: <span class="tok-kw">anytype</span>, header: HeaderData) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> chunk = chunk_writer.chunkWriter(writer, <span class="tok-str">&quot;IHDR&quot;</span>);</span>
<span class="line" id="L139"> <span class="tok-kw">var</span> chunk_wr = chunk.writer();</span>
<span class="line" id="L140"></span>
<span class="line" id="L141"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u32</span>, header.width, .big);</span>
<span class="line" id="L142"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u32</span>, header.height, .big);</span>
<span class="line" id="L143"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u8</span>, header.bit_depth, .big);</span>
<span class="line" id="L144"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u8</span>, <span class="tok-builtin">@intFromEnum</span>(header.color_type), .big);</span>
<span class="line" id="L145"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u8</span>, <span class="tok-builtin">@intFromEnum</span>(header.compression_method), .big);</span>
<span class="line" id="L146"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u8</span>, <span class="tok-builtin">@intFromEnum</span>(header.filter_method), .big);</span>
<span class="line" id="L147"> <span class="tok-kw">try</span> chunk_wr.writeInt(<span class="tok-type">u8</span>, <span class="tok-builtin">@intFromEnum</span>(header.interlace_method), .big);</span>
<span class="line" id="L148"></span>
<span class="line" id="L149"> <span class="tok-kw">try</span> chunk.flush();</span>
<span class="line" id="L150"> }</span>
<span class="line" id="L151"></span>
<span class="line" id="L152"> <span class="tok-comment">// IDAT (multiple maybe)</span>
</span>
<span class="line" id="L153"> <span class="tok-kw">fn</span> <span class="tok-fn">writeData</span>(writer: <span class="tok-kw">anytype</span>, pixels: color.PixelStorage, header: HeaderData, filter_choice: filter.FilterChoice) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L154"> <span class="tok-comment">// Note: there may be more than 1 chunk</span>
</span>
<span class="line" id="L155"> <span class="tok-comment">// TODO: provide choice of how much it buffers (how much data per idat chunk)</span>
</span>
<span class="line" id="L156"> <span class="tok-kw">var</span> chunks = chunk_writer.chunkWriter(writer, <span class="tok-str">&quot;IDAT&quot;</span>);</span>
<span class="line" id="L157"> <span class="tok-kw">const</span> chunk_wr = chunks.writer();</span>
<span class="line" id="L158"></span>
<span class="line" id="L159"> <span class="tok-kw">var</span> zlib: ZlibCompressor(<span class="tok-builtin">@TypeOf</span>(chunk_wr)) = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L160"> <span class="tok-kw">try</span> zlib.init(chunk_wr);</span>
<span class="line" id="L161"></span>
<span class="line" id="L162"> <span class="tok-kw">try</span> zlib.begin();</span>
<span class="line" id="L163"> <span class="tok-kw">try</span> filter.filter(zlib.writer(), pixels, filter_choice, header);</span>
<span class="line" id="L164"> <span class="tok-kw">try</span> zlib.end();</span>
<span class="line" id="L165"></span>
<span class="line" id="L166"> <span class="tok-kw">try</span> chunks.flush();</span>
<span class="line" id="L167"> }</span>
<span class="line" id="L168"></span>
<span class="line" id="L169"> <span class="tok-comment">// IEND chunk</span>
</span>
<span class="line" id="L170"> <span class="tok-kw">fn</span> <span class="tok-fn">writeTrailer</span>(writer: <span class="tok-kw">anytype</span>) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L171"> <span class="tok-kw">var</span> chunk = chunk_writer.chunkWriter(writer, <span class="tok-str">&quot;IEND&quot;</span>);</span>
<span class="line" id="L172"> <span class="tok-kw">try</span> chunk.flush();</span>
<span class="line" id="L173"> }</span>
<span class="line" id="L174"></span>
<span class="line" id="L175"> <span class="tok-comment">// PLTE (if indexed storage)</span>
</span>
<span class="line" id="L176"> <span class="tok-kw">fn</span> <span class="tok-fn">writePalette</span>(writer: <span class="tok-kw">anytype</span>, pixels: color.PixelStorage) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L177"> <span class="tok-kw">var</span> chunk = chunk_writer.chunkWriter(writer, <span class="tok-str">&quot;PLTE&quot;</span>);</span>
<span class="line" id="L178"> <span class="tok-kw">var</span> chunk_wr = chunk.writer();</span>
<span class="line" id="L179"></span>
<span class="line" id="L180"> <span class="tok-kw">const</span> palette = <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L181"> .indexed1 =&gt; |d| d.palette,</span>
<span class="line" id="L182"> .indexed2 =&gt; |d| d.palette,</span>
<span class="line" id="L183"> .indexed4 =&gt; |d| d.palette,</span>
<span class="line" id="L184"> .indexed8 =&gt; |d| d.palette,</span>
<span class="line" id="L185"> .indexed16 =&gt; <span class="tok-kw">return</span> ImageWriteError.Unsupported,</span>
<span class="line" id="L186"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L187"> };</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-kw">for</span> (palette) |col| {</span>
<span class="line" id="L190"> <span class="tok-kw">try</span> chunk_wr.writeByte(col.r);</span>
<span class="line" id="L191"> <span class="tok-kw">try</span> chunk_wr.writeByte(col.g);</span>
<span class="line" id="L192"> <span class="tok-kw">try</span> chunk_wr.writeByte(col.b);</span>
<span class="line" id="L193"> }</span>
<span class="line" id="L194"></span>
<span class="line" id="L195"> <span class="tok-kw">try</span> chunk.flush();</span>
<span class="line" id="L196"> }</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-comment">// tRNS (if indexed storage with transparency (there may be other uses later))</span>
</span>
<span class="line" id="L199"> <span class="tok-kw">fn</span> <span class="tok-fn">writeTransparencyInfo</span>(writer: <span class="tok-kw">anytype</span>, pixels: color.PixelStorage) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L200"> <span class="tok-kw">var</span> chunk = chunk_writer.chunkWriter(writer, <span class="tok-str">&quot;tRNS&quot;</span>);</span>
<span class="line" id="L201"> <span class="tok-kw">var</span> chunk_wr = chunk.writer();</span>
<span class="line" id="L202"></span>
<span class="line" id="L203"> <span class="tok-kw">const</span> palette = <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L204"> .indexed1 =&gt; |d| d.palette,</span>
<span class="line" id="L205"> .indexed2 =&gt; |d| d.palette,</span>
<span class="line" id="L206"> .indexed4 =&gt; |d| d.palette,</span>
<span class="line" id="L207"> .indexed8 =&gt; |d| d.palette,</span>
<span class="line" id="L208"> .indexed16 =&gt; <span class="tok-kw">return</span> ImageWriteError.Unsupported,</span>
<span class="line" id="L209"> <span class="tok-comment">// TODO: png support transparency info for other formats?</span>
</span>
<span class="line" id="L210"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L211"> };</span>
<span class="line" id="L212"></span>
<span class="line" id="L213"> <span class="tok-kw">for</span> (palette) |col| {</span>
<span class="line" id="L214"> <span class="tok-kw">try</span> chunk_wr.writeByte(col.a);</span>
<span class="line" id="L215"> }</span>
<span class="line" id="L216"></span>
<span class="line" id="L217"> <span class="tok-kw">try</span> chunk.flush();</span>
<span class="line" id="L218"> }</span>
<span class="line" id="L219">};</span>
<span class="line" id="L220"></span>
</code></pre></body>
</html>

View file

@ -1,182 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/png/chunk_writer.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">const</span> io = std.io;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> mem = std.mem;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> Crc = std.hash.crc.Crc32WithPoly(.IEEE);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-comment">/// Writer based on buffered writer that will write whole chunks of data of [buffer size]</span></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">ChunkWriter</span>(<span class="tok-kw">comptime</span> buffer_size: <span class="tok-type">usize</span>, <span class="tok-kw">comptime</span> WriterType: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L10"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L11"> unbuffered_writer: WriterType,</span>
<span class="line" id="L12"> buf: [buffer_size]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L13"> end: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L14"> section_id: [<span class="tok-number">4</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Error = WriterType.Error;</span>
<span class="line" id="L17"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Writer = io.Writer(*Self, Error, write);</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">flush</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L22"> <span class="tok-kw">try</span> self.unbuffered_writer.writeInt(<span class="tok-type">u32</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u32</span>, <span class="tok-builtin">@truncate</span>(self.end)), .big);</span>
<span class="line" id="L23"></span>
<span class="line" id="L24"> <span class="tok-kw">var</span> crc = Crc.init();</span>
<span class="line" id="L25"></span>
<span class="line" id="L26"> crc.update(&amp;self.section_id);</span>
<span class="line" id="L27"> <span class="tok-kw">try</span> self.unbuffered_writer.writeAll(&amp;self.section_id);</span>
<span class="line" id="L28"> crc.update(self.buf[<span class="tok-number">0</span>..self.end]);</span>
<span class="line" id="L29"> <span class="tok-kw">try</span> self.unbuffered_writer.writeAll(self.buf[<span class="tok-number">0</span>..self.end]);</span>
<span class="line" id="L30"></span>
<span class="line" id="L31"> <span class="tok-kw">try</span> self.unbuffered_writer.writeInt(<span class="tok-type">u32</span>, crc.final(), .big);</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"> self.end = <span class="tok-number">0</span>;</span>
<span class="line" id="L34"> }</span>
<span class="line" id="L35"></span>
<span class="line" id="L36"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writer</span>(self: *Self) Writer {</span>
<span class="line" id="L37"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L38"> }</span>
<span class="line" id="L39"></span>
<span class="line" id="L40"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Self, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) Error!<span class="tok-type">usize</span> {</span>
<span class="line" id="L41"> <span class="tok-kw">if</span> (self.end + bytes.len &gt; self.buf.len) {</span>
<span class="line" id="L42"> <span class="tok-kw">try</span> self.flush();</span>
<span class="line" id="L43"> <span class="tok-kw">if</span> (bytes.len &gt; self.buf.len)</span>
<span class="line" id="L44"> <span class="tok-kw">return</span> self.unbuffered_writer.write(bytes);</span>
<span class="line" id="L45"> }</span>
<span class="line" id="L46"></span>
<span class="line" id="L47"> <span class="tok-builtin">@memcpy</span>(self.buf[self.end..][<span class="tok-number">0</span>..bytes.len], bytes);</span>
<span class="line" id="L48"> self.end += bytes.len;</span>
<span class="line" id="L49"> <span class="tok-kw">return</span> bytes.len;</span>
<span class="line" id="L50"> }</span>
<span class="line" id="L51"> };</span>
<span class="line" id="L52">}</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"><span class="tok-kw">const</span> ChunkBufferSize = <span class="tok-number">1</span> &lt;&lt; <span class="tok-number">14</span>; <span class="tok-comment">// 16 kb</span>
</span>
<span class="line" id="L55"></span>
<span class="line" id="L56"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">chunkWriter</span>(underlying_stream: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> id: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) ChunkWriter(ChunkBufferSize, <span class="tok-builtin">@TypeOf</span>(underlying_stream)) {</span>
<span class="line" id="L57"> <span class="tok-kw">if</span> (id.len != <span class="tok-number">4</span>)</span>
<span class="line" id="L58"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;PNG chunk id must be 4 characters&quot;</span>);</span>
<span class="line" id="L59"></span>
<span class="line" id="L60"> <span class="tok-kw">return</span> .{ .unbuffered_writer = underlying_stream, .section_id = std.mem.bytesToValue([<span class="tok-number">4</span>]<span class="tok-type">u8</span>, id[<span class="tok-number">0</span>..<span class="tok-number">4</span>]) };</span>
<span class="line" id="L61">}</span>
<span class="line" id="L62"></span>
<span class="line" id="L63"><span class="tok-comment">// TODO: test idat writer</span>
</span>
<span class="line" id="L64"></span>
</code></pre></body>
</html>

View file

@ -1,320 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/png/filtering.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../color.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../Image.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> HeaderData = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;types.zig&quot;</span>).HeaderData;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> builtin = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;builtin&quot;</span>);</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterType = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L9"> none = <span class="tok-number">0</span>,</span>
<span class="line" id="L10"> sub = <span class="tok-number">1</span>,</span>
<span class="line" id="L11"> up = <span class="tok-number">2</span>,</span>
<span class="line" id="L12"> average = <span class="tok-number">3</span>,</span>
<span class="line" id="L13"> paeth = <span class="tok-number">4</span>,</span>
<span class="line" id="L14">};</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterChoiceStrategies = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L17"> try_all,</span>
<span class="line" id="L18"> heuristic,</span>
<span class="line" id="L19"> specified,</span>
<span class="line" id="L20">};</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterChoice = <span class="tok-kw">union</span>(FilterChoiceStrategies) {</span>
<span class="line" id="L23"> try_all,</span>
<span class="line" id="L24"> heuristic,</span>
<span class="line" id="L25"> specified: FilterType,</span>
<span class="line" id="L26">};</span>
<span class="line" id="L27"></span>
<span class="line" id="L28"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">filter</span>(writer: <span class="tok-kw">anytype</span>, pixels: color.PixelStorage, filter_choice: FilterChoice, header: HeaderData) Image.WriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L29"> <span class="tok-kw">var</span> scanline: color.PixelStorage = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L30"> <span class="tok-kw">var</span> previous_scanline: ?color.PixelStorage = <span class="tok-null">null</span>;</span>
<span class="line" id="L31"></span>
<span class="line" id="L32"> <span class="tok-kw">const</span> format: PixelFormat = pixels;</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"> <span class="tok-kw">if</span> (format.bitsPerChannel() &lt; <span class="tok-number">8</span>)</span>
<span class="line" id="L35"> <span class="tok-kw">return</span> Image.WriteError.Unsupported;</span>
<span class="line" id="L36"></span>
<span class="line" id="L37"> <span class="tok-kw">const</span> pixel_len = format.pixelStride();</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"> <span class="tok-kw">var</span> y: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L40"> <span class="tok-kw">while</span> (y &lt; header.height) : (y += <span class="tok-number">1</span>) {</span>
<span class="line" id="L41"> scanline = pixels.slice(y * header.width, (y + <span class="tok-number">1</span>) * header.width);</span>
<span class="line" id="L42"></span>
<span class="line" id="L43"> <span class="tok-kw">const</span> filter_type: FilterType = <span class="tok-kw">switch</span> (filter_choice) {</span>
<span class="line" id="L44"> .try_all =&gt; <span class="tok-builtin">@panic</span>(<span class="tok-str">&quot;Unimplemented&quot;</span>),</span>
<span class="line" id="L45"> .heuristic =&gt; filterChoiceHeuristic(scanline, previous_scanline),</span>
<span class="line" id="L46"> .specified =&gt; |f| f,</span>
<span class="line" id="L47"> };</span>
<span class="line" id="L48"></span>
<span class="line" id="L49"> writer.writeByte(<span class="tok-builtin">@intFromEnum</span>(filter_type)) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> Image.WriteError.InvalidData;</span>
<span class="line" id="L50"></span>
<span class="line" id="L51"> <span class="tok-kw">for</span> (<span class="tok-number">0</span>..scanline.asBytes().len) |byte_index| {</span>
<span class="line" id="L52"> <span class="tok-kw">const</span> i = <span class="tok-kw">if</span> (builtin.target.cpu.arch.endian() == .little) pixelByteSwappedIndex(scanline, byte_index) <span class="tok-kw">else</span> byte_index;</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-kw">const</span> sample = scanline.asBytes()[i];</span>
<span class="line" id="L55"> <span class="tok-kw">const</span> previous: <span class="tok-type">u8</span> = <span class="tok-kw">if</span> (byte_index &gt;= pixel_len) scanline.asBytes()[i - pixel_len] <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L56"> <span class="tok-kw">const</span> above: <span class="tok-type">u8</span> = <span class="tok-kw">if</span> (previous_scanline) |b| b.asBytes()[i] <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L57"> <span class="tok-kw">const</span> above_previous = <span class="tok-kw">if</span> (previous_scanline) |b| (<span class="tok-kw">if</span> (byte_index &gt;= pixel_len) b.asBytes()[i - pixel_len] <span class="tok-kw">else</span> <span class="tok-number">0</span>) <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L58"></span>
<span class="line" id="L59"> <span class="tok-kw">const</span> byte: <span class="tok-type">u8</span> = <span class="tok-kw">switch</span> (filter_type) {</span>
<span class="line" id="L60"> .none =&gt; sample,</span>
<span class="line" id="L61"> .sub =&gt; sample -% previous,</span>
<span class="line" id="L62"> .up =&gt; sample -% above,</span>
<span class="line" id="L63"> .average =&gt; sample -% average(previous, above),</span>
<span class="line" id="L64"> .paeth =&gt; sample -% paeth(previous, above, above_previous),</span>
<span class="line" id="L65"> };</span>
<span class="line" id="L66"></span>
<span class="line" id="L67"> writer.writeByte(byte) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> Image.WriteError.InvalidData;</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"> previous_scanline = scanline;</span>
<span class="line" id="L70"> }</span>
<span class="line" id="L71">}</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"><span class="tok-comment">// Map the index of a byte to what it would be if each struct element was byte swapped</span>
</span>
<span class="line" id="L74"><span class="tok-kw">fn</span> <span class="tok-fn">pixelByteSwappedIndex</span>(storage: color.PixelStorage, index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L75"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (storage) {</span>
<span class="line" id="L76"> .invalid =&gt; index,</span>
<span class="line" id="L77"> <span class="tok-kw">inline</span> .indexed1, .indexed2, .indexed4, .indexed8, .indexed16 =&gt; |data| byteSwappedIndex(<span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(data.indices)).Pointer.child, index),</span>
<span class="line" id="L78"> <span class="tok-kw">inline</span> <span class="tok-kw">else</span> =&gt; |data| byteSwappedIndex(<span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(data)).Pointer.child, index),</span>
<span class="line" id="L79"> };</span>
<span class="line" id="L80">}</span>
<span class="line" id="L81"></span>
<span class="line" id="L82"><span class="tok-comment">// Map the index of a byte to what it would be if each struct element was byte swapped</span>
</span>
<span class="line" id="L83"><span class="tok-kw">fn</span> <span class="tok-fn">byteSwappedIndex</span>(<span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, byte_index: <span class="tok-type">usize</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L84"> <span class="tok-kw">const</span> element_index = byte_index / <span class="tok-builtin">@sizeOf</span>(T);</span>
<span class="line" id="L85"> <span class="tok-kw">const</span> element_offset = element_index * <span class="tok-builtin">@sizeOf</span>(T);</span>
<span class="line" id="L86"> <span class="tok-kw">const</span> index = byte_index % <span class="tok-builtin">@sizeOf</span>(T);</span>
<span class="line" id="L87"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(T)) {</span>
<span class="line" id="L88"> .Int =&gt; {</span>
<span class="line" id="L89"> <span class="tok-kw">if</span> (<span class="tok-builtin">@sizeOf</span>(T) == <span class="tok-number">1</span>) <span class="tok-kw">return</span> byte_index;</span>
<span class="line" id="L90"> <span class="tok-kw">return</span> element_offset + <span class="tok-builtin">@sizeOf</span>(T) - <span class="tok-number">1</span> - index;</span>
<span class="line" id="L91"> },</span>
<span class="line" id="L92"> .Struct =&gt; |info| {</span>
<span class="line" id="L93"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (info.fields) |field| {</span>
<span class="line" id="L94"> <span class="tok-kw">if</span> (index &gt;= <span class="tok-builtin">@offsetOf</span>(T, field.name) <span class="tok-kw">or</span> index &lt;= <span class="tok-builtin">@offsetOf</span>(T, field.name) + <span class="tok-builtin">@sizeOf</span>(field.<span class="tok-type">type</span>)) {</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (<span class="tok-builtin">@sizeOf</span>(field.<span class="tok-type">type</span>) == <span class="tok-number">1</span>) <span class="tok-kw">return</span> byte_index;</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> element_offset + <span class="tok-builtin">@sizeOf</span>(field.<span class="tok-type">type</span>) - <span class="tok-number">1</span> - index;</span>
<span class="line" id="L97"> }</span>
<span class="line" id="L98"> }</span>
<span class="line" id="L99"> },</span>
<span class="line" id="L100"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot; not supported&quot;</span>),</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102">}</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"><span class="tok-kw">fn</span> <span class="tok-fn">filterChoiceHeuristic</span>(scanline: color.PixelStorage, previous_scanline: ?color.PixelStorage) FilterType {</span>
<span class="line" id="L105"> <span class="tok-kw">const</span> pixel_len = <span class="tok-builtin">@as</span>(PixelFormat, scanline).pixelStride();</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"> <span class="tok-kw">const</span> filter_types = [_]FilterType{ .none, .sub, .up, .average, .paeth };</span>
<span class="line" id="L108"></span>
<span class="line" id="L109"> <span class="tok-kw">var</span> previous_bytes: [filter_types.len]<span class="tok-type">u8</span> = [_]<span class="tok-type">u8</span>{<span class="tok-number">0</span>} ** filter_types.len;</span>
<span class="line" id="L110"> <span class="tok-kw">var</span> combos: [filter_types.len]<span class="tok-type">usize</span> = [_]<span class="tok-type">usize</span>{<span class="tok-number">0</span>} ** filter_types.len;</span>
<span class="line" id="L111"> <span class="tok-kw">var</span> scores: [filter_types.len]<span class="tok-type">usize</span> = [_]<span class="tok-type">usize</span>{<span class="tok-number">0</span>} ** filter_types.len;</span>
<span class="line" id="L112"></span>
<span class="line" id="L113"> <span class="tok-kw">for</span> (scanline.asBytes(), <span class="tok-number">0</span>..) |sample, i| {</span>
<span class="line" id="L114"> <span class="tok-kw">const</span> previous: <span class="tok-type">u8</span> = <span class="tok-kw">if</span> (i &gt;= pixel_len) scanline.asBytes()[i - pixel_len] <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L115"> <span class="tok-kw">const</span> above: <span class="tok-type">u8</span> = <span class="tok-kw">if</span> (previous_scanline) |b| b.asBytes()[i] <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L116"> <span class="tok-kw">const</span> above_previous = <span class="tok-kw">if</span> (previous_scanline) |b| (<span class="tok-kw">if</span> (i &gt;= pixel_len) b.asBytes()[i - pixel_len] <span class="tok-kw">else</span> <span class="tok-number">0</span>) <span class="tok-kw">else</span> <span class="tok-number">0</span>;</span>
<span class="line" id="L117"></span>
<span class="line" id="L118"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (filter_types, &amp;previous_bytes, &amp;combos, &amp;scores) |filter_type, *previous_byte, *combo, *score| {</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> byte: <span class="tok-type">u8</span> = <span class="tok-kw">switch</span> (filter_type) {</span>
<span class="line" id="L120"> .none =&gt; sample,</span>
<span class="line" id="L121"> .sub =&gt; sample -% previous,</span>
<span class="line" id="L122"> .up =&gt; sample -% above,</span>
<span class="line" id="L123"> .average =&gt; sample -% average(previous, above),</span>
<span class="line" id="L124"> .paeth =&gt; sample -% paeth(previous, above, above_previous),</span>
<span class="line" id="L125"> };</span>
<span class="line" id="L126"></span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (byte == previous_byte.*) {</span>
<span class="line" id="L128"> combo.* += <span class="tok-number">1</span>;</span>
<span class="line" id="L129"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L130"> score.* += combo.* * combo.*;</span>
<span class="line" id="L131"> combo.* = <span class="tok-number">0</span>;</span>
<span class="line" id="L132"> previous_byte.* = byte;</span>
<span class="line" id="L133"> }</span>
<span class="line" id="L134"> }</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-kw">var</span> best: FilterType = .none;</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> max_score: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L139"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (filter_types, scores) |filter_type, score| {</span>
<span class="line" id="L140"> <span class="tok-kw">if</span> (score &gt; max_score) {</span>
<span class="line" id="L141"> max_score = score;</span>
<span class="line" id="L142"> best = filter_type;</span>
<span class="line" id="L143"> }</span>
<span class="line" id="L144"> }</span>
<span class="line" id="L145"> <span class="tok-kw">return</span> best;</span>
<span class="line" id="L146">}</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"><span class="tok-kw">fn</span> <span class="tok-fn">average</span>(a: <span class="tok-type">u9</span>, b: <span class="tok-type">u9</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L149"> <span class="tok-kw">return</span> <span class="tok-builtin">@truncate</span>((a + b) / <span class="tok-number">2</span>);</span>
<span class="line" id="L150">}</span>
<span class="line" id="L151"></span>
<span class="line" id="L152"><span class="tok-kw">fn</span> <span class="tok-fn">paeth</span>(b4: <span class="tok-type">u8</span>, up: <span class="tok-type">u8</span>, b4_up: <span class="tok-type">u8</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L153"> <span class="tok-kw">const</span> p: <span class="tok-type">i16</span> = <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, <span class="tok-builtin">@intCast</span>(b4)) + up - b4_up;</span>
<span class="line" id="L154"> <span class="tok-kw">const</span> pa = <span class="tok-builtin">@abs</span>(p - b4);</span>
<span class="line" id="L155"> <span class="tok-kw">const</span> pb = <span class="tok-builtin">@abs</span>(p - up);</span>
<span class="line" id="L156"> <span class="tok-kw">const</span> pc = <span class="tok-builtin">@abs</span>(p - b4_up);</span>
<span class="line" id="L157"></span>
<span class="line" id="L158"> <span class="tok-kw">if</span> (pa &lt;= pb <span class="tok-kw">and</span> pa &lt;= pc) {</span>
<span class="line" id="L159"> <span class="tok-kw">return</span> b4;</span>
<span class="line" id="L160"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (pb &lt;= pc) {</span>
<span class="line" id="L161"> <span class="tok-kw">return</span> up;</span>
<span class="line" id="L162"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L163"> <span class="tok-kw">return</span> b4_up;</span>
<span class="line" id="L164"> }</span>
<span class="line" id="L165">}</span>
<span class="line" id="L166"></span>
<span class="line" id="L167"><span class="tok-kw">test</span> <span class="tok-str">&quot;filtering 16-bit grayscale pixels uses correct endianess&quot;</span> {</span>
<span class="line" id="L168"> <span class="tok-kw">var</span> output_bytes = std.ArrayList(<span class="tok-type">u8</span>).init(std.testing.allocator);</span>
<span class="line" id="L169"> <span class="tok-kw">defer</span> output_bytes.deinit();</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-kw">const</span> pixels = <span class="tok-kw">try</span> std.testing.allocator.dupe(color.Grayscale16, &amp;.{</span>
<span class="line" id="L172"> .{ .value = <span class="tok-number">0xF</span> },</span>
<span class="line" id="L173"> .{ .value = <span class="tok-number">0xFF</span> },</span>
<span class="line" id="L174"> .{ .value = <span class="tok-number">0xFFF</span> },</span>
<span class="line" id="L175"> .{ .value = <span class="tok-number">0xFFFF</span> },</span>
<span class="line" id="L176"> .{ .value = <span class="tok-number">0xF</span> },</span>
<span class="line" id="L177"> .{ .value = <span class="tok-number">0xFF</span> },</span>
<span class="line" id="L178"> .{ .value = <span class="tok-number">0xFFF</span> },</span>
<span class="line" id="L179"> .{ .value = <span class="tok-number">0xFFFF</span> },</span>
<span class="line" id="L180"> });</span>
<span class="line" id="L181"> <span class="tok-kw">defer</span> std.testing.allocator.free(pixels);</span>
<span class="line" id="L182"></span>
<span class="line" id="L183"> <span class="tok-comment">// We specify the endianess as none to simplify the test</span>
</span>
<span class="line" id="L184"> <span class="tok-kw">try</span> filter(output_bytes.writer(), .{ .grayscale16 = pixels }, .{ .specified = .none }, .{</span>
<span class="line" id="L185"> .width = <span class="tok-number">4</span>,</span>
<span class="line" id="L186"> .height = <span class="tok-number">2</span>,</span>
<span class="line" id="L187"> .bit_depth = <span class="tok-number">16</span>,</span>
<span class="line" id="L188"> .color_type = .grayscale,</span>
<span class="line" id="L189"> .compression_method = .deflate,</span>
<span class="line" id="L190"> .filter_method = .adaptive,</span>
<span class="line" id="L191"> .interlace_method = .none,</span>
<span class="line" id="L192"> });</span>
<span class="line" id="L193"></span>
<span class="line" id="L194"> <span class="tok-kw">try</span> std.testing.expectEqualSlices(<span class="tok-type">u8</span>, &amp;.{</span>
<span class="line" id="L195"> <span class="tok-number">0x00</span>, <span class="tok-number">0x00</span>, <span class="tok-number">0x0F</span>, <span class="tok-number">0x00</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0x0F</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0xFF</span>, <span class="tok-comment">//</span>
</span>
<span class="line" id="L196"> <span class="tok-number">0x00</span>, <span class="tok-number">0x00</span>, <span class="tok-number">0x0F</span>, <span class="tok-number">0x00</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0x0F</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0xFF</span>, <span class="tok-number">0xFF</span>, <span class="tok-comment">//</span>
</span>
<span class="line" id="L197"> }, output_bytes.items);</span>
<span class="line" id="L198">}</span>
<span class="line" id="L199"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,310 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/png/types.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../utils.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../color.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L5"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L6"><span class="tok-kw">const</span> Colorf32 = color.Colorf32;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> magic_header = <span class="tok-str">&quot;\x89PNG\x0D\x0A\x1A\x0A&quot;</span>;</span>
<span class="line" id="L9"></span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Chunk = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L11"> id: <span class="tok-type">u32</span>,</span>
<span class="line" id="L12"> name: *<span class="tok-kw">const</span> [<span class="tok-number">4</span>:<span class="tok-number">0</span>]<span class="tok-type">u8</span>,</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(name: *<span class="tok-kw">const</span> [<span class="tok-number">4</span>:<span class="tok-number">0</span>]<span class="tok-type">u8</span>) Chunk {</span>
<span class="line" id="L15"> <span class="tok-kw">return</span> .{ .name = name, .id = std.mem.bigToNative(<span class="tok-type">u32</span>, std.mem.bytesToValue(<span class="tok-type">u32</span>, name)) };</span>
<span class="line" id="L16"> }</span>
<span class="line" id="L17">};</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Chunks = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L20"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> IHDR = Chunk.init(<span class="tok-str">&quot;IHDR&quot;</span>);</span>
<span class="line" id="L21"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> PLTE = Chunk.init(<span class="tok-str">&quot;PLTE&quot;</span>);</span>
<span class="line" id="L22"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> IDAT = Chunk.init(<span class="tok-str">&quot;IDAT&quot;</span>);</span>
<span class="line" id="L23"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> IEND = Chunk.init(<span class="tok-str">&quot;IEND&quot;</span>);</span>
<span class="line" id="L24"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> gAMA = Chunk.init(<span class="tok-str">&quot;gAMA&quot;</span>);</span>
<span class="line" id="L25"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> sBIT = Chunk.init(<span class="tok-str">&quot;sBIT&quot;</span>);</span>
<span class="line" id="L26"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> tEXt = Chunk.init(<span class="tok-str">&quot;tEXt&quot;</span>);</span>
<span class="line" id="L27"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> zTXt = Chunk.init(<span class="tok-str">&quot;zTXt&quot;</span>);</span>
<span class="line" id="L28"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> iTXt = Chunk.init(<span class="tok-str">&quot;iTXt&quot;</span>);</span>
<span class="line" id="L29"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> cHRM = Chunk.init(<span class="tok-str">&quot;cHRM&quot;</span>);</span>
<span class="line" id="L30"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> pHYs = Chunk.init(<span class="tok-str">&quot;pHYs&quot;</span>);</span>
<span class="line" id="L31"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> tRNS = Chunk.init(<span class="tok-str">&quot;tRNS&quot;</span>);</span>
<span class="line" id="L32"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> bKGD = Chunk.init(<span class="tok-str">&quot;bKGD&quot;</span>);</span>
<span class="line" id="L33"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> tIME = Chunk.init(<span class="tok-str">&quot;tIME&quot;</span>);</span>
<span class="line" id="L34"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> iCCP = Chunk.init(<span class="tok-str">&quot;iCCP&quot;</span>);</span>
<span class="line" id="L35"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> sRGB = Chunk.init(<span class="tok-str">&quot;sRGB&quot;</span>);</span>
<span class="line" id="L36"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Any = Chunk.init(<span class="tok-str">&quot;_ANY&quot;</span>);</span>
<span class="line" id="L37">};</span>
<span class="line" id="L38"></span>
<span class="line" id="L39"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ColorType = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L40"> grayscale = <span class="tok-number">0</span>,</span>
<span class="line" id="L41"> rgb_color = <span class="tok-number">2</span>,</span>
<span class="line" id="L42"> indexed = <span class="tok-number">3</span>,</span>
<span class="line" id="L43"> grayscale_alpha = <span class="tok-number">4</span>,</span>
<span class="line" id="L44"> rgba_color = <span class="tok-number">6</span>,</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">channelCount</span>(self: Self) <span class="tok-type">u8</span> {</span>
<span class="line" id="L49"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L50"> .grayscale =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L51"> .rgb_color =&gt; <span class="tok-number">3</span>,</span>
<span class="line" id="L52"> .indexed =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L53"> .grayscale_alpha =&gt; <span class="tok-number">2</span>,</span>
<span class="line" id="L54"> .rgba_color =&gt; <span class="tok-number">4</span>,</span>
<span class="line" id="L55"> };</span>
<span class="line" id="L56"> }</span>
<span class="line" id="L57"></span>
<span class="line" id="L58"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">fromPixelFormat</span>(pixel_format: PixelFormat) !Self {</span>
<span class="line" id="L59"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (pixel_format) {</span>
<span class="line" id="L60"> .rgb24, .rgb48 =&gt; .rgb_color,</span>
<span class="line" id="L61"></span>
<span class="line" id="L62"> .rgba32, .rgba64 =&gt; .rgba_color,</span>
<span class="line" id="L63"></span>
<span class="line" id="L64"> .grayscale1, .grayscale2, .grayscale4, .grayscale8, .grayscale16 =&gt; .grayscale,</span>
<span class="line" id="L65"></span>
<span class="line" id="L66"> .grayscale8Alpha, .grayscale16Alpha =&gt; .grayscale_alpha,</span>
<span class="line" id="L67"></span>
<span class="line" id="L68"> .indexed1, .indexed2, .indexed4, .indexed8 =&gt; .indexed,</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> <span class="tok-kw">error</span>.Unsupported,</span>
<span class="line" id="L71"> };</span>
<span class="line" id="L72"> }</span>
<span class="line" id="L73">};</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterType = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L76"> none = <span class="tok-number">0</span>,</span>
<span class="line" id="L77"> sub = <span class="tok-number">1</span>,</span>
<span class="line" id="L78"> up = <span class="tok-number">2</span>,</span>
<span class="line" id="L79"> average = <span class="tok-number">3</span>,</span>
<span class="line" id="L80"> paeth = <span class="tok-number">4</span>,</span>
<span class="line" id="L81">};</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> InterlaceMethod = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L84"> none = <span class="tok-number">0</span>,</span>
<span class="line" id="L85"> adam7 = <span class="tok-number">1</span>,</span>
<span class="line" id="L86">};</span>
<span class="line" id="L87"></span>
<span class="line" id="L88"><span class="tok-comment">/// The compression methods supported by PNG</span></span>
<span class="line" id="L89"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> CompressionMethod = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) { deflate = <span class="tok-number">0</span>, _ };</span>
<span class="line" id="L90"></span>
<span class="line" id="L91"><span class="tok-comment">/// The filter methods supported by PNG</span></span>
<span class="line" id="L92"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FilterMethod = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) { adaptive = <span class="tok-number">0</span>, _ };</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> ChunkHeader = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L95"> length: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L96"> <span class="tok-type">type</span>: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L97"></span>
<span class="line" id="L98"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L99"></span>
<span class="line" id="L100"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">name</span>(self: *Self) []<span class="tok-kw">const</span> <span class="tok-type">u8</span> {</span>
<span class="line" id="L101"> <span class="tok-kw">return</span> std.mem.asBytes(&amp;self.<span class="tok-type">type</span>);</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103">};</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> HeaderData = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L106"> width: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L107"> height: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L108"> bit_depth: <span class="tok-type">u8</span>,</span>
<span class="line" id="L109"> color_type: ColorType,</span>
<span class="line" id="L110"> compression_method: CompressionMethod,</span>
<span class="line" id="L111"> filter_method: FilterMethod,</span>
<span class="line" id="L112"> interlace_method: InterlaceMethod,</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isValid</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L117"> <span class="tok-kw">const</span> max_dim = std.math.maxInt(<span class="tok-type">u32</span>) &gt;&gt; <span class="tok-number">1</span>;</span>
<span class="line" id="L118"> <span class="tok-kw">const</span> w = self.width;</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> h = self.height;</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (w == <span class="tok-number">0</span> <span class="tok-kw">or</span> w &gt; max_dim) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L121"> <span class="tok-kw">if</span> (h == <span class="tok-number">0</span> <span class="tok-kw">or</span> h &gt; max_dim) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L122"></span>
<span class="line" id="L123"> <span class="tok-kw">const</span> bd = self.bit_depth;</span>
<span class="line" id="L124"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.color_type) {</span>
<span class="line" id="L125"> .grayscale =&gt; bd == <span class="tok-number">1</span> <span class="tok-kw">or</span> bd == <span class="tok-number">2</span> <span class="tok-kw">or</span> bd == <span class="tok-number">4</span> <span class="tok-kw">or</span> bd == <span class="tok-number">8</span> <span class="tok-kw">or</span> bd == <span class="tok-number">16</span>,</span>
<span class="line" id="L126"> .indexed =&gt; bd == <span class="tok-number">1</span> <span class="tok-kw">or</span> bd == <span class="tok-number">2</span> <span class="tok-kw">or</span> bd == <span class="tok-number">4</span> <span class="tok-kw">or</span> bd == <span class="tok-number">8</span>,</span>
<span class="line" id="L127"> <span class="tok-kw">else</span> =&gt; bd == <span class="tok-number">8</span> <span class="tok-kw">or</span> bd == <span class="tok-number">16</span>,</span>
<span class="line" id="L128"> };</span>
<span class="line" id="L129"> }</span>
<span class="line" id="L130"></span>
<span class="line" id="L131"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">allowsPalette</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L132"> <span class="tok-kw">return</span> self.color_type == .indexed <span class="tok-kw">or</span></span>
<span class="line" id="L133"> self.color_type == .rgb_color <span class="tok-kw">or</span></span>
<span class="line" id="L134"> self.color_type == .rgba_color;</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">maxPaletteSize</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">u16</span> {</span>
<span class="line" id="L138"> <span class="tok-kw">return</span> <span class="tok-kw">if</span> (self.bit_depth &gt; <span class="tok-number">8</span>) <span class="tok-number">256</span> <span class="tok-kw">else</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u16</span>, <span class="tok-number">1</span>) &lt;&lt; <span class="tok-builtin">@truncate</span>(self.bit_depth);</span>
<span class="line" id="L139"> }</span>
<span class="line" id="L140"></span>
<span class="line" id="L141"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">channelCount</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">u8</span> {</span>
<span class="line" id="L142"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.color_type) {</span>
<span class="line" id="L143"> .grayscale =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L144"> .rgb_color =&gt; <span class="tok-number">3</span>,</span>
<span class="line" id="L145"> .indexed =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L146"> .grayscale_alpha =&gt; <span class="tok-number">2</span>,</span>
<span class="line" id="L147"> .rgba_color =&gt; <span class="tok-number">4</span>,</span>
<span class="line" id="L148"> };</span>
<span class="line" id="L149"> }</span>
<span class="line" id="L150"></span>
<span class="line" id="L151"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelBits</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">u8</span> {</span>
<span class="line" id="L152"> <span class="tok-kw">return</span> self.bit_depth * self.channelCount();</span>
<span class="line" id="L153"> }</span>
<span class="line" id="L154"></span>
<span class="line" id="L155"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">lineBytes</span>(self: *<span class="tok-kw">const</span> Self) <span class="tok-type">u32</span> {</span>
<span class="line" id="L156"> <span class="tok-kw">return</span> (self.pixelBits() * self.width + <span class="tok-number">7</span>) / <span class="tok-number">8</span>;</span>
<span class="line" id="L157"> }</span>
<span class="line" id="L158"></span>
<span class="line" id="L159"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getPixelFormat</span>(self: *<span class="tok-kw">const</span> Self) PixelFormat {</span>
<span class="line" id="L160"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.color_type) {</span>
<span class="line" id="L161"> .grayscale =&gt; <span class="tok-kw">switch</span> (self.bit_depth) {</span>
<span class="line" id="L162"> <span class="tok-number">1</span> =&gt; PixelFormat.grayscale1,</span>
<span class="line" id="L163"> <span class="tok-number">2</span> =&gt; PixelFormat.grayscale2,</span>
<span class="line" id="L164"> <span class="tok-number">4</span> =&gt; PixelFormat.grayscale4,</span>
<span class="line" id="L165"> <span class="tok-number">8</span> =&gt; PixelFormat.grayscale8,</span>
<span class="line" id="L166"> <span class="tok-number">16</span> =&gt; PixelFormat.grayscale16,</span>
<span class="line" id="L167"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L168"> },</span>
<span class="line" id="L169"> .rgb_color =&gt; <span class="tok-kw">switch</span> (self.bit_depth) {</span>
<span class="line" id="L170"> <span class="tok-number">8</span> =&gt; PixelFormat.rgb24,</span>
<span class="line" id="L171"> <span class="tok-number">16</span> =&gt; PixelFormat.rgb48,</span>
<span class="line" id="L172"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L173"> },</span>
<span class="line" id="L174"> .indexed =&gt; <span class="tok-kw">switch</span> (self.bit_depth) {</span>
<span class="line" id="L175"> <span class="tok-number">1</span> =&gt; PixelFormat.indexed1,</span>
<span class="line" id="L176"> <span class="tok-number">2</span> =&gt; PixelFormat.indexed2,</span>
<span class="line" id="L177"> <span class="tok-number">4</span> =&gt; PixelFormat.indexed4,</span>
<span class="line" id="L178"> <span class="tok-number">8</span> =&gt; PixelFormat.indexed8,</span>
<span class="line" id="L179"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L180"> },</span>
<span class="line" id="L181"> .grayscale_alpha =&gt; <span class="tok-kw">switch</span> (self.bit_depth) {</span>
<span class="line" id="L182"> <span class="tok-number">8</span> =&gt; PixelFormat.grayscale8Alpha,</span>
<span class="line" id="L183"> <span class="tok-number">16</span> =&gt; PixelFormat.grayscale16Alpha,</span>
<span class="line" id="L184"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L185"> },</span>
<span class="line" id="L186"> .rgba_color =&gt; <span class="tok-kw">switch</span> (self.bit_depth) {</span>
<span class="line" id="L187"> <span class="tok-number">8</span> =&gt; PixelFormat.rgba32,</span>
<span class="line" id="L188"> <span class="tok-number">16</span> =&gt; PixelFormat.rgba64,</span>
<span class="line" id="L189"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">unreachable</span>,</span>
<span class="line" id="L190"> },</span>
<span class="line" id="L191"> };</span>
<span class="line" id="L192"> }</span>
<span class="line" id="L193">};</span>
<span class="line" id="L194"></span>
</code></pre></body>
</html>

View file

@ -1,185 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/png/zlib_compressor.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> io = std.io;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> deflate = std.compress.flate;</span>
<span class="line" id="L4"></span>
<span class="line" id="L5"><span class="tok-comment">/// Zlib Compressor (Deflate) with a writer interface</span></span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">ZlibCompressor</span>(<span class="tok-kw">comptime</span> WriterType: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L7"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L8"> raw_writer: WriterType,</span>
<span class="line" id="L9"> compressor: deflate.Compressor(WriterType),</span>
<span class="line" id="L10"> adler: std.hash.Adler32,</span>
<span class="line" id="L11"></span>
<span class="line" id="L12"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"> <span class="tok-comment">// TODO: find why doing it an other way segfaults</span>
</span>
<span class="line" id="L15"> <span class="tok-comment">/// Inits a zlibcompressor</span></span>
<span class="line" id="L16"> <span class="tok-comment">/// This is made this way because not doing it in place segfaults for a reason</span></span>
<span class="line" id="L17"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(self: *Self, stream: WriterType) !<span class="tok-type">void</span> {</span>
<span class="line" id="L18"> self.raw_writer = stream;</span>
<span class="line" id="L19"> self.compressor = <span class="tok-kw">try</span> deflate.compressor(self.raw_writer, .{});</span>
<span class="line" id="L20"> self.adler = std.hash.Adler32.init();</span>
<span class="line" id="L21"> }</span>
<span class="line" id="L22"></span>
<span class="line" id="L23"> <span class="tok-comment">/// Begins a zlib block with the header</span></span>
<span class="line" id="L24"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">begin</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L25"> <span class="tok-comment">// TODO: customize</span>
</span>
<span class="line" id="L26"> <span class="tok-kw">const</span> compression_method = <span class="tok-number">0x78</span>; <span class="tok-comment">// 8 = deflate, 7 = log(window size (see std.compress.deflate)) - 8</span>
</span>
<span class="line" id="L27"> <span class="tok-kw">const</span> compression_flags = blk: {</span>
<span class="line" id="L28"> <span class="tok-kw">var</span> ret: <span class="tok-type">u8</span> = <span class="tok-number">0b10000000</span>; <span class="tok-comment">// 11 = max compression</span>
</span>
<span class="line" id="L29"> <span class="tok-kw">const</span> rem: <span class="tok-type">u8</span> = <span class="tok-builtin">@truncate</span>(((<span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@intCast</span>(compression_method)) &lt;&lt; <span class="tok-number">8</span>) + ret) % <span class="tok-number">31</span>);</span>
<span class="line" id="L30"> ret += <span class="tok-number">31</span> - <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@truncate</span>(rem));</span>
<span class="line" id="L31"> <span class="tok-kw">break</span> :blk ret;</span>
<span class="line" id="L32"> };</span>
<span class="line" id="L33"></span>
<span class="line" id="L34"> <span class="tok-comment">//std.debug.assert(((@intCast(usize, cmf) &lt;&lt; 8) + flg) % 31 == 0);</span>
</span>
<span class="line" id="L35"> <span class="tok-comment">// write the header</span>
</span>
<span class="line" id="L36"> <span class="tok-kw">var</span> wr = self.raw_writer;</span>
<span class="line" id="L37"> <span class="tok-kw">try</span> wr.writeByte(compression_method);</span>
<span class="line" id="L38"> <span class="tok-kw">try</span> wr.writeByte(compression_flags);</span>
<span class="line" id="L39"> }</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Error = deflate.Compressor(WriterType).Error;</span>
<span class="line" id="L42"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> Writer = std.io.Writer(*Self, Error, write);</span>
<span class="line" id="L43"></span>
<span class="line" id="L44"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writer</span>(self: *Self) Writer {</span>
<span class="line" id="L45"> <span class="tok-kw">return</span> .{ .context = self };</span>
<span class="line" id="L46"> }</span>
<span class="line" id="L47"></span>
<span class="line" id="L48"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: *Self, bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) Error!<span class="tok-type">usize</span> {</span>
<span class="line" id="L49"> <span class="tok-kw">const</span> amount = <span class="tok-kw">try</span> self.compressor.writer().write(bytes);</span>
<span class="line" id="L50"> self.adler.update(bytes[<span class="tok-number">0</span>..amount]);</span>
<span class="line" id="L51"> <span class="tok-kw">return</span> amount;</span>
<span class="line" id="L52"> }</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-comment">/// Ends a zlib block with the checksum</span></span>
<span class="line" id="L55"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">end</span>(self: *Self) !<span class="tok-type">void</span> {</span>
<span class="line" id="L56"> <span class="tok-comment">// Write the checksum</span>
</span>
<span class="line" id="L57"> <span class="tok-kw">try</span> self.compressor.finish();</span>
<span class="line" id="L58"> <span class="tok-kw">try</span> self.raw_writer.writeInt(<span class="tok-type">u32</span>, self.adler.final(), .big);</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60"> };</span>
<span class="line" id="L61">}</span>
<span class="line" id="L62"></span>
</code></pre></body>
</html>

View file

@ -1,568 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/formats/qoi.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Adapted from https://github.com/MasterQ32/zig-qoi</span>
</span>
<span class="line" id="L2"><span class="tok-comment">// with permission from Felix Queißner</span>
</span>
<span class="line" id="L3"><span class="tok-kw">const</span> Allocator = std.mem.Allocator;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> buffered_stream_source = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../buffered_stream_source.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../color.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">const</span> fs = std.fs;</span>
<span class="line" id="L8"><span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../Image.zig&quot;</span>);</span>
<span class="line" id="L9"><span class="tok-kw">const</span> ImageError = Image.Error;</span>
<span class="line" id="L10"><span class="tok-kw">const</span> ImageReadError = Image.ReadError;</span>
<span class="line" id="L11"><span class="tok-kw">const</span> ImageWriteError = Image.WriteError;</span>
<span class="line" id="L12"><span class="tok-kw">const</span> io = std.io;</span>
<span class="line" id="L13"><span class="tok-kw">const</span> mem = std.mem;</span>
<span class="line" id="L14"><span class="tok-kw">const</span> path = std.fs.path;</span>
<span class="line" id="L15"><span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L16"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L17"><span class="tok-kw">const</span> utils = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;../utils.zig&quot;</span>);</span>
<span class="line" id="L18"></span>
<span class="line" id="L19"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> QoiColor = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L20"> r: <span class="tok-type">u8</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L21"> g: <span class="tok-type">u8</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L22"> b: <span class="tok-type">u8</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L23"> a: <span class="tok-type">u8</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>) = <span class="tok-number">0xFF</span>,</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"> <span class="tok-kw">fn</span> <span class="tok-fn">hash</span>(c: QoiColor) <span class="tok-type">u6</span> {</span>
<span class="line" id="L26"> <span class="tok-kw">return</span> <span class="tok-builtin">@truncate</span>(c.r *% <span class="tok-number">3</span> +% c.g *% <span class="tok-number">5</span> +% c.b *% <span class="tok-number">7</span> +% c.a *% <span class="tok-number">11</span>);</span>
<span class="line" id="L27"> }</span>
<span class="line" id="L28"></span>
<span class="line" id="L29"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">eql</span>(a: QoiColor, b: QoiColor) <span class="tok-type">bool</span> {</span>
<span class="line" id="L30"> <span class="tok-kw">return</span> std.meta.eql(a, b);</span>
<span class="line" id="L31"> }</span>
<span class="line" id="L32"></span>
<span class="line" id="L33"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toRgb24</span>(self: QoiColor) color.Rgb24 {</span>
<span class="line" id="L34"> <span class="tok-kw">return</span> color.Rgb24{</span>
<span class="line" id="L35"> .r = self.r,</span>
<span class="line" id="L36"> .g = self.g,</span>
<span class="line" id="L37"> .b = self.b,</span>
<span class="line" id="L38"> };</span>
<span class="line" id="L39"> }</span>
<span class="line" id="L40"></span>
<span class="line" id="L41"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toRgba32</span>(self: QoiColor) color.Rgba32 {</span>
<span class="line" id="L42"> <span class="tok-kw">return</span> color.Rgba32{</span>
<span class="line" id="L43"> .r = self.r,</span>
<span class="line" id="L44"> .g = self.g,</span>
<span class="line" id="L45"> .b = self.b,</span>
<span class="line" id="L46"> .a = self.a,</span>
<span class="line" id="L47"> };</span>
<span class="line" id="L48"> }</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">from</span>(pixel: <span class="tok-kw">anytype</span>) QoiColor {</span>
<span class="line" id="L51"> <span class="tok-kw">if</span> (<span class="tok-builtin">@TypeOf</span>(pixel) == color.Rgb24) {</span>
<span class="line" id="L52"> <span class="tok-kw">return</span> QoiColor{</span>
<span class="line" id="L53"> .r = pixel.r,</span>
<span class="line" id="L54"> .g = pixel.g,</span>
<span class="line" id="L55"> .b = pixel.b,</span>
<span class="line" id="L56"> };</span>
<span class="line" id="L57"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (<span class="tok-builtin">@TypeOf</span>(pixel) == color.Rgba32) {</span>
<span class="line" id="L58"> <span class="tok-kw">return</span> QoiColor{</span>
<span class="line" id="L59"> .r = pixel.r,</span>
<span class="line" id="L60"> .g = pixel.g,</span>
<span class="line" id="L61"> .b = pixel.b,</span>
<span class="line" id="L62"> .a = pixel.a,</span>
<span class="line" id="L63"> };</span>
<span class="line" id="L64"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L65"> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L66"> }</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68">};</span>
<span class="line" id="L69"></span>
<span class="line" id="L70"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Colorspace = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L71"> <span class="tok-comment">/// sRGB color, linear alpha</span></span>
<span class="line" id="L72"> srgb = <span class="tok-number">0</span>,</span>
<span class="line" id="L73"></span>
<span class="line" id="L74"> <span class="tok-comment">/// Every channel is linear</span></span>
<span class="line" id="L75"> linear = <span class="tok-number">1</span>,</span>
<span class="line" id="L76">};</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Format = <span class="tok-kw">enum</span>(<span class="tok-type">u8</span>) {</span>
<span class="line" id="L79"> rgb = <span class="tok-number">3</span>,</span>
<span class="line" id="L80"> rgba = <span class="tok-number">4</span>,</span>
<span class="line" id="L81">};</span>
<span class="line" id="L82"></span>
<span class="line" id="L83"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Header = <span class="tok-kw">extern</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L84"> <span class="tok-kw">const</span> size = <span class="tok-number">14</span>;</span>
<span class="line" id="L85"> <span class="tok-kw">const</span> correct_magic = [<span class="tok-number">4</span>]<span class="tok-type">u8</span>{ <span class="tok-str">'q'</span>, <span class="tok-str">'o'</span>, <span class="tok-str">'i'</span>, <span class="tok-str">'f'</span> };</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> width: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L88"> height: <span class="tok-type">u32</span> <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L89"> format: Format <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L90"> colorspace: Colorspace <span class="tok-kw">align</span>(<span class="tok-number">1</span>),</span>
<span class="line" id="L91"></span>
<span class="line" id="L92"> <span class="tok-kw">fn</span> <span class="tok-fn">encode</span>(header: Header) [size]<span class="tok-type">u8</span> {</span>
<span class="line" id="L93"> <span class="tok-kw">var</span> result: [size]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L94"> <span class="tok-builtin">@memcpy</span>(result[<span class="tok-number">0</span>..<span class="tok-number">4</span>], &amp;correct_magic);</span>
<span class="line" id="L95"> std.mem.writeInt(<span class="tok-type">u32</span>, result[<span class="tok-number">4</span>..<span class="tok-number">8</span>], header.width, .big);</span>
<span class="line" id="L96"> std.mem.writeInt(<span class="tok-type">u32</span>, result[<span class="tok-number">8</span>..<span class="tok-number">12</span>], header.height, .big);</span>
<span class="line" id="L97"> result[<span class="tok-number">12</span>] = <span class="tok-builtin">@intFromEnum</span>(header.format);</span>
<span class="line" id="L98"> result[<span class="tok-number">13</span>] = <span class="tok-builtin">@intFromEnum</span>(header.colorspace);</span>
<span class="line" id="L99"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L100"> }</span>
<span class="line" id="L101"></span>
<span class="line" id="L102"> <span class="tok-kw">comptime</span> {</span>
<span class="line" id="L103"> std.debug.assert((<span class="tok-builtin">@sizeOf</span>(Header) + Header.correct_magic.len) == Header.size);</span>
<span class="line" id="L104"> }</span>
<span class="line" id="L105">};</span>
<span class="line" id="L106"></span>
<span class="line" id="L107"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> QOI = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L108"> header: Header = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L109"></span>
<span class="line" id="L110"> <span class="tok-kw">pub</span> <span class="tok-kw">const</span> EncoderOptions = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L111"> colorspace: Colorspace = .srgb,</span>
<span class="line" id="L112"> };</span>
<span class="line" id="L113"></span>
<span class="line" id="L114"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatInterface</span>() FormatInterface {</span>
<span class="line" id="L117"> <span class="tok-kw">return</span> FormatInterface{</span>
<span class="line" id="L118"> .format = format,</span>
<span class="line" id="L119"> .formatDetect = formatDetect,</span>
<span class="line" id="L120"> .readImage = readImage,</span>
<span class="line" id="L121"> .writeImage = writeImage,</span>
<span class="line" id="L122"> };</span>
<span class="line" id="L123"> }</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">format</span>() Image.Format {</span>
<span class="line" id="L126"> <span class="tok-kw">return</span> Image.Format.qoi;</span>
<span class="line" id="L127"> }</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">formatDetect</span>(stream: *Image.Stream) ImageReadError!<span class="tok-type">bool</span> {</span>
<span class="line" id="L130"> <span class="tok-kw">var</span> magic_buffer: [Header.correct_magic.len]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L131"></span>
<span class="line" id="L132"> _ = <span class="tok-kw">try</span> stream.read(magic_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L133"></span>
<span class="line" id="L134"> <span class="tok-kw">return</span> std.mem.eql(<span class="tok-type">u8</span>, magic_buffer[<span class="tok-number">0</span>..], Header.correct_magic[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"></span>
<span class="line" id="L137"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readImage</span>(allocator: Allocator, stream: *Image.Stream) ImageReadError!Image {</span>
<span class="line" id="L138"> <span class="tok-kw">var</span> result = Image.init(allocator);</span>
<span class="line" id="L139"> <span class="tok-kw">errdefer</span> result.deinit();</span>
<span class="line" id="L140"> <span class="tok-kw">var</span> qoi = Self{};</span>
<span class="line" id="L141"></span>
<span class="line" id="L142"> <span class="tok-kw">const</span> pixels = <span class="tok-kw">try</span> qoi.read(allocator, stream);</span>
<span class="line" id="L143"></span>
<span class="line" id="L144"> result.width = qoi.width();</span>
<span class="line" id="L145"> result.height = qoi.height();</span>
<span class="line" id="L146"> result.pixels = pixels;</span>
<span class="line" id="L147"></span>
<span class="line" id="L148"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L149"> }</span>
<span class="line" id="L150"></span>
<span class="line" id="L151"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeImage</span>(allocator: Allocator, write_stream: *Image.Stream, image: Image, encoder_options: Image.EncoderOptions) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L152"> _ = allocator;</span>
<span class="line" id="L153"></span>
<span class="line" id="L154"> <span class="tok-kw">var</span> qoi = Self{};</span>
<span class="line" id="L155"> qoi.header.width = <span class="tok-builtin">@truncate</span>(image.width);</span>
<span class="line" id="L156"> qoi.header.height = <span class="tok-builtin">@truncate</span>(image.height);</span>
<span class="line" id="L157"> qoi.header.format = <span class="tok-kw">switch</span> (image.pixels) {</span>
<span class="line" id="L158"> .rgb24 =&gt; Format.rgb,</span>
<span class="line" id="L159"> .rgba32 =&gt; Format.rgba,</span>
<span class="line" id="L160"> <span class="tok-kw">else</span> =&gt; <span class="tok-kw">return</span> ImageError.Unsupported,</span>
<span class="line" id="L161"> };</span>
<span class="line" id="L162"> <span class="tok-kw">switch</span> (encoder_options) {</span>
<span class="line" id="L163"> .qoi =&gt; |qoi_encode_options| {</span>
<span class="line" id="L164"> qoi.header.colorspace = qoi_encode_options.colorspace;</span>
<span class="line" id="L165"> },</span>
<span class="line" id="L166"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L167"> qoi.header.colorspace = .srgb;</span>
<span class="line" id="L168"> },</span>
<span class="line" id="L169"> }</span>
<span class="line" id="L170"></span>
<span class="line" id="L171"> <span class="tok-kw">try</span> qoi.write(write_stream, image.pixels);</span>
<span class="line" id="L172"> }</span>
<span class="line" id="L173"></span>
<span class="line" id="L174"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">width</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L175"> <span class="tok-kw">return</span> self.header.width;</span>
<span class="line" id="L176"> }</span>
<span class="line" id="L177"></span>
<span class="line" id="L178"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">height</span>(self: Self) <span class="tok-type">usize</span> {</span>
<span class="line" id="L179"> <span class="tok-kw">return</span> self.header.height;</span>
<span class="line" id="L180"> }</span>
<span class="line" id="L181"></span>
<span class="line" id="L182"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelFormat</span>(self: Self) !PixelFormat {</span>
<span class="line" id="L183"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self.header.format) {</span>
<span class="line" id="L184"> .rgb =&gt; PixelFormat.rgb24,</span>
<span class="line" id="L185"> .rgba =&gt; PixelFormat.rgba32,</span>
<span class="line" id="L186"> };</span>
<span class="line" id="L187"> }</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">read</span>(self: *Self, allocator: Allocator, stream: *Image.Stream) ImageReadError!color.PixelStorage {</span>
<span class="line" id="L190"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceReader(stream);</span>
<span class="line" id="L191"></span>
<span class="line" id="L192"> <span class="tok-kw">var</span> magic_buffer: [Header.correct_magic.len]<span class="tok-type">u8</span> = <span class="tok-null">undefined</span>;</span>
<span class="line" id="L193"></span>
<span class="line" id="L194"> <span class="tok-kw">const</span> reader = buffered_stream.reader();</span>
<span class="line" id="L195"></span>
<span class="line" id="L196"> _ = <span class="tok-kw">try</span> buffered_stream.read(magic_buffer[<span class="tok-number">0</span>..]);</span>
<span class="line" id="L197"></span>
<span class="line" id="L198"> <span class="tok-kw">if</span> (!std.mem.eql(<span class="tok-type">u8</span>, magic_buffer[<span class="tok-number">0</span>..], Header.correct_magic[<span class="tok-number">0</span>..])) {</span>
<span class="line" id="L199"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L200"> }</span>
<span class="line" id="L201"></span>
<span class="line" id="L202"> self.header = utils.readStruct(reader, Header, .big) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L203"></span>
<span class="line" id="L204"> <span class="tok-kw">const</span> pixel_format = <span class="tok-kw">try</span> self.pixelFormat();</span>
<span class="line" id="L205"></span>
<span class="line" id="L206"> <span class="tok-kw">var</span> pixels = <span class="tok-kw">try</span> color.PixelStorage.init(allocator, pixel_format, self.width() * self.height());</span>
<span class="line" id="L207"> <span class="tok-kw">errdefer</span> pixels.deinit(allocator);</span>
<span class="line" id="L208"></span>
<span class="line" id="L209"> <span class="tok-kw">var</span> current_color = QoiColor{ .r = <span class="tok-number">0</span>, .g = <span class="tok-number">0</span>, .b = <span class="tok-number">0</span>, .a = <span class="tok-number">0xFF</span> };</span>
<span class="line" id="L210"> <span class="tok-kw">var</span> color_lut = std.mem.zeroes([<span class="tok-number">64</span>]QoiColor);</span>
<span class="line" id="L211"></span>
<span class="line" id="L212"> <span class="tok-kw">var</span> index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L213"> <span class="tok-kw">const</span> pixels_size: <span class="tok-type">usize</span> = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, self.header.width) * <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, self.header.height);</span>
<span class="line" id="L214"></span>
<span class="line" id="L215"> <span class="tok-kw">while</span> (index &lt; pixels_size) {</span>
<span class="line" id="L216"> <span class="tok-kw">const</span> byte = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L217"></span>
<span class="line" id="L218"> <span class="tok-kw">var</span> new_color = current_color;</span>
<span class="line" id="L219"> <span class="tok-kw">var</span> count: <span class="tok-type">usize</span> = <span class="tok-number">1</span>;</span>
<span class="line" id="L220"></span>
<span class="line" id="L221"> <span class="tok-kw">if</span> (byte == <span class="tok-number">0b11111110</span>) { <span class="tok-comment">// QOI_OP_RGB</span>
</span>
<span class="line" id="L222"> new_color.r = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L223"> new_color.g = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L224"> new_color.b = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L225"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (byte == <span class="tok-number">0b11111111</span>) { <span class="tok-comment">// QOI_OP_RGBA</span>
</span>
<span class="line" id="L226"> new_color.r = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L227"> new_color.g = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L228"> new_color.b = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L229"> new_color.a = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L230"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (hasPrefix(byte, <span class="tok-type">u2</span>, <span class="tok-number">0b00</span>)) { <span class="tok-comment">// QOI_OP_INDEX</span>
</span>
<span class="line" id="L231"> <span class="tok-kw">const</span> color_index: <span class="tok-type">u6</span> = <span class="tok-builtin">@truncate</span>(byte);</span>
<span class="line" id="L232"> new_color = color_lut[color_index];</span>
<span class="line" id="L233"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (hasPrefix(byte, <span class="tok-type">u2</span>, <span class="tok-number">0b01</span>)) { <span class="tok-comment">// QOI_OP_DIFF</span>
</span>
<span class="line" id="L234"> <span class="tok-kw">const</span> diff_r = unmapRange2(byte &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L235"> <span class="tok-kw">const</span> diff_g = unmapRange2(byte &gt;&gt; <span class="tok-number">2</span>);</span>
<span class="line" id="L236"> <span class="tok-kw">const</span> diff_b = unmapRange2(byte &gt;&gt; <span class="tok-number">0</span>);</span>
<span class="line" id="L237"></span>
<span class="line" id="L238"> add8(&amp;new_color.r, diff_r);</span>
<span class="line" id="L239"> add8(&amp;new_color.g, diff_g);</span>
<span class="line" id="L240"> add8(&amp;new_color.b, diff_b);</span>
<span class="line" id="L241"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (hasPrefix(byte, <span class="tok-type">u2</span>, <span class="tok-number">0b10</span>)) { <span class="tok-comment">// QOI_OP_LUMA</span>
</span>
<span class="line" id="L242"> <span class="tok-kw">const</span> diff_g = unmapRange6(byte);</span>
<span class="line" id="L243"></span>
<span class="line" id="L244"> <span class="tok-kw">const</span> diff_rg_rb = <span class="tok-kw">try</span> reader.readByte();</span>
<span class="line" id="L245"></span>
<span class="line" id="L246"> <span class="tok-kw">const</span> diff_rg = unmapRange4(diff_rg_rb &gt;&gt; <span class="tok-number">4</span>);</span>
<span class="line" id="L247"> <span class="tok-kw">const</span> diff_rb = unmapRange4(diff_rg_rb &gt;&gt; <span class="tok-number">0</span>);</span>
<span class="line" id="L248"></span>
<span class="line" id="L249"> <span class="tok-kw">const</span> diff_r = <span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, diff_g) + diff_rg;</span>
<span class="line" id="L250"> <span class="tok-kw">const</span> diff_b = <span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, diff_g) + diff_rb;</span>
<span class="line" id="L251"></span>
<span class="line" id="L252"> add8(&amp;new_color.r, diff_r);</span>
<span class="line" id="L253"> add8(&amp;new_color.g, diff_g);</span>
<span class="line" id="L254"> add8(&amp;new_color.b, diff_b);</span>
<span class="line" id="L255"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (hasPrefix(byte, <span class="tok-type">u2</span>, <span class="tok-number">0b11</span>)) { <span class="tok-comment">// QOI_OP_RUN</span>
</span>
<span class="line" id="L256"> count = <span class="tok-builtin">@as</span>(<span class="tok-type">usize</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u6</span>, <span class="tok-builtin">@truncate</span>(byte))) + <span class="tok-number">1</span>;</span>
<span class="line" id="L257"> std.debug.assert(count &gt;= <span class="tok-number">1</span> <span class="tok-kw">and</span> count &lt;= <span class="tok-number">62</span>);</span>
<span class="line" id="L258"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L259"> <span class="tok-comment">// we have covered all possibilities.</span>
</span>
<span class="line" id="L260"> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L261"> }</span>
<span class="line" id="L262"></span>
<span class="line" id="L263"> <span class="tok-comment">// this will happen when a file has an invalid run length</span>
</span>
<span class="line" id="L264"> <span class="tok-comment">// and we would decode more pixels than there are in the image.</span>
</span>
<span class="line" id="L265"> <span class="tok-kw">if</span> (index + count &gt; pixels_size) {</span>
<span class="line" id="L266"> <span class="tok-kw">return</span> ImageReadError.InvalidData;</span>
<span class="line" id="L267"> }</span>
<span class="line" id="L268"></span>
<span class="line" id="L269"> <span class="tok-kw">while</span> (count &gt; <span class="tok-number">0</span>) {</span>
<span class="line" id="L270"> count -= <span class="tok-number">1</span>;</span>
<span class="line" id="L271"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L272"> .rgb24 =&gt; |data| {</span>
<span class="line" id="L273"> data[index] = new_color.toRgb24();</span>
<span class="line" id="L274"> },</span>
<span class="line" id="L275"> .rgba32 =&gt; |data| {</span>
<span class="line" id="L276"> data[index] = new_color.toRgba32();</span>
<span class="line" id="L277"> },</span>
<span class="line" id="L278"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L279"> }</span>
<span class="line" id="L280"> index += <span class="tok-number">1</span>;</span>
<span class="line" id="L281"> }</span>
<span class="line" id="L282"></span>
<span class="line" id="L283"> color_lut[new_color.hash()] = new_color;</span>
<span class="line" id="L284"> current_color = new_color;</span>
<span class="line" id="L285"> }</span>
<span class="line" id="L286"></span>
<span class="line" id="L287"> <span class="tok-kw">return</span> pixels;</span>
<span class="line" id="L288"> }</span>
<span class="line" id="L289"></span>
<span class="line" id="L290"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">write</span>(self: Self, stream: *Image.Stream, pixels: color.PixelStorage) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L291"> <span class="tok-kw">var</span> buffered_stream = buffered_stream_source.bufferedStreamSourceWriter(stream);</span>
<span class="line" id="L292"> <span class="tok-kw">const</span> writer = buffered_stream.writer();</span>
<span class="line" id="L293"> <span class="tok-kw">try</span> writer.writeAll(&amp;self.header.encode());</span>
<span class="line" id="L294"></span>
<span class="line" id="L295"> <span class="tok-kw">switch</span> (pixels) {</span>
<span class="line" id="L296"> .rgb24 =&gt; |data| {</span>
<span class="line" id="L297"> <span class="tok-kw">try</span> writeData(writer, data);</span>
<span class="line" id="L298"> },</span>
<span class="line" id="L299"> .rgba32 =&gt; |data| {</span>
<span class="line" id="L300"> <span class="tok-kw">try</span> writeData(writer, data);</span>
<span class="line" id="L301"> },</span>
<span class="line" id="L302"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L303"> <span class="tok-kw">return</span> ImageError.Unsupported;</span>
<span class="line" id="L304"> },</span>
<span class="line" id="L305"> }</span>
<span class="line" id="L306"></span>
<span class="line" id="L307"> <span class="tok-kw">try</span> writer.writeAll(&amp;[<span class="tok-number">8</span>]<span class="tok-type">u8</span>{</span>
<span class="line" id="L308"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L309"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L310"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L311"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L312"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L313"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L314"> <span class="tok-number">0x00</span>,</span>
<span class="line" id="L315"> <span class="tok-number">0x01</span>,</span>
<span class="line" id="L316"> });</span>
<span class="line" id="L317"></span>
<span class="line" id="L318"> <span class="tok-kw">try</span> buffered_stream.flush();</span>
<span class="line" id="L319"> }</span>
<span class="line" id="L320"></span>
<span class="line" id="L321"> <span class="tok-kw">fn</span> <span class="tok-fn">writeData</span>(writer: buffered_stream_source.DefaultBufferedStreamSourceWriter.Writer, pixels_data: <span class="tok-kw">anytype</span>) ImageWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L322"> <span class="tok-kw">var</span> color_lut = std.mem.zeroes([<span class="tok-number">64</span>]QoiColor);</span>
<span class="line" id="L323"></span>
<span class="line" id="L324"> <span class="tok-kw">var</span> previous_pixel = QoiColor{ .r = <span class="tok-number">0</span>, .g = <span class="tok-number">0</span>, .b = <span class="tok-number">0</span>, .a = <span class="tok-number">0xFF</span> };</span>
<span class="line" id="L325"> <span class="tok-kw">var</span> run_length: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L326"></span>
<span class="line" id="L327"> <span class="tok-kw">for</span> (pixels_data, <span class="tok-number">0</span>..) |current_color, i| {</span>
<span class="line" id="L328"> <span class="tok-kw">const</span> pixel = QoiColor.from(current_color);</span>
<span class="line" id="L329"></span>
<span class="line" id="L330"> <span class="tok-kw">defer</span> previous_pixel = pixel;</span>
<span class="line" id="L331"></span>
<span class="line" id="L332"> <span class="tok-kw">const</span> same_pixel = pixel.eql(previous_pixel);</span>
<span class="line" id="L333"></span>
<span class="line" id="L334"> <span class="tok-kw">if</span> (same_pixel) {</span>
<span class="line" id="L335"> run_length += <span class="tok-number">1</span>;</span>
<span class="line" id="L336"> }</span>
<span class="line" id="L337"></span>
<span class="line" id="L338"> <span class="tok-kw">if</span> (run_length &gt; <span class="tok-number">0</span> <span class="tok-kw">and</span> (run_length == <span class="tok-number">62</span> <span class="tok-kw">or</span> !same_pixel <span class="tok-kw">or</span> (i == (pixels_data.len - <span class="tok-number">1</span>)))) {</span>
<span class="line" id="L339"> <span class="tok-comment">// QOI_OP_RUN</span>
</span>
<span class="line" id="L340"> std.debug.assert(run_length &gt;= <span class="tok-number">1</span> <span class="tok-kw">and</span> run_length &lt;= <span class="tok-number">62</span>);</span>
<span class="line" id="L341"> <span class="tok-kw">try</span> writer.writeByte(<span class="tok-number">0b1100_0000</span> | <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-builtin">@truncate</span>(run_length - <span class="tok-number">1</span>)));</span>
<span class="line" id="L342"> run_length = <span class="tok-number">0</span>;</span>
<span class="line" id="L343"> }</span>
<span class="line" id="L344"></span>
<span class="line" id="L345"> <span class="tok-kw">if</span> (!same_pixel) {</span>
<span class="line" id="L346"> <span class="tok-kw">const</span> hash = pixel.hash();</span>
<span class="line" id="L347"> <span class="tok-kw">if</span> (color_lut[hash].eql(pixel)) {</span>
<span class="line" id="L348"> <span class="tok-comment">// QOI_OP_INDEX</span>
</span>
<span class="line" id="L349"> <span class="tok-kw">try</span> writer.writeByte(<span class="tok-number">0b0000_0000</span> | hash);</span>
<span class="line" id="L350"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L351"> color_lut[hash] = pixel;</span>
<span class="line" id="L352"></span>
<span class="line" id="L353"> <span class="tok-kw">const</span> diff_r = <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, pixel.r) - <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, previous_pixel.r);</span>
<span class="line" id="L354"> <span class="tok-kw">const</span> diff_g = <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, pixel.g) - <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, previous_pixel.g);</span>
<span class="line" id="L355"> <span class="tok-kw">const</span> diff_b = <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, pixel.b) - <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, previous_pixel.b);</span>
<span class="line" id="L356"> <span class="tok-kw">const</span> diff_a = <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, pixel.a) - <span class="tok-builtin">@as</span>(<span class="tok-type">i16</span>, previous_pixel.a);</span>
<span class="line" id="L357"></span>
<span class="line" id="L358"> <span class="tok-kw">const</span> diff_rg = diff_r - diff_g;</span>
<span class="line" id="L359"> <span class="tok-kw">const</span> diff_rb = diff_b - diff_g;</span>
<span class="line" id="L360"></span>
<span class="line" id="L361"> <span class="tok-kw">if</span> (diff_a == <span class="tok-number">0</span> <span class="tok-kw">and</span> inRange2(diff_r) <span class="tok-kw">and</span> inRange2(diff_g) <span class="tok-kw">and</span> inRange2(diff_b)) {</span>
<span class="line" id="L362"> <span class="tok-comment">// QOI_OP_DIFF</span>
</span>
<span class="line" id="L363"> <span class="tok-kw">const</span> byte = <span class="tok-number">0b0100_0000</span> |</span>
<span class="line" id="L364"> (mapRange2(diff_r) &lt;&lt; <span class="tok-number">4</span>) |</span>
<span class="line" id="L365"> (mapRange2(diff_g) &lt;&lt; <span class="tok-number">2</span>) |</span>
<span class="line" id="L366"> (mapRange2(diff_b) &lt;&lt; <span class="tok-number">0</span>);</span>
<span class="line" id="L367"> <span class="tok-kw">try</span> writer.writeByte(byte);</span>
<span class="line" id="L368"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (diff_a == <span class="tok-number">0</span> <span class="tok-kw">and</span> inRange6(diff_g) <span class="tok-kw">and</span> inRange4(diff_rg) <span class="tok-kw">and</span> inRange4(diff_rb)) {</span>
<span class="line" id="L369"> <span class="tok-comment">// QOI_OP_LUMA</span>
</span>
<span class="line" id="L370"> <span class="tok-kw">try</span> writer.writeAll(&amp;[<span class="tok-number">2</span>]<span class="tok-type">u8</span>{</span>
<span class="line" id="L371"> <span class="tok-number">0b1000_0000</span> | mapRange6(diff_g),</span>
<span class="line" id="L372"> (mapRange4(diff_rg) &lt;&lt; <span class="tok-number">4</span>) | (mapRange4(diff_rb) &lt;&lt; <span class="tok-number">0</span>),</span>
<span class="line" id="L373"> });</span>
<span class="line" id="L374"> } <span class="tok-kw">else</span> <span class="tok-kw">if</span> (diff_a == <span class="tok-number">0</span>) {</span>
<span class="line" id="L375"> <span class="tok-comment">// QOI_OP_RGB</span>
</span>
<span class="line" id="L376"> <span class="tok-kw">try</span> writer.writeAll(&amp;[<span class="tok-number">4</span>]<span class="tok-type">u8</span>{</span>
<span class="line" id="L377"> <span class="tok-number">0b1111_1110</span>,</span>
<span class="line" id="L378"> pixel.r,</span>
<span class="line" id="L379"> pixel.g,</span>
<span class="line" id="L380"> pixel.b,</span>
<span class="line" id="L381"> });</span>
<span class="line" id="L382"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L383"> <span class="tok-comment">// QOI_OP_RGBA</span>
</span>
<span class="line" id="L384"> <span class="tok-kw">try</span> writer.writeAll(&amp;[<span class="tok-number">5</span>]<span class="tok-type">u8</span>{</span>
<span class="line" id="L385"> <span class="tok-number">0b1111_1111</span>,</span>
<span class="line" id="L386"> pixel.r,</span>
<span class="line" id="L387"> pixel.g,</span>
<span class="line" id="L388"> pixel.b,</span>
<span class="line" id="L389"> pixel.a,</span>
<span class="line" id="L390"> });</span>
<span class="line" id="L391"> }</span>
<span class="line" id="L392"> }</span>
<span class="line" id="L393"> }</span>
<span class="line" id="L394"> }</span>
<span class="line" id="L395"> }</span>
<span class="line" id="L396"></span>
<span class="line" id="L397"> <span class="tok-kw">fn</span> <span class="tok-fn">mapRange2</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L398"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u2</span>, <span class="tok-builtin">@intCast</span>(val + <span class="tok-number">2</span>));</span>
<span class="line" id="L399"> }</span>
<span class="line" id="L400"> <span class="tok-kw">fn</span> <span class="tok-fn">mapRange4</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L401"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u4</span>, <span class="tok-builtin">@intCast</span>(val + <span class="tok-number">8</span>));</span>
<span class="line" id="L402"> }</span>
<span class="line" id="L403"> <span class="tok-kw">fn</span> <span class="tok-fn">mapRange6</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L404"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">u6</span>, <span class="tok-builtin">@intCast</span>(val + <span class="tok-number">32</span>));</span>
<span class="line" id="L405"> }</span>
<span class="line" id="L406"></span>
<span class="line" id="L407"> <span class="tok-kw">fn</span> <span class="tok-fn">unmapRange2</span>(val: <span class="tok-type">u32</span>) <span class="tok-type">i2</span> {</span>
<span class="line" id="L408"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">i2</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u2</span>, <span class="tok-builtin">@truncate</span>(val))) - <span class="tok-number">2</span>));</span>
<span class="line" id="L409"> }</span>
<span class="line" id="L410"> <span class="tok-kw">fn</span> <span class="tok-fn">unmapRange4</span>(val: <span class="tok-type">u32</span>) <span class="tok-type">i4</span> {</span>
<span class="line" id="L411"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">i4</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u4</span>, <span class="tok-builtin">@truncate</span>(val))) - <span class="tok-number">8</span>));</span>
<span class="line" id="L412"> }</span>
<span class="line" id="L413"> <span class="tok-kw">fn</span> <span class="tok-fn">unmapRange6</span>(val: <span class="tok-type">u32</span>) <span class="tok-type">i6</span> {</span>
<span class="line" id="L414"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(<span class="tok-type">i6</span>, <span class="tok-builtin">@intCast</span>(<span class="tok-builtin">@as</span>(<span class="tok-type">i8</span>, <span class="tok-builtin">@as</span>(<span class="tok-type">u6</span>, <span class="tok-builtin">@truncate</span>(val))) - <span class="tok-number">32</span>));</span>
<span class="line" id="L415"> }</span>
<span class="line" id="L416"></span>
<span class="line" id="L417"> <span class="tok-kw">fn</span> <span class="tok-fn">inRange2</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L418"> <span class="tok-kw">return</span> (val &gt;= -<span class="tok-number">2</span>) <span class="tok-kw">and</span> (val &lt;= <span class="tok-number">1</span>);</span>
<span class="line" id="L419"> }</span>
<span class="line" id="L420"> <span class="tok-kw">fn</span> <span class="tok-fn">inRange4</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L421"> <span class="tok-kw">return</span> (val &gt;= -<span class="tok-number">8</span>) <span class="tok-kw">and</span> (val &lt;= <span class="tok-number">7</span>);</span>
<span class="line" id="L422"> }</span>
<span class="line" id="L423"> <span class="tok-kw">fn</span> <span class="tok-fn">inRange6</span>(val: <span class="tok-type">i16</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L424"> <span class="tok-kw">return</span> (val &gt;= -<span class="tok-number">32</span>) <span class="tok-kw">and</span> (val &lt;= <span class="tok-number">31</span>);</span>
<span class="line" id="L425"> }</span>
<span class="line" id="L426"></span>
<span class="line" id="L427"> <span class="tok-kw">fn</span> <span class="tok-fn">add8</span>(dst: *<span class="tok-type">u8</span>, diff: <span class="tok-type">i8</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L428"> dst.* +%= <span class="tok-builtin">@bitCast</span>(diff);</span>
<span class="line" id="L429"> }</span>
<span class="line" id="L430"></span>
<span class="line" id="L431"> <span class="tok-kw">fn</span> <span class="tok-fn">hasPrefix</span>(value: <span class="tok-type">u8</span>, <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, prefix: T) <span class="tok-type">bool</span> {</span>
<span class="line" id="L432"> <span class="tok-kw">return</span> (<span class="tok-builtin">@as</span>(T, <span class="tok-builtin">@truncate</span>(value &gt;&gt; (<span class="tok-number">8</span> - <span class="tok-builtin">@bitSizeOf</span>(T)))) == prefix);</span>
<span class="line" id="L433"> }</span>
<span class="line" id="L434">};</span>
<span class="line" id="L435"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -1,335 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/octree_quantizer.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> Allocator = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).mem.Allocator;</span>
<span class="line" id="L2"><span class="tok-kw">const</span> ArenaAllocator = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).heap.ArenaAllocator;</span>
<span class="line" id="L3"><span class="tok-kw">const</span> ArrayList = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>).ArrayList;</span>
<span class="line" id="L4"><span class="tok-kw">const</span> Rgba32 = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;color.zig&quot;</span>).Rgba32;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">const</span> MaxDepth = <span class="tok-number">8</span>;</span>
<span class="line" id="L7"></span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> OctTreeQuantizer = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L9"> rootNode: OctTreeQuantizerNode,</span>
<span class="line" id="L10"> levels: [MaxDepth]NodeArrayList,</span>
<span class="line" id="L11"> arenaAllocator: ArenaAllocator,</span>
<span class="line" id="L12"></span>
<span class="line" id="L13"> <span class="tok-kw">const</span> NodeArrayList = ArrayList(*OctTreeQuantizerNode);</span>
<span class="line" id="L14"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(allocator: Allocator) Self {</span>
<span class="line" id="L17"> <span class="tok-kw">var</span> result = Self{</span>
<span class="line" id="L18"> .rootNode = OctTreeQuantizerNode{},</span>
<span class="line" id="L19"> .arenaAllocator = ArenaAllocator.init(allocator),</span>
<span class="line" id="L20"> .levels = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L21"> };</span>
<span class="line" id="L22"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L23"> <span class="tok-kw">while</span> (i &lt; result.levels.len) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L24"> result.levels[i] = NodeArrayList.init(allocator);</span>
<span class="line" id="L25"> }</span>
<span class="line" id="L26"> result.rootNode.init(<span class="tok-number">0</span>, &amp;result) <span class="tok-kw">catch</span> <span class="tok-kw">unreachable</span>;</span>
<span class="line" id="L27"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L28"> }</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">deinit</span>(self: *Self) <span class="tok-type">void</span> {</span>
<span class="line" id="L31"> self.arenaAllocator.deinit();</span>
<span class="line" id="L32"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L33"> <span class="tok-kw">while</span> (i &lt; self.levels.len) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L34"> self.levels[i].deinit();</span>
<span class="line" id="L35"> }</span>
<span class="line" id="L36"> }</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">allocateNode</span>(self: *Self) !*OctTreeQuantizerNode {</span>
<span class="line" id="L39"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> self.arenaAllocator.allocator().create(OctTreeQuantizerNode);</span>
<span class="line" id="L40"> }</span>
<span class="line" id="L41"></span>
<span class="line" id="L42"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">addLevelNode</span>(self: *Self, level: <span class="tok-type">i32</span>, node: *OctTreeQuantizerNode) !<span class="tok-type">void</span> {</span>
<span class="line" id="L43"> <span class="tok-kw">try</span> self.levels[<span class="tok-builtin">@intCast</span>(level)].append(node);</span>
<span class="line" id="L44"> }</span>
<span class="line" id="L45"></span>
<span class="line" id="L46"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">addColor</span>(self: *Self, color: Rgba32) !<span class="tok-type">void</span> {</span>
<span class="line" id="L47"> <span class="tok-kw">try</span> self.rootNode.addColor(color, <span class="tok-number">0</span>, self);</span>
<span class="line" id="L48"> }</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getPaletteIndex</span>(self: Self, color: Rgba32) !<span class="tok-type">usize</span> {</span>
<span class="line" id="L51"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> self.rootNode.getPaletteIndex(color, <span class="tok-number">0</span>);</span>
<span class="line" id="L52"> }</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">makePalette</span>(self: *Self, colorCount: <span class="tok-type">usize</span>, palette: []Rgba32) <span class="tok-type">anyerror</span>![]Rgba32 {</span>
<span class="line" id="L55"> <span class="tok-kw">var</span> paletteIndex: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L56"></span>
<span class="line" id="L57"> <span class="tok-kw">var</span> rootLeafNodes = <span class="tok-kw">try</span> self.rootNode.getLeafNodes(self.arenaAllocator.child_allocator);</span>
<span class="line" id="L58"> <span class="tok-kw">defer</span> rootLeafNodes.deinit();</span>
<span class="line" id="L59"> <span class="tok-kw">var</span> leafCount = rootLeafNodes.items.len;</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> <span class="tok-kw">var</span> level: <span class="tok-type">usize</span> = MaxDepth - <span class="tok-number">1</span>;</span>
<span class="line" id="L62"> <span class="tok-kw">while</span> (level &gt;= <span class="tok-number">0</span>) : (level -= <span class="tok-number">1</span>) {</span>
<span class="line" id="L63"> <span class="tok-kw">for</span> (self.levels[level].items) |node| {</span>
<span class="line" id="L64"> leafCount -= <span class="tok-builtin">@intCast</span>(node.removeLeaves());</span>
<span class="line" id="L65"> <span class="tok-kw">if</span> (leafCount &lt;= colorCount) {</span>
<span class="line" id="L66"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69"> <span class="tok-kw">if</span> (leafCount &lt;= colorCount) {</span>
<span class="line" id="L70"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L71"> }</span>
<span class="line" id="L72"> <span class="tok-kw">try</span> self.levels[level].resize(<span class="tok-number">0</span>);</span>
<span class="line" id="L73"> }</span>
<span class="line" id="L74"></span>
<span class="line" id="L75"> <span class="tok-kw">var</span> processedRoofLeafNodes = <span class="tok-kw">try</span> self.rootNode.getLeafNodes(self.arenaAllocator.child_allocator);</span>
<span class="line" id="L76"> <span class="tok-kw">defer</span> processedRoofLeafNodes.deinit();</span>
<span class="line" id="L77"></span>
<span class="line" id="L78"> <span class="tok-kw">for</span> (processedRoofLeafNodes.items) |node| {</span>
<span class="line" id="L79"> <span class="tok-kw">if</span> (paletteIndex &gt;= colorCount) {</span>
<span class="line" id="L80"> <span class="tok-kw">break</span>;</span>
<span class="line" id="L81"> }</span>
<span class="line" id="L82"> <span class="tok-kw">if</span> (node.isLeaf()) {</span>
<span class="line" id="L83"> palette[paletteIndex] = node.getColor();</span>
<span class="line" id="L84"> node.paletteIndex = paletteIndex;</span>
<span class="line" id="L85"> paletteIndex += <span class="tok-number">1</span>;</span>
<span class="line" id="L86"> }</span>
<span class="line" id="L87"> }</span>
<span class="line" id="L88"></span>
<span class="line" id="L89"> <span class="tok-kw">return</span> palette[<span class="tok-number">0</span>..paletteIndex];</span>
<span class="line" id="L90"> }</span>
<span class="line" id="L91">};</span>
<span class="line" id="L92"></span>
<span class="line" id="L93"><span class="tok-kw">const</span> OctTreeQuantizerNode = <span class="tok-kw">struct</span> {</span>
<span class="line" id="L94"> red: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L95"> green: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L96"> blue: <span class="tok-type">u32</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L97"> referenceCount: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L98"> paletteIndex: <span class="tok-type">usize</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L99"> children: [<span class="tok-number">8</span>]?*Self = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L100"></span>
<span class="line" id="L101"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L102"> <span class="tok-kw">const</span> NodeArrayList = ArrayList(*Self);</span>
<span class="line" id="L103"></span>
<span class="line" id="L104"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">init</span>(self: *Self, level: <span class="tok-type">i32</span>, parent: *OctTreeQuantizer) !<span class="tok-type">void</span> {</span>
<span class="line" id="L105"> self.red = <span class="tok-number">0</span>;</span>
<span class="line" id="L106"> self.green = <span class="tok-number">0</span>;</span>
<span class="line" id="L107"> self.blue = <span class="tok-number">0</span>;</span>
<span class="line" id="L108"> self.referenceCount = <span class="tok-number">0</span>;</span>
<span class="line" id="L109"> self.paletteIndex = <span class="tok-number">0</span>;</span>
<span class="line" id="L110"></span>
<span class="line" id="L111"> <span class="tok-kw">var</span> i: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L112"> <span class="tok-kw">while</span> (i &lt; self.children.len) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L113"> self.children[i] = <span class="tok-null">null</span>;</span>
<span class="line" id="L114"> }</span>
<span class="line" id="L115"></span>
<span class="line" id="L116"> <span class="tok-kw">if</span> (level &lt; (MaxDepth - <span class="tok-number">1</span>)) {</span>
<span class="line" id="L117"> <span class="tok-kw">try</span> parent.addLevelNode(level, self);</span>
<span class="line" id="L118"> }</span>
<span class="line" id="L119"> }</span>
<span class="line" id="L120"></span>
<span class="line" id="L121"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isLeaf</span>(self: Self) <span class="tok-type">bool</span> {</span>
<span class="line" id="L122"> <span class="tok-kw">return</span> self.referenceCount &gt; <span class="tok-number">0</span>;</span>
<span class="line" id="L123"> }</span>
<span class="line" id="L124"></span>
<span class="line" id="L125"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getColor</span>(self: Self) Rgba32 {</span>
<span class="line" id="L126"> <span class="tok-kw">return</span> Rgba32.initRgb(<span class="tok-builtin">@intCast</span>(self.red / self.referenceCount), <span class="tok-builtin">@intCast</span>(self.green / self.referenceCount), <span class="tok-builtin">@intCast</span>(self.blue / self.referenceCount));</span>
<span class="line" id="L127"> }</span>
<span class="line" id="L128"></span>
<span class="line" id="L129"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">addColor</span>(self: *Self, color: Rgba32, level: <span class="tok-type">i32</span>, parent: *OctTreeQuantizer) <span class="tok-type">anyerror</span>!<span class="tok-type">void</span> {</span>
<span class="line" id="L130"> <span class="tok-kw">if</span> (level &gt;= MaxDepth) {</span>
<span class="line" id="L131"> self.red += color.r;</span>
<span class="line" id="L132"> self.green += color.g;</span>
<span class="line" id="L133"> self.blue += color.b;</span>
<span class="line" id="L134"> self.referenceCount += <span class="tok-number">1</span>;</span>
<span class="line" id="L135"> <span class="tok-kw">return</span>;</span>
<span class="line" id="L136"> }</span>
<span class="line" id="L137"> <span class="tok-kw">const</span> index = getColorIndex(color, level);</span>
<span class="line" id="L138"> <span class="tok-kw">if</span> (index &gt;= self.children.len) {</span>
<span class="line" id="L139"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.InvalidColorIndex;</span>
<span class="line" id="L140"> }</span>
<span class="line" id="L141"> <span class="tok-kw">if</span> (self.children[index]) |child| {</span>
<span class="line" id="L142"> <span class="tok-kw">try</span> child.addColor(color, level + <span class="tok-number">1</span>, parent);</span>
<span class="line" id="L143"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L144"> <span class="tok-kw">var</span> newNode = <span class="tok-kw">try</span> parent.allocateNode();</span>
<span class="line" id="L145"> <span class="tok-kw">try</span> newNode.init(level, parent);</span>
<span class="line" id="L146"> <span class="tok-kw">try</span> newNode.addColor(color, level + <span class="tok-number">1</span>, parent);</span>
<span class="line" id="L147"> self.children[index] = newNode;</span>
<span class="line" id="L148"> }</span>
<span class="line" id="L149"> }</span>
<span class="line" id="L150"></span>
<span class="line" id="L151"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getPaletteIndex</span>(self: Self, color: Rgba32, level: <span class="tok-type">i32</span>) <span class="tok-type">anyerror</span>!<span class="tok-type">usize</span> {</span>
<span class="line" id="L152"> <span class="tok-kw">if</span> (self.isLeaf()) {</span>
<span class="line" id="L153"> <span class="tok-kw">return</span> self.paletteIndex;</span>
<span class="line" id="L154"> }</span>
<span class="line" id="L155"> <span class="tok-kw">const</span> index = getColorIndex(color, level);</span>
<span class="line" id="L156"> <span class="tok-kw">if</span> (self.children[index]) |child| {</span>
<span class="line" id="L157"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> child.getPaletteIndex(color, level + <span class="tok-number">1</span>);</span>
<span class="line" id="L158"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L159"> <span class="tok-kw">for</span> (self.children) |childOptional| {</span>
<span class="line" id="L160"> <span class="tok-kw">if</span> (childOptional) |child| {</span>
<span class="line" id="L161"> <span class="tok-kw">return</span> <span class="tok-kw">try</span> child.getPaletteIndex(color, level + <span class="tok-number">1</span>);</span>
<span class="line" id="L162"> }</span>
<span class="line" id="L163"> }</span>
<span class="line" id="L164"> }</span>
<span class="line" id="L165"></span>
<span class="line" id="L166"> <span class="tok-kw">return</span> <span class="tok-kw">error</span>.ColorNotFound;</span>
<span class="line" id="L167"> }</span>
<span class="line" id="L168"></span>
<span class="line" id="L169"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">getLeafNodes</span>(self: Self, allocator: Allocator) <span class="tok-type">anyerror</span>!NodeArrayList {</span>
<span class="line" id="L170"> <span class="tok-kw">var</span> leafNodes = NodeArrayList.init(allocator);</span>
<span class="line" id="L171"></span>
<span class="line" id="L172"> <span class="tok-kw">for</span> (self.children) |childOptional| {</span>
<span class="line" id="L173"> <span class="tok-kw">if</span> (childOptional) |child| {</span>
<span class="line" id="L174"> <span class="tok-kw">if</span> (child.isLeaf()) {</span>
<span class="line" id="L175"> <span class="tok-kw">try</span> leafNodes.append(child);</span>
<span class="line" id="L176"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L177"> <span class="tok-kw">var</span> childNodes = <span class="tok-kw">try</span> child.getLeafNodes(allocator);</span>
<span class="line" id="L178"> <span class="tok-kw">defer</span> childNodes.deinit();</span>
<span class="line" id="L179"> <span class="tok-kw">for</span> (childNodes.items) |childNode| {</span>
<span class="line" id="L180"> <span class="tok-kw">try</span> leafNodes.append(childNode);</span>
<span class="line" id="L181"> }</span>
<span class="line" id="L182"> }</span>
<span class="line" id="L183"> }</span>
<span class="line" id="L184"> }</span>
<span class="line" id="L185"></span>
<span class="line" id="L186"> <span class="tok-kw">return</span> leafNodes;</span>
<span class="line" id="L187"> }</span>
<span class="line" id="L188"></span>
<span class="line" id="L189"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">removeLeaves</span>(self: *Self) <span class="tok-type">i32</span> {</span>
<span class="line" id="L190"> <span class="tok-kw">var</span> result: <span class="tok-type">i32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L191"> <span class="tok-kw">for</span> (self.children, <span class="tok-number">0</span>..) |childOptional, i| {</span>
<span class="line" id="L192"> <span class="tok-kw">if</span> (childOptional) |child| {</span>
<span class="line" id="L193"> self.red += child.red;</span>
<span class="line" id="L194"> self.green += child.green;</span>
<span class="line" id="L195"> self.blue += child.blue;</span>
<span class="line" id="L196"> self.referenceCount += child.referenceCount;</span>
<span class="line" id="L197"> result += <span class="tok-number">1</span>;</span>
<span class="line" id="L198"> self.children[i] = <span class="tok-null">null</span>;</span>
<span class="line" id="L199"> }</span>
<span class="line" id="L200"> }</span>
<span class="line" id="L201"> <span class="tok-kw">return</span> result - <span class="tok-number">1</span>;</span>
<span class="line" id="L202"> }</span>
<span class="line" id="L203"></span>
<span class="line" id="L204"> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">getColorIndex</span>(color: Rgba32, level: <span class="tok-type">i32</span>) <span class="tok-type">usize</span> {</span>
<span class="line" id="L205"> <span class="tok-kw">var</span> index: <span class="tok-type">usize</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L206"> <span class="tok-kw">const</span> mask = <span class="tok-builtin">@as</span>(<span class="tok-type">u8</span>, <span class="tok-number">0b10000000</span>) &gt;&gt; <span class="tok-builtin">@intCast</span>(level);</span>
<span class="line" id="L207"> <span class="tok-kw">if</span> (color.r &amp; mask != <span class="tok-number">0</span>) {</span>
<span class="line" id="L208"> index |= <span class="tok-number">0b100</span>;</span>
<span class="line" id="L209"> }</span>
<span class="line" id="L210"> <span class="tok-kw">if</span> (color.g &amp; mask != <span class="tok-number">0</span>) {</span>
<span class="line" id="L211"> index |= <span class="tok-number">0b010</span>;</span>
<span class="line" id="L212"> }</span>
<span class="line" id="L213"> <span class="tok-kw">if</span> (color.b &amp; mask != <span class="tok-number">0</span>) {</span>
<span class="line" id="L214"> index |= <span class="tok-number">0b001</span>;</span>
<span class="line" id="L215"> }</span>
<span class="line" id="L216"> <span class="tok-kw">return</span> index;</span>
<span class="line" id="L217"> }</span>
<span class="line" id="L218">};</span>
<span class="line" id="L219"></span>
</code></pre></body>
</html>

View file

@ -1,235 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/pixel_format.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PixelFormatVariant = <span class="tok-kw">enum</span>(<span class="tok-type">u4</span>) {</span>
<span class="line" id="L2"> none = <span class="tok-number">0</span>,</span>
<span class="line" id="L3"> bgr = <span class="tok-number">1</span>,</span>
<span class="line" id="L4"> float = <span class="tok-number">2</span>,</span>
<span class="line" id="L5"> rgb565 = <span class="tok-number">3</span>,</span>
<span class="line" id="L6"> _,</span>
<span class="line" id="L7">};</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-comment">/// The values for this enum are chosen so that:</span></span>
<span class="line" id="L10"><span class="tok-comment">/// 1. value &amp; 0xFF gives number of bits per channel</span></span>
<span class="line" id="L11"><span class="tok-comment">/// 2. value &amp; 0xF00 gives number of channels</span></span>
<span class="line" id="L12"><span class="tok-comment">/// 3. value &amp; 0xF000 gives a special variant number, 1 for Bgr, 2 for Float and 3 for special Rgb 565</span></span>
<span class="line" id="L13"><span class="tok-comment">/// Note that palette index formats have number of channels set to 0.</span></span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PixelFormatInfo = <span class="tok-kw">packed</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L15"> bits_per_channel: <span class="tok-type">u8</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L16"> channel_count: <span class="tok-type">u4</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L17"> variant: PixelFormatVariant = .none,</span>
<span class="line" id="L18"> padding: <span class="tok-type">u16</span> = <span class="tok-number">0</span>,</span>
<span class="line" id="L19">};</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">toPixelFormatValue</span>(<span class="tok-kw">comptime</span> pixel_format: PixelFormatInfo) <span class="tok-type">u32</span> {</span>
<span class="line" id="L22"> <span class="tok-kw">return</span> <span class="tok-builtin">@bitCast</span>(pixel_format);</span>
<span class="line" id="L23">}</span>
<span class="line" id="L24"></span>
<span class="line" id="L25"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PixelFormat = <span class="tok-kw">enum</span>(<span class="tok-type">u32</span>) {</span>
<span class="line" id="L26"> invalid = <span class="tok-number">0</span>,</span>
<span class="line" id="L27"> indexed1 = toPixelFormatValue(.{ .bits_per_channel = <span class="tok-number">1</span> }),</span>
<span class="line" id="L28"> indexed2 = toPixelFormatValue(.{ .bits_per_channel = <span class="tok-number">2</span> }),</span>
<span class="line" id="L29"> indexed4 = toPixelFormatValue(.{ .bits_per_channel = <span class="tok-number">4</span> }),</span>
<span class="line" id="L30"> indexed8 = toPixelFormatValue(.{ .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L31"> indexed16 = toPixelFormatValue(.{ .bits_per_channel = <span class="tok-number">16</span> }),</span>
<span class="line" id="L32"> grayscale1 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">1</span>, .bits_per_channel = <span class="tok-number">1</span> }),</span>
<span class="line" id="L33"> grayscale2 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">1</span>, .bits_per_channel = <span class="tok-number">2</span> }),</span>
<span class="line" id="L34"> grayscale4 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">1</span>, .bits_per_channel = <span class="tok-number">4</span> }),</span>
<span class="line" id="L35"> grayscale8 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">1</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L36"> grayscale16 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">1</span>, .bits_per_channel = <span class="tok-number">16</span> }),</span>
<span class="line" id="L37"> grayscale8Alpha = toPixelFormatValue(.{ .channel_count = <span class="tok-number">2</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L38"> grayscale16Alpha = toPixelFormatValue(.{ .channel_count = <span class="tok-number">2</span>, .bits_per_channel = <span class="tok-number">16</span> }),</span>
<span class="line" id="L39"> rgb555 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">5</span> }),</span>
<span class="line" id="L40"> rgb565 = toPixelFormatValue(.{ .variant = .rgb565, .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">5</span> }),</span>
<span class="line" id="L41"> rgb24 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L42"> rgba32 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">4</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L43"> bgr555 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">5</span> }),</span>
<span class="line" id="L44"> bgr24 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L45"> bgra32 = toPixelFormatValue(.{ .variant = .bgr, .channel_count = <span class="tok-number">4</span>, .bits_per_channel = <span class="tok-number">8</span> }),</span>
<span class="line" id="L46"> rgb48 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">3</span>, .bits_per_channel = <span class="tok-number">16</span> }),</span>
<span class="line" id="L47"> rgba64 = toPixelFormatValue(.{ .channel_count = <span class="tok-number">4</span>, .bits_per_channel = <span class="tok-number">16</span> }),</span>
<span class="line" id="L48"> float32 = toPixelFormatValue(.{ .variant = .float, .channel_count = <span class="tok-number">4</span>, .bits_per_channel = <span class="tok-number">32</span> }),</span>
<span class="line" id="L49"></span>
<span class="line" id="L50"> <span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">info</span>(self: PixelFormat) PixelFormatInfo {</span>
<span class="line" id="L51"> <span class="tok-kw">return</span> <span class="tok-builtin">@as</span>(PixelFormatInfo, <span class="tok-builtin">@bitCast</span>(<span class="tok-builtin">@intFromEnum</span>(self)));</span>
<span class="line" id="L52"> }</span>
<span class="line" id="L53"></span>
<span class="line" id="L54"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isGrayscale</span>(self: PixelFormat) <span class="tok-type">bool</span> {</span>
<span class="line" id="L55"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L56"> .grayscale1, .grayscale2, .grayscale4, .grayscale8, .grayscale16, .grayscale8Alpha, .grayscale16Alpha =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L57"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L58"> };</span>
<span class="line" id="L59"> }</span>
<span class="line" id="L60"></span>
<span class="line" id="L61"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isIndexed</span>(self: PixelFormat) <span class="tok-type">bool</span> {</span>
<span class="line" id="L62"> <span class="tok-kw">return</span> info(self).channel_count == <span class="tok-number">0</span>;</span>
<span class="line" id="L63"> }</span>
<span class="line" id="L64"></span>
<span class="line" id="L65"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isStandardRgb</span>(self: PixelFormat) <span class="tok-type">bool</span> {</span>
<span class="line" id="L66"> <span class="tok-kw">return</span> self == .rgb24 <span class="tok-kw">or</span> self == .rgb48;</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68"></span>
<span class="line" id="L69"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isRgba</span>(self: PixelFormat) <span class="tok-type">bool</span> {</span>
<span class="line" id="L70"> <span class="tok-kw">return</span> self == .rgba32 <span class="tok-kw">or</span> self == .rgba64;</span>
<span class="line" id="L71"> }</span>
<span class="line" id="L72"></span>
<span class="line" id="L73"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">is16Bit</span>(self: PixelFormat) <span class="tok-type">bool</span> {</span>
<span class="line" id="L74"> <span class="tok-kw">return</span> info(self).bits_per_channel == <span class="tok-number">16</span>;</span>
<span class="line" id="L75"> }</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">pixelStride</span>(self: PixelFormat) <span class="tok-type">u8</span> {</span>
<span class="line" id="L78"> <span class="tok-kw">if</span> (self.isIndexed()) {</span>
<span class="line" id="L79"> <span class="tok-kw">return</span> (info(self).bits_per_channel + <span class="tok-number">7</span>) / <span class="tok-number">8</span>;</span>
<span class="line" id="L80"> }</span>
<span class="line" id="L81"></span>
<span class="line" id="L82"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L83"> <span class="tok-kw">inline</span> <span class="tok-kw">else</span> =&gt; |value| (info(value).channel_count * info(value).bits_per_channel + <span class="tok-number">7</span>) / <span class="tok-number">8</span>,</span>
<span class="line" id="L84"> };</span>
<span class="line" id="L85"> }</span>
<span class="line" id="L86"></span>
<span class="line" id="L87"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">bitsPerChannel</span>(self: PixelFormat) <span class="tok-type">u8</span> {</span>
<span class="line" id="L88"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L89"> .rgb565 =&gt; <span class="tok-kw">unreachable</span>, <span class="tok-comment">// TODO: what to do in that case?</span>
</span>
<span class="line" id="L90"> <span class="tok-kw">inline</span> <span class="tok-kw">else</span> =&gt; |value| info(value).bits_per_channel,</span>
<span class="line" id="L91"> };</span>
<span class="line" id="L92"> }</span>
<span class="line" id="L93"></span>
<span class="line" id="L94"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">channelCount</span>(self: PixelFormat) <span class="tok-type">u8</span> {</span>
<span class="line" id="L95"> <span class="tok-kw">if</span> (self.isIndexed()) {</span>
<span class="line" id="L96"> <span class="tok-kw">return</span> <span class="tok-number">1</span>;</span>
<span class="line" id="L97"> }</span>
<span class="line" id="L98"></span>
<span class="line" id="L99"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (self) {</span>
<span class="line" id="L100"> <span class="tok-kw">inline</span> <span class="tok-kw">else</span> =&gt; |value| info(value).channel_count,</span>
<span class="line" id="L101"> };</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103">};</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"><span class="tok-kw">comptime</span> {</span>
<span class="line" id="L106"> <span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L107"></span>
<span class="line" id="L108"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.grayscale1) == <span class="tok-number">0x101</span>);</span>
<span class="line" id="L109"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.grayscale16) == <span class="tok-number">0x110</span>);</span>
<span class="line" id="L110"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.grayscale8Alpha) == <span class="tok-number">0x208</span>);</span>
<span class="line" id="L111"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.rgb555) == <span class="tok-number">0x305</span>);</span>
<span class="line" id="L112"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.rgb565) == <span class="tok-number">0x3305</span>);</span>
<span class="line" id="L113"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.rgba32) == <span class="tok-number">0x408</span>);</span>
<span class="line" id="L114"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.bgr24) == <span class="tok-number">0x1308</span>);</span>
<span class="line" id="L115"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.bgra32) == <span class="tok-number">0x1408</span>);</span>
<span class="line" id="L116"> std.debug.assert(<span class="tok-builtin">@intFromEnum</span>(PixelFormat.float32) == <span class="tok-number">0x2420</span>);</span>
<span class="line" id="L117">}</span>
<span class="line" id="L118"></span>
</code></pre></body>
</html>

View file

@ -1,145 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/simd.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">load</span>(bytes: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, <span class="tok-kw">comptime</span> len: <span class="tok-type">u32</span>) T {</span>
<span class="line" id="L4"> <span class="tok-kw">const</span> mem = std.mem.bytesAsSlice(vectorInnerType(T), bytes);</span>
<span class="line" id="L5"> <span class="tok-kw">var</span> result: T = <span class="tok-builtin">@splat</span>(<span class="tok-builtin">@as</span>(vectorInnerType(T), <span class="tok-number">0</span>));</span>
<span class="line" id="L6"> <span class="tok-kw">const</span> vector_len = <span class="tok-kw">if</span> (len == <span class="tok-number">0</span>) vectorLength(T) <span class="tok-kw">else</span> len;</span>
<span class="line" id="L7"> <span class="tok-kw">comptime</span> <span class="tok-kw">var</span> i: <span class="tok-type">u32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L8"> <span class="tok-kw">inline</span> <span class="tok-kw">while</span> (i &lt; vector_len) : (i += <span class="tok-number">1</span>) {</span>
<span class="line" id="L9"> result[i] = mem[i];</span>
<span class="line" id="L10"> }</span>
<span class="line" id="L11"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L12">}</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"><span class="tok-kw">fn</span> <span class="tok-fn">vectorLength</span>(<span class="tok-kw">comptime</span> VectorType: <span class="tok-type">type</span>) <span class="tok-type">comptime_int</span> {</span>
<span class="line" id="L15"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(VectorType)) {</span>
<span class="line" id="L16"> .Vector =&gt; |info| info.len,</span>
<span class="line" id="L17"> .Array =&gt; |info| info.len,</span>
<span class="line" id="L18"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Invalid type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(VectorType)),</span>
<span class="line" id="L19"> };</span>
<span class="line" id="L20">}</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-kw">fn</span> <span class="tok-fn">vectorInnerType</span>(<span class="tok-kw">comptime</span> VectorType: <span class="tok-type">type</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L23"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(VectorType)) {</span>
<span class="line" id="L24"> .Vector =&gt; |info| info.child,</span>
<span class="line" id="L25"> .Array =&gt; |info| info.child,</span>
<span class="line" id="L26"> <span class="tok-kw">else</span> =&gt; <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Invalid type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(VectorType)),</span>
<span class="line" id="L27"> };</span>
<span class="line" id="L28">}</span>
<span class="line" id="L29"></span>
</code></pre></body>
</html>

View file

@ -1,295 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>src/utils.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">const</span> builtin = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;builtin&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L3"></span>
<span class="line" id="L4"><span class="tok-kw">const</span> native_endian = builtin.target.cpu.arch.endian();</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> StructReadError = <span class="tok-kw">error</span>{ EndOfStream, InvalidData } || std.io.StreamSource.ReadError;</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> StructWriteError = std.io.StreamSource.WriteError;</span>
<span class="line" id="L8"></span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">FixedStorage</span>(<span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, <span class="tok-kw">comptime</span> storage_size: <span class="tok-type">usize</span>) <span class="tok-type">type</span> {</span>
<span class="line" id="L10"> <span class="tok-kw">return</span> <span class="tok-kw">struct</span> {</span>
<span class="line" id="L11"> data: []T = &amp;.{},</span>
<span class="line" id="L12"> storage: [storage_size]T = <span class="tok-null">undefined</span>,</span>
<span class="line" id="L13"></span>
<span class="line" id="L14"> <span class="tok-kw">const</span> Self = <span class="tok-builtin">@This</span>();</span>
<span class="line" id="L15"></span>
<span class="line" id="L16"> <span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">resize</span>(self: *Self, size: <span class="tok-type">usize</span>) <span class="tok-type">void</span> {</span>
<span class="line" id="L17"> self.data = self.storage[<span class="tok-number">0</span>..size];</span>
<span class="line" id="L18"> }</span>
<span class="line" id="L19"> };</span>
<span class="line" id="L20">}</span>
<span class="line" id="L21"></span>
<span class="line" id="L22"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toMagicNumberNative</span>(magic: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">u32</span> {</span>
<span class="line" id="L23"> <span class="tok-kw">var</span> result: <span class="tok-type">u32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L24"> <span class="tok-kw">for</span> (magic, <span class="tok-number">0</span>..) |character, index| {</span>
<span class="line" id="L25"> result |= (<span class="tok-builtin">@as</span>(<span class="tok-type">u32</span>, character) &lt;&lt; <span class="tok-builtin">@intCast</span>((index * <span class="tok-number">8</span>)));</span>
<span class="line" id="L26"> }</span>
<span class="line" id="L27"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L28">}</span>
<span class="line" id="L29"></span>
<span class="line" id="L30"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">toMagicNumberForeign</span>(magic: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>) <span class="tok-type">u32</span> {</span>
<span class="line" id="L31"> <span class="tok-kw">var</span> result: <span class="tok-type">u32</span> = <span class="tok-number">0</span>;</span>
<span class="line" id="L32"> <span class="tok-kw">for</span> (magic, <span class="tok-number">0</span>..) |character, index| {</span>
<span class="line" id="L33"> result |= (<span class="tok-builtin">@as</span>(<span class="tok-type">u32</span>, character) &lt;&lt; <span class="tok-builtin">@intCast</span>((magic.len - <span class="tok-number">1</span> - index) * <span class="tok-number">8</span>));</span>
<span class="line" id="L34"> }</span>
<span class="line" id="L35"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L36">}</span>
<span class="line" id="L37"></span>
<span class="line" id="L38"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">toMagicNumber</span>(magic: []<span class="tok-kw">const</span> <span class="tok-type">u8</span>, <span class="tok-kw">comptime</span> wanted_endian: std.builtin.Endian) <span class="tok-type">u32</span> {</span>
<span class="line" id="L39"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (native_endian) {</span>
<span class="line" id="L40"> .little =&gt; {</span>
<span class="line" id="L41"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L42"> .little =&gt; toMagicNumberNative(magic),</span>
<span class="line" id="L43"> .big =&gt; toMagicNumberForeign(magic),</span>
<span class="line" id="L44"> };</span>
<span class="line" id="L45"> },</span>
<span class="line" id="L46"> .big =&gt; {</span>
<span class="line" id="L47"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L48"> .little =&gt; toMagicNumberForeign(magic),</span>
<span class="line" id="L49"> .big =&gt; toMagicNumberNative(magic),</span>
<span class="line" id="L50"> };</span>
<span class="line" id="L51"> },</span>
<span class="line" id="L52"> };</span>
<span class="line" id="L53">}</span>
<span class="line" id="L54"></span>
<span class="line" id="L55"><span class="tok-kw">fn</span> <span class="tok-fn">checkEnumFields</span>(data: <span class="tok-kw">anytype</span>) StructReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L56"> <span class="tok-kw">const</span> T = <span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(data)).Pointer.child;</span>
<span class="line" id="L57"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (std.meta.fields(T)) |entry| {</span>
<span class="line" id="L58"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(entry.<span class="tok-type">type</span>)) {</span>
<span class="line" id="L59"> .Enum =&gt; {</span>
<span class="line" id="L60"> <span class="tok-kw">const</span> value = <span class="tok-builtin">@intFromEnum</span>(<span class="tok-builtin">@field</span>(data, entry.name));</span>
<span class="line" id="L61"> _ = std.meta.intToEnum(entry.<span class="tok-type">type</span>, value) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> StructReadError.InvalidData;</span>
<span class="line" id="L62"> },</span>
<span class="line" id="L63"> .Struct =&gt; {</span>
<span class="line" id="L64"> <span class="tok-kw">try</span> checkEnumFields(&amp;<span class="tok-builtin">@field</span>(data, entry.name));</span>
<span class="line" id="L65"> },</span>
<span class="line" id="L66"> <span class="tok-kw">else</span> =&gt; {},</span>
<span class="line" id="L67"> }</span>
<span class="line" id="L68"> }</span>
<span class="line" id="L69">}</span>
<span class="line" id="L70"></span>
<span class="line" id="L71"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readStructNative</span>(reader: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>) StructReadError!T {</span>
<span class="line" id="L72"> <span class="tok-kw">var</span> result: T = <span class="tok-kw">try</span> reader.readStruct(T);</span>
<span class="line" id="L73"> <span class="tok-kw">try</span> checkEnumFields(&amp;result);</span>
<span class="line" id="L74"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L75">}</span>
<span class="line" id="L76"></span>
<span class="line" id="L77"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeStructNative</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-kw">anytype</span>) StructWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L78"> <span class="tok-kw">try</span> writer.writeStruct(value);</span>
<span class="line" id="L79">}</span>
<span class="line" id="L80"></span>
<span class="line" id="L81"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeStructForeign</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-kw">anytype</span>) StructWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L82"> <span class="tok-kw">const</span> T = <span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(value));</span>
<span class="line" id="L83"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (std.meta.fields(T)) |field| {</span>
<span class="line" id="L84"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(field.<span class="tok-type">type</span>)) {</span>
<span class="line" id="L85"> .Int =&gt; {</span>
<span class="line" id="L86"> <span class="tok-kw">try</span> writer.writeIntForeign(field.<span class="tok-type">type</span>, <span class="tok-builtin">@field</span>(value, field.name));</span>
<span class="line" id="L87"> },</span>
<span class="line" id="L88"> .Struct =&gt; {</span>
<span class="line" id="L89"> <span class="tok-kw">try</span> writeStructForeign(writer, <span class="tok-builtin">@field</span>(value, field.name));</span>
<span class="line" id="L90"> },</span>
<span class="line" id="L91"> .Enum =&gt; {</span>
<span class="line" id="L92"> <span class="tok-kw">const</span> enum_value = <span class="tok-builtin">@intFromEnum</span>(<span class="tok-builtin">@field</span>(value, field.name));</span>
<span class="line" id="L93"> <span class="tok-kw">try</span> writer.writeIntForeign(field.<span class="tok-type">type</span>, enum_value);</span>
<span class="line" id="L94"> },</span>
<span class="line" id="L95"> .Bool =&gt; {</span>
<span class="line" id="L96"> <span class="tok-kw">try</span> writer.writeByte(<span class="tok-builtin">@intFromBool</span>(<span class="tok-builtin">@field</span>(value, field.name)));</span>
<span class="line" id="L97"> },</span>
<span class="line" id="L98"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L99"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Add support for type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;.&quot;</span> ++ <span class="tok-builtin">@typeName</span>(field.<span class="tok-type">type</span>) ++ <span class="tok-str">&quot; in writeStructForeign()&quot;</span>);</span>
<span class="line" id="L100"> },</span>
<span class="line" id="L101"> }</span>
<span class="line" id="L102"> }</span>
<span class="line" id="L103">}</span>
<span class="line" id="L104"></span>
<span class="line" id="L105"><span class="tok-comment">// Extend std.mem.byteSwapAllFields to support enums</span>
</span>
<span class="line" id="L106"><span class="tok-kw">fn</span> <span class="tok-fn">swapFieldBytes</span>(data: <span class="tok-kw">anytype</span>) StructReadError!<span class="tok-type">void</span> {</span>
<span class="line" id="L107"> <span class="tok-kw">const</span> T = <span class="tok-builtin">@typeInfo</span>(<span class="tok-builtin">@TypeOf</span>(data)).Pointer.child;</span>
<span class="line" id="L108"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (std.meta.fields(T)) |entry| {</span>
<span class="line" id="L109"> <span class="tok-kw">switch</span> (<span class="tok-builtin">@typeInfo</span>(entry.<span class="tok-type">type</span>)) {</span>
<span class="line" id="L110"> .Int =&gt; |int| {</span>
<span class="line" id="L111"> <span class="tok-kw">if</span> (int.bits &gt; <span class="tok-number">8</span>) {</span>
<span class="line" id="L112"> <span class="tok-builtin">@field</span>(data, entry.name) = <span class="tok-builtin">@byteSwap</span>(<span class="tok-builtin">@field</span>(data, entry.name));</span>
<span class="line" id="L113"> }</span>
<span class="line" id="L114"> },</span>
<span class="line" id="L115"> .Struct =&gt; {</span>
<span class="line" id="L116"> <span class="tok-kw">try</span> swapFieldBytes(&amp;<span class="tok-builtin">@field</span>(data, entry.name));</span>
<span class="line" id="L117"> },</span>
<span class="line" id="L118"> .Enum =&gt; {</span>
<span class="line" id="L119"> <span class="tok-kw">const</span> value = <span class="tok-builtin">@intFromEnum</span>(<span class="tok-builtin">@field</span>(data, entry.name));</span>
<span class="line" id="L120"> <span class="tok-kw">if</span> (<span class="tok-builtin">@bitSizeOf</span>(<span class="tok-builtin">@TypeOf</span>(value)) &gt; <span class="tok-number">8</span>) {</span>
<span class="line" id="L121"> <span class="tok-builtin">@field</span>(data, entry.name) = <span class="tok-kw">try</span> std.meta.intToEnum(entry.<span class="tok-type">type</span>, <span class="tok-builtin">@byteSwap</span>(value));</span>
<span class="line" id="L122"> } <span class="tok-kw">else</span> {</span>
<span class="line" id="L123"> _ = std.meta.intToEnum(entry.<span class="tok-type">type</span>, value) <span class="tok-kw">catch</span> <span class="tok-kw">return</span> StructReadError.InvalidData;</span>
<span class="line" id="L124"> }</span>
<span class="line" id="L125"> },</span>
<span class="line" id="L126"> .Array =&gt; |array| {</span>
<span class="line" id="L127"> <span class="tok-kw">if</span> (array.child != <span class="tok-type">u8</span>) {</span>
<span class="line" id="L128"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Add support for type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;.&quot;</span> ++ <span class="tok-builtin">@typeName</span>(entry.<span class="tok-type">type</span>) ++ <span class="tok-str">&quot; in swapFieldBytes&quot;</span>);</span>
<span class="line" id="L129"> }</span>
<span class="line" id="L130"> },</span>
<span class="line" id="L131"> .Bool =&gt; {},</span>
<span class="line" id="L132"> <span class="tok-kw">else</span> =&gt; {</span>
<span class="line" id="L133"> <span class="tok-builtin">@compileError</span>(<span class="tok-str">&quot;Add support for type &quot;</span> ++ <span class="tok-builtin">@typeName</span>(T) ++ <span class="tok-str">&quot;.&quot;</span> ++ <span class="tok-builtin">@typeName</span>(entry.<span class="tok-type">type</span>) ++ <span class="tok-str">&quot; in swapFieldBytes&quot;</span>);</span>
<span class="line" id="L134"> },</span>
<span class="line" id="L135"> }</span>
<span class="line" id="L136"> }</span>
<span class="line" id="L137">}</span>
<span class="line" id="L138"></span>
<span class="line" id="L139"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">readStructForeign</span>(reader: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>) StructReadError!T {</span>
<span class="line" id="L140"> <span class="tok-kw">var</span> result: T = <span class="tok-kw">try</span> reader.readStruct(T);</span>
<span class="line" id="L141"> <span class="tok-kw">try</span> swapFieldBytes(&amp;result);</span>
<span class="line" id="L142"> <span class="tok-kw">return</span> result;</span>
<span class="line" id="L143">}</span>
<span class="line" id="L144"></span>
<span class="line" id="L145"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">readStruct</span>(reader: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> T: <span class="tok-type">type</span>, <span class="tok-kw">comptime</span> wanted_endian: std.builtin.Endian) StructReadError!T {</span>
<span class="line" id="L146"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (native_endian) {</span>
<span class="line" id="L147"> .little =&gt; {</span>
<span class="line" id="L148"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L149"> .little =&gt; readStructNative(reader, T),</span>
<span class="line" id="L150"> .big =&gt; readStructForeign(reader, T),</span>
<span class="line" id="L151"> };</span>
<span class="line" id="L152"> },</span>
<span class="line" id="L153"> .big =&gt; {</span>
<span class="line" id="L154"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L155"> .little =&gt; readStructForeign(reader, T),</span>
<span class="line" id="L156"> .big =&gt; readStructNative(reader, T),</span>
<span class="line" id="L157"> };</span>
<span class="line" id="L158"> },</span>
<span class="line" id="L159"> };</span>
<span class="line" id="L160">}</span>
<span class="line" id="L161"></span>
<span class="line" id="L162"><span class="tok-kw">pub</span> <span class="tok-kw">inline</span> <span class="tok-kw">fn</span> <span class="tok-fn">writeStruct</span>(writer: <span class="tok-kw">anytype</span>, value: <span class="tok-kw">anytype</span>, <span class="tok-kw">comptime</span> wanted_endian: std.builtin.Endian) StructWriteError!<span class="tok-type">void</span> {</span>
<span class="line" id="L163"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (native_endian) {</span>
<span class="line" id="L164"> .little =&gt; {</span>
<span class="line" id="L165"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L166"> .little =&gt; writeStructNative(writer, value),</span>
<span class="line" id="L167"> .big =&gt; writeStructForeign(writer, value),</span>
<span class="line" id="L168"> };</span>
<span class="line" id="L169"> },</span>
<span class="line" id="L170"> .big =&gt; {</span>
<span class="line" id="L171"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (wanted_endian) {</span>
<span class="line" id="L172"> .little =&gt; writeStructForeign(writer, value),</span>
<span class="line" id="L173"> .big =&gt; writeStructNative(writer, value),</span>
<span class="line" id="L174"> };</span>
<span class="line" id="L175"> },</span>
<span class="line" id="L176"> };</span>
<span class="line" id="L177">}</span>
<span class="line" id="L178"></span>
</code></pre></body>
</html>

View file

@ -1,156 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>zigimg.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> AllFormats = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/all.zig&quot;</span>);</span>
<span class="line" id="L2"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> bmp = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/bmp.zig&quot;</span>);</span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> color = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/color.zig&quot;</span>);</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> FormatInterface = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/FormatInterface.zig&quot;</span>);</span>
<span class="line" id="L5"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Image = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/Image.zig&quot;</span>);</span>
<span class="line" id="L6"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> gif = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/gif.zig&quot;</span>);</span>
<span class="line" id="L7"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> netpbm = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/netpbm.zig&quot;</span>);</span>
<span class="line" id="L8"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> OctTreeQuantizer = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/octree_quantizer.zig&quot;</span>).OctTreeQuantizer;</span>
<span class="line" id="L9"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> pcx = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/pcx.zig&quot;</span>);</span>
<span class="line" id="L10"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> PixelFormat = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/pixel_format.zig&quot;</span>).PixelFormat;</span>
<span class="line" id="L11"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> jpeg = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/jpeg.zig&quot;</span>);</span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> png = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/png.zig&quot;</span>);</span>
<span class="line" id="L13"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> qoi = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/qoi.zig&quot;</span>);</span>
<span class="line" id="L14"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> tga = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/tga.zig&quot;</span>);</span>
<span class="line" id="L15"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> pam = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/pam.zig&quot;</span>);</span>
<span class="line" id="L16"></span>
<span class="line" id="L17"><span class="tok-kw">test</span> {</span>
<span class="line" id="L18"> <span class="tok-kw">const</span> std = <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;std&quot;</span>);</span>
<span class="line" id="L19"> std.testing.refAllDecls(<span class="tok-builtin">@This</span>());</span>
<span class="line" id="L20"></span>
<span class="line" id="L21"> <span class="tok-kw">inline</span> <span class="tok-kw">for</span> (.{</span>
<span class="line" id="L22"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/compressions/lzw.zig&quot;</span>),</span>
<span class="line" id="L23"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;src/formats/png/reader.zig&quot;</span>),</span>
<span class="line" id="L24"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/buffered_stream_source_test.zig&quot;</span>),</span>
<span class="line" id="L25"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/color_test.zig&quot;</span>),</span>
<span class="line" id="L26"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/bmp_test.zig&quot;</span>),</span>
<span class="line" id="L27"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/gif_test.zig&quot;</span>),</span>
<span class="line" id="L28"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/jpeg_test.zig&quot;</span>),</span>
<span class="line" id="L29"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/netpbm_test.zig&quot;</span>),</span>
<span class="line" id="L30"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/pam_test.zig&quot;</span>),</span>
<span class="line" id="L31"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/pcx_test.zig&quot;</span>),</span>
<span class="line" id="L32"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/png_test.zig&quot;</span>),</span>
<span class="line" id="L33"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/qoi_test.zig&quot;</span>),</span>
<span class="line" id="L34"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/formats/tga_test.zig&quot;</span>),</span>
<span class="line" id="L35"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/image_test.zig&quot;</span>),</span>
<span class="line" id="L36"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/octree_quantizer_test.zig&quot;</span>),</span>
<span class="line" id="L37"> <span class="tok-builtin">@import</span>(<span class="tok-str">&quot;tests/pixel_format_test.zig&quot;</span>),</span>
<span class="line" id="L38"> }) |source_file| std.testing.refAllDeclsRecursive(source_file);</span>
<span class="line" id="L39">}</span>
<span class="line" id="L40"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,519 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>autogen/derived_combining_class.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Autogenerated from https://www.unicode.org/Public/15.0.0/ucd/</span>
</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-comment">// `combiningClass` maps the code point to its combining class value.</span>
</span>
<span class="line" id="L4"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">combiningClass</span>(cp: <span class="tok-type">u21</span>) <span class="tok-type">u8</span> {</span>
<span class="line" id="L5"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (cp) {</span>
<span class="line" id="L6"> <span class="tok-number">0x334</span>...<span class="tok-number">0x338</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L7"> <span class="tok-number">0x1CD4</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L8"> <span class="tok-number">0x1CE2</span>...<span class="tok-number">0x1CE8</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L9"> <span class="tok-number">0x20D2</span>...<span class="tok-number">0x20D3</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L10"> <span class="tok-number">0x20D8</span>...<span class="tok-number">0x20DA</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L11"> <span class="tok-number">0x20E5</span>...<span class="tok-number">0x20E6</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L12"> <span class="tok-number">0x20EA</span>...<span class="tok-number">0x20EB</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L13"> <span class="tok-number">0x10A39</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L14"> <span class="tok-number">0x16AF0</span>...<span class="tok-number">0x16AF4</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L15"> <span class="tok-number">0x1BC9E</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L16"> <span class="tok-number">0x1D167</span>...<span class="tok-number">0x1D169</span> =&gt; <span class="tok-number">1</span>,</span>
<span class="line" id="L17"> <span class="tok-number">0x16FF0</span>...<span class="tok-number">0x16FF1</span> =&gt; <span class="tok-number">6</span>,</span>
<span class="line" id="L18"> <span class="tok-number">0x93C</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L19"> <span class="tok-number">0x9BC</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L20"> <span class="tok-number">0xA3C</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L21"> <span class="tok-number">0xABC</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L22"> <span class="tok-number">0xB3C</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L23"> <span class="tok-number">0xC3C</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L24"> <span class="tok-number">0xCBC</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L25"> <span class="tok-number">0x1037</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L26"> <span class="tok-number">0x1B34</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L27"> <span class="tok-number">0x1BE6</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L28"> <span class="tok-number">0x1C37</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L29"> <span class="tok-number">0xA9B3</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L30"> <span class="tok-number">0x110BA</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L31"> <span class="tok-number">0x11173</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L32"> <span class="tok-number">0x111CA</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L33"> <span class="tok-number">0x11236</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L34"> <span class="tok-number">0x112E9</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L35"> <span class="tok-number">0x1133B</span>...<span class="tok-number">0x1133C</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L36"> <span class="tok-number">0x11446</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L37"> <span class="tok-number">0x114C3</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L38"> <span class="tok-number">0x115C0</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L39"> <span class="tok-number">0x116B7</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L40"> <span class="tok-number">0x1183A</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L41"> <span class="tok-number">0x11943</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L42"> <span class="tok-number">0x11D42</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L43"> <span class="tok-number">0x1E94A</span> =&gt; <span class="tok-number">7</span>,</span>
<span class="line" id="L44"> <span class="tok-number">0x3099</span>...<span class="tok-number">0x309A</span> =&gt; <span class="tok-number">8</span>,</span>
<span class="line" id="L45"> <span class="tok-number">0x94D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L46"> <span class="tok-number">0x9CD</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L47"> <span class="tok-number">0xA4D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L48"> <span class="tok-number">0xACD</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L49"> <span class="tok-number">0xB4D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L50"> <span class="tok-number">0xBCD</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L51"> <span class="tok-number">0xC4D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L52"> <span class="tok-number">0xCCD</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L53"> <span class="tok-number">0xD3B</span>...<span class="tok-number">0xD3C</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L54"> <span class="tok-number">0xD4D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L55"> <span class="tok-number">0xDCA</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L56"> <span class="tok-number">0xE3A</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L57"> <span class="tok-number">0xEBA</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L58"> <span class="tok-number">0xF84</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L59"> <span class="tok-number">0x1039</span>...<span class="tok-number">0x103A</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L60"> <span class="tok-number">0x1714</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L61"> <span class="tok-number">0x1715</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L62"> <span class="tok-number">0x1734</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L63"> <span class="tok-number">0x17D2</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L64"> <span class="tok-number">0x1A60</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L65"> <span class="tok-number">0x1B44</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L66"> <span class="tok-number">0x1BAA</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L67"> <span class="tok-number">0x1BAB</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L68"> <span class="tok-number">0x1BF2</span>...<span class="tok-number">0x1BF3</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L69"> <span class="tok-number">0x2D7F</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L70"> <span class="tok-number">0xA806</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L71"> <span class="tok-number">0xA82C</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L72"> <span class="tok-number">0xA8C4</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L73"> <span class="tok-number">0xA953</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L74"> <span class="tok-number">0xA9C0</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L75"> <span class="tok-number">0xAAF6</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L76"> <span class="tok-number">0xABED</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L77"> <span class="tok-number">0x10A3F</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L78"> <span class="tok-number">0x11046</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L79"> <span class="tok-number">0x11070</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L80"> <span class="tok-number">0x1107F</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L81"> <span class="tok-number">0x110B9</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L82"> <span class="tok-number">0x11133</span>...<span class="tok-number">0x11134</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L83"> <span class="tok-number">0x111C0</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L84"> <span class="tok-number">0x11235</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L85"> <span class="tok-number">0x112EA</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L86"> <span class="tok-number">0x1134D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L87"> <span class="tok-number">0x11442</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L88"> <span class="tok-number">0x114C2</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L89"> <span class="tok-number">0x115BF</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L90"> <span class="tok-number">0x1163F</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L91"> <span class="tok-number">0x116B6</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L92"> <span class="tok-number">0x1172B</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L93"> <span class="tok-number">0x11839</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L94"> <span class="tok-number">0x1193D</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L95"> <span class="tok-number">0x1193E</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L96"> <span class="tok-number">0x119E0</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L97"> <span class="tok-number">0x11A34</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L98"> <span class="tok-number">0x11A47</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L99"> <span class="tok-number">0x11A99</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L100"> <span class="tok-number">0x11C3F</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L101"> <span class="tok-number">0x11D44</span>...<span class="tok-number">0x11D45</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L102"> <span class="tok-number">0x11D97</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L103"> <span class="tok-number">0x11F41</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L104"> <span class="tok-number">0x11F42</span> =&gt; <span class="tok-number">9</span>,</span>
<span class="line" id="L105"> <span class="tok-number">0x5B0</span> =&gt; <span class="tok-number">10</span>,</span>
<span class="line" id="L106"> <span class="tok-number">0x5B1</span> =&gt; <span class="tok-number">11</span>,</span>
<span class="line" id="L107"> <span class="tok-number">0x5B2</span> =&gt; <span class="tok-number">12</span>,</span>
<span class="line" id="L108"> <span class="tok-number">0x5B3</span> =&gt; <span class="tok-number">13</span>,</span>
<span class="line" id="L109"> <span class="tok-number">0x5B4</span> =&gt; <span class="tok-number">14</span>,</span>
<span class="line" id="L110"> <span class="tok-number">0x5B5</span> =&gt; <span class="tok-number">15</span>,</span>
<span class="line" id="L111"> <span class="tok-number">0x5B6</span> =&gt; <span class="tok-number">16</span>,</span>
<span class="line" id="L112"> <span class="tok-number">0x5B7</span> =&gt; <span class="tok-number">17</span>,</span>
<span class="line" id="L113"> <span class="tok-number">0x5B8</span> =&gt; <span class="tok-number">18</span>,</span>
<span class="line" id="L114"> <span class="tok-number">0x5C7</span> =&gt; <span class="tok-number">18</span>,</span>
<span class="line" id="L115"> <span class="tok-number">0x5B9</span>...<span class="tok-number">0x5BA</span> =&gt; <span class="tok-number">19</span>,</span>
<span class="line" id="L116"> <span class="tok-number">0x5BB</span> =&gt; <span class="tok-number">20</span>,</span>
<span class="line" id="L117"> <span class="tok-number">0x5BC</span> =&gt; <span class="tok-number">21</span>,</span>
<span class="line" id="L118"> <span class="tok-number">0x5BD</span> =&gt; <span class="tok-number">22</span>,</span>
<span class="line" id="L119"> <span class="tok-number">0x5BF</span> =&gt; <span class="tok-number">23</span>,</span>
<span class="line" id="L120"> <span class="tok-number">0x5C1</span> =&gt; <span class="tok-number">24</span>,</span>
<span class="line" id="L121"> <span class="tok-number">0x5C2</span> =&gt; <span class="tok-number">25</span>,</span>
<span class="line" id="L122"> <span class="tok-number">0xFB1E</span> =&gt; <span class="tok-number">26</span>,</span>
<span class="line" id="L123"> <span class="tok-number">0x64B</span> =&gt; <span class="tok-number">27</span>,</span>
<span class="line" id="L124"> <span class="tok-number">0x8F0</span> =&gt; <span class="tok-number">27</span>,</span>
<span class="line" id="L125"> <span class="tok-number">0x64C</span> =&gt; <span class="tok-number">28</span>,</span>
<span class="line" id="L126"> <span class="tok-number">0x8F1</span> =&gt; <span class="tok-number">28</span>,</span>
<span class="line" id="L127"> <span class="tok-number">0x64D</span> =&gt; <span class="tok-number">29</span>,</span>
<span class="line" id="L128"> <span class="tok-number">0x8F2</span> =&gt; <span class="tok-number">29</span>,</span>
<span class="line" id="L129"> <span class="tok-number">0x618</span> =&gt; <span class="tok-number">30</span>,</span>
<span class="line" id="L130"> <span class="tok-number">0x64E</span> =&gt; <span class="tok-number">30</span>,</span>
<span class="line" id="L131"> <span class="tok-number">0x619</span> =&gt; <span class="tok-number">31</span>,</span>
<span class="line" id="L132"> <span class="tok-number">0x64F</span> =&gt; <span class="tok-number">31</span>,</span>
<span class="line" id="L133"> <span class="tok-number">0x61A</span> =&gt; <span class="tok-number">32</span>,</span>
<span class="line" id="L134"> <span class="tok-number">0x650</span> =&gt; <span class="tok-number">32</span>,</span>
<span class="line" id="L135"> <span class="tok-number">0x651</span> =&gt; <span class="tok-number">33</span>,</span>
<span class="line" id="L136"> <span class="tok-number">0x652</span> =&gt; <span class="tok-number">34</span>,</span>
<span class="line" id="L137"> <span class="tok-number">0x670</span> =&gt; <span class="tok-number">35</span>,</span>
<span class="line" id="L138"> <span class="tok-number">0x711</span> =&gt; <span class="tok-number">36</span>,</span>
<span class="line" id="L139"> <span class="tok-number">0xC55</span> =&gt; <span class="tok-number">84</span>,</span>
<span class="line" id="L140"> <span class="tok-number">0xC56</span> =&gt; <span class="tok-number">91</span>,</span>
<span class="line" id="L141"> <span class="tok-number">0xE38</span>...<span class="tok-number">0xE39</span> =&gt; <span class="tok-number">103</span>,</span>
<span class="line" id="L142"> <span class="tok-number">0xE48</span>...<span class="tok-number">0xE4B</span> =&gt; <span class="tok-number">107</span>,</span>
<span class="line" id="L143"> <span class="tok-number">0xEB8</span>...<span class="tok-number">0xEB9</span> =&gt; <span class="tok-number">118</span>,</span>
<span class="line" id="L144"> <span class="tok-number">0xEC8</span>...<span class="tok-number">0xECB</span> =&gt; <span class="tok-number">122</span>,</span>
<span class="line" id="L145"> <span class="tok-number">0xF71</span> =&gt; <span class="tok-number">129</span>,</span>
<span class="line" id="L146"> <span class="tok-number">0xF72</span> =&gt; <span class="tok-number">130</span>,</span>
<span class="line" id="L147"> <span class="tok-number">0xF7A</span>...<span class="tok-number">0xF7D</span> =&gt; <span class="tok-number">130</span>,</span>
<span class="line" id="L148"> <span class="tok-number">0xF80</span> =&gt; <span class="tok-number">130</span>,</span>
<span class="line" id="L149"> <span class="tok-number">0xF74</span> =&gt; <span class="tok-number">132</span>,</span>
<span class="line" id="L150"> <span class="tok-number">0x321</span>...<span class="tok-number">0x322</span> =&gt; <span class="tok-number">202</span>,</span>
<span class="line" id="L151"> <span class="tok-number">0x327</span>...<span class="tok-number">0x328</span> =&gt; <span class="tok-number">202</span>,</span>
<span class="line" id="L152"> <span class="tok-number">0x1DD0</span> =&gt; <span class="tok-number">202</span>,</span>
<span class="line" id="L153"> <span class="tok-number">0x1DCE</span> =&gt; <span class="tok-number">214</span>,</span>
<span class="line" id="L154"> <span class="tok-number">0x31B</span> =&gt; <span class="tok-number">216</span>,</span>
<span class="line" id="L155"> <span class="tok-number">0xF39</span> =&gt; <span class="tok-number">216</span>,</span>
<span class="line" id="L156"> <span class="tok-number">0x1D165</span>...<span class="tok-number">0x1D166</span> =&gt; <span class="tok-number">216</span>,</span>
<span class="line" id="L157"> <span class="tok-number">0x1D16E</span>...<span class="tok-number">0x1D172</span> =&gt; <span class="tok-number">216</span>,</span>
<span class="line" id="L158"> <span class="tok-number">0x1DFA</span> =&gt; <span class="tok-number">218</span>,</span>
<span class="line" id="L159"> <span class="tok-number">0x302A</span> =&gt; <span class="tok-number">218</span>,</span>
<span class="line" id="L160"> <span class="tok-number">0x316</span>...<span class="tok-number">0x319</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L161"> <span class="tok-number">0x31C</span>...<span class="tok-number">0x320</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L162"> <span class="tok-number">0x323</span>...<span class="tok-number">0x326</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L163"> <span class="tok-number">0x329</span>...<span class="tok-number">0x333</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L164"> <span class="tok-number">0x339</span>...<span class="tok-number">0x33C</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L165"> <span class="tok-number">0x347</span>...<span class="tok-number">0x349</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L166"> <span class="tok-number">0x34D</span>...<span class="tok-number">0x34E</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L167"> <span class="tok-number">0x353</span>...<span class="tok-number">0x356</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L168"> <span class="tok-number">0x359</span>...<span class="tok-number">0x35A</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L169"> <span class="tok-number">0x591</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L170"> <span class="tok-number">0x596</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L171"> <span class="tok-number">0x59B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L172"> <span class="tok-number">0x5A2</span>...<span class="tok-number">0x5A7</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L173"> <span class="tok-number">0x5AA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L174"> <span class="tok-number">0x5C5</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L175"> <span class="tok-number">0x655</span>...<span class="tok-number">0x656</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L176"> <span class="tok-number">0x65C</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L177"> <span class="tok-number">0x65F</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L178"> <span class="tok-number">0x6E3</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L179"> <span class="tok-number">0x6EA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L180"> <span class="tok-number">0x6ED</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L181"> <span class="tok-number">0x731</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L182"> <span class="tok-number">0x734</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L183"> <span class="tok-number">0x737</span>...<span class="tok-number">0x739</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L184"> <span class="tok-number">0x73B</span>...<span class="tok-number">0x73C</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L185"> <span class="tok-number">0x73E</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L186"> <span class="tok-number">0x742</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L187"> <span class="tok-number">0x744</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L188"> <span class="tok-number">0x746</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L189"> <span class="tok-number">0x748</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L190"> <span class="tok-number">0x7F2</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L191"> <span class="tok-number">0x7FD</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L192"> <span class="tok-number">0x859</span>...<span class="tok-number">0x85B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L193"> <span class="tok-number">0x899</span>...<span class="tok-number">0x89B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L194"> <span class="tok-number">0x8CF</span>...<span class="tok-number">0x8D3</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L195"> <span class="tok-number">0x8E3</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L196"> <span class="tok-number">0x8E6</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L197"> <span class="tok-number">0x8E9</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L198"> <span class="tok-number">0x8ED</span>...<span class="tok-number">0x8EF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L199"> <span class="tok-number">0x8F6</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L200"> <span class="tok-number">0x8F9</span>...<span class="tok-number">0x8FA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L201"> <span class="tok-number">0x952</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L202"> <span class="tok-number">0xF18</span>...<span class="tok-number">0xF19</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L203"> <span class="tok-number">0xF35</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L204"> <span class="tok-number">0xF37</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L205"> <span class="tok-number">0xFC6</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L206"> <span class="tok-number">0x108D</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L207"> <span class="tok-number">0x193B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L208"> <span class="tok-number">0x1A18</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L209"> <span class="tok-number">0x1A7F</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L210"> <span class="tok-number">0x1AB5</span>...<span class="tok-number">0x1ABA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L211"> <span class="tok-number">0x1ABD</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L212"> <span class="tok-number">0x1ABF</span>...<span class="tok-number">0x1AC0</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L213"> <span class="tok-number">0x1AC3</span>...<span class="tok-number">0x1AC4</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L214"> <span class="tok-number">0x1ACA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L215"> <span class="tok-number">0x1B6C</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L216"> <span class="tok-number">0x1CD5</span>...<span class="tok-number">0x1CD9</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L217"> <span class="tok-number">0x1CDC</span>...<span class="tok-number">0x1CDF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L218"> <span class="tok-number">0x1CED</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L219"> <span class="tok-number">0x1DC2</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L220"> <span class="tok-number">0x1DCA</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L221"> <span class="tok-number">0x1DCF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L222"> <span class="tok-number">0x1DF9</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L223"> <span class="tok-number">0x1DFD</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L224"> <span class="tok-number">0x1DFF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L225"> <span class="tok-number">0x20E8</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L226"> <span class="tok-number">0x20EC</span>...<span class="tok-number">0x20EF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L227"> <span class="tok-number">0xA92B</span>...<span class="tok-number">0xA92D</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L228"> <span class="tok-number">0xAAB4</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L229"> <span class="tok-number">0xFE27</span>...<span class="tok-number">0xFE2D</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L230"> <span class="tok-number">0x101FD</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L231"> <span class="tok-number">0x102E0</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L232"> <span class="tok-number">0x10A0D</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L233"> <span class="tok-number">0x10A3A</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L234"> <span class="tok-number">0x10AE6</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L235"> <span class="tok-number">0x10EFD</span>...<span class="tok-number">0x10EFF</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L236"> <span class="tok-number">0x10F46</span>...<span class="tok-number">0x10F47</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L237"> <span class="tok-number">0x10F4B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L238"> <span class="tok-number">0x10F4D</span>...<span class="tok-number">0x10F50</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L239"> <span class="tok-number">0x10F83</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L240"> <span class="tok-number">0x10F85</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L241"> <span class="tok-number">0x1D17B</span>...<span class="tok-number">0x1D182</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L242"> <span class="tok-number">0x1D18A</span>...<span class="tok-number">0x1D18B</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L243"> <span class="tok-number">0x1E4EE</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L244"> <span class="tok-number">0x1E8D0</span>...<span class="tok-number">0x1E8D6</span> =&gt; <span class="tok-number">220</span>,</span>
<span class="line" id="L245"> <span class="tok-number">0x59A</span> =&gt; <span class="tok-number">222</span>,</span>
<span class="line" id="L246"> <span class="tok-number">0x5AD</span> =&gt; <span class="tok-number">222</span>,</span>
<span class="line" id="L247"> <span class="tok-number">0x1939</span> =&gt; <span class="tok-number">222</span>,</span>
<span class="line" id="L248"> <span class="tok-number">0x302D</span> =&gt; <span class="tok-number">222</span>,</span>
<span class="line" id="L249"> <span class="tok-number">0x302E</span>...<span class="tok-number">0x302F</span> =&gt; <span class="tok-number">224</span>,</span>
<span class="line" id="L250"> <span class="tok-number">0x1D16D</span> =&gt; <span class="tok-number">226</span>,</span>
<span class="line" id="L251"> <span class="tok-number">0x5AE</span> =&gt; <span class="tok-number">228</span>,</span>
<span class="line" id="L252"> <span class="tok-number">0x18A9</span> =&gt; <span class="tok-number">228</span>,</span>
<span class="line" id="L253"> <span class="tok-number">0x1DF7</span>...<span class="tok-number">0x1DF8</span> =&gt; <span class="tok-number">228</span>,</span>
<span class="line" id="L254"> <span class="tok-number">0x302B</span> =&gt; <span class="tok-number">228</span>,</span>
<span class="line" id="L255"> <span class="tok-number">0x300</span>...<span class="tok-number">0x314</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L256"> <span class="tok-number">0x33D</span>...<span class="tok-number">0x344</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L257"> <span class="tok-number">0x346</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L258"> <span class="tok-number">0x34A</span>...<span class="tok-number">0x34C</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L259"> <span class="tok-number">0x350</span>...<span class="tok-number">0x352</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L260"> <span class="tok-number">0x357</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L261"> <span class="tok-number">0x35B</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L262"> <span class="tok-number">0x363</span>...<span class="tok-number">0x36F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L263"> <span class="tok-number">0x483</span>...<span class="tok-number">0x487</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L264"> <span class="tok-number">0x592</span>...<span class="tok-number">0x595</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L265"> <span class="tok-number">0x597</span>...<span class="tok-number">0x599</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L266"> <span class="tok-number">0x59C</span>...<span class="tok-number">0x5A1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L267"> <span class="tok-number">0x5A8</span>...<span class="tok-number">0x5A9</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L268"> <span class="tok-number">0x5AB</span>...<span class="tok-number">0x5AC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L269"> <span class="tok-number">0x5AF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L270"> <span class="tok-number">0x5C4</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L271"> <span class="tok-number">0x610</span>...<span class="tok-number">0x617</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L272"> <span class="tok-number">0x653</span>...<span class="tok-number">0x654</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L273"> <span class="tok-number">0x657</span>...<span class="tok-number">0x65B</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L274"> <span class="tok-number">0x65D</span>...<span class="tok-number">0x65E</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L275"> <span class="tok-number">0x6D6</span>...<span class="tok-number">0x6DC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L276"> <span class="tok-number">0x6DF</span>...<span class="tok-number">0x6E2</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L277"> <span class="tok-number">0x6E4</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L278"> <span class="tok-number">0x6E7</span>...<span class="tok-number">0x6E8</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L279"> <span class="tok-number">0x6EB</span>...<span class="tok-number">0x6EC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L280"> <span class="tok-number">0x730</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L281"> <span class="tok-number">0x732</span>...<span class="tok-number">0x733</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L282"> <span class="tok-number">0x735</span>...<span class="tok-number">0x736</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L283"> <span class="tok-number">0x73A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L284"> <span class="tok-number">0x73D</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L285"> <span class="tok-number">0x73F</span>...<span class="tok-number">0x741</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L286"> <span class="tok-number">0x743</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L287"> <span class="tok-number">0x745</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L288"> <span class="tok-number">0x747</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L289"> <span class="tok-number">0x749</span>...<span class="tok-number">0x74A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L290"> <span class="tok-number">0x7EB</span>...<span class="tok-number">0x7F1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L291"> <span class="tok-number">0x7F3</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L292"> <span class="tok-number">0x816</span>...<span class="tok-number">0x819</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L293"> <span class="tok-number">0x81B</span>...<span class="tok-number">0x823</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L294"> <span class="tok-number">0x825</span>...<span class="tok-number">0x827</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L295"> <span class="tok-number">0x829</span>...<span class="tok-number">0x82D</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L296"> <span class="tok-number">0x898</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L297"> <span class="tok-number">0x89C</span>...<span class="tok-number">0x89F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L298"> <span class="tok-number">0x8CA</span>...<span class="tok-number">0x8CE</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L299"> <span class="tok-number">0x8D4</span>...<span class="tok-number">0x8E1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L300"> <span class="tok-number">0x8E4</span>...<span class="tok-number">0x8E5</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L301"> <span class="tok-number">0x8E7</span>...<span class="tok-number">0x8E8</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L302"> <span class="tok-number">0x8EA</span>...<span class="tok-number">0x8EC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L303"> <span class="tok-number">0x8F3</span>...<span class="tok-number">0x8F5</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L304"> <span class="tok-number">0x8F7</span>...<span class="tok-number">0x8F8</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L305"> <span class="tok-number">0x8FB</span>...<span class="tok-number">0x8FF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L306"> <span class="tok-number">0x951</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L307"> <span class="tok-number">0x953</span>...<span class="tok-number">0x954</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L308"> <span class="tok-number">0x9FE</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L309"> <span class="tok-number">0xF82</span>...<span class="tok-number">0xF83</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L310"> <span class="tok-number">0xF86</span>...<span class="tok-number">0xF87</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L311"> <span class="tok-number">0x135D</span>...<span class="tok-number">0x135F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L312"> <span class="tok-number">0x17DD</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L313"> <span class="tok-number">0x193A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L314"> <span class="tok-number">0x1A17</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L315"> <span class="tok-number">0x1A75</span>...<span class="tok-number">0x1A7C</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L316"> <span class="tok-number">0x1AB0</span>...<span class="tok-number">0x1AB4</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L317"> <span class="tok-number">0x1ABB</span>...<span class="tok-number">0x1ABC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L318"> <span class="tok-number">0x1AC1</span>...<span class="tok-number">0x1AC2</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L319"> <span class="tok-number">0x1AC5</span>...<span class="tok-number">0x1AC9</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L320"> <span class="tok-number">0x1ACB</span>...<span class="tok-number">0x1ACE</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L321"> <span class="tok-number">0x1B6B</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L322"> <span class="tok-number">0x1B6D</span>...<span class="tok-number">0x1B73</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L323"> <span class="tok-number">0x1CD0</span>...<span class="tok-number">0x1CD2</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L324"> <span class="tok-number">0x1CDA</span>...<span class="tok-number">0x1CDB</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L325"> <span class="tok-number">0x1CE0</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L326"> <span class="tok-number">0x1CF4</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L327"> <span class="tok-number">0x1CF8</span>...<span class="tok-number">0x1CF9</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L328"> <span class="tok-number">0x1DC0</span>...<span class="tok-number">0x1DC1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L329"> <span class="tok-number">0x1DC3</span>...<span class="tok-number">0x1DC9</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L330"> <span class="tok-number">0x1DCB</span>...<span class="tok-number">0x1DCC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L331"> <span class="tok-number">0x1DD1</span>...<span class="tok-number">0x1DF5</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L332"> <span class="tok-number">0x1DFB</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L333"> <span class="tok-number">0x1DFE</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L334"> <span class="tok-number">0x20D0</span>...<span class="tok-number">0x20D1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L335"> <span class="tok-number">0x20D4</span>...<span class="tok-number">0x20D7</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L336"> <span class="tok-number">0x20DB</span>...<span class="tok-number">0x20DC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L337"> <span class="tok-number">0x20E1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L338"> <span class="tok-number">0x20E7</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L339"> <span class="tok-number">0x20E9</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L340"> <span class="tok-number">0x20F0</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L341"> <span class="tok-number">0x2CEF</span>...<span class="tok-number">0x2CF1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L342"> <span class="tok-number">0x2DE0</span>...<span class="tok-number">0x2DFF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L343"> <span class="tok-number">0xA66F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L344"> <span class="tok-number">0xA674</span>...<span class="tok-number">0xA67D</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L345"> <span class="tok-number">0xA69E</span>...<span class="tok-number">0xA69F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L346"> <span class="tok-number">0xA6F0</span>...<span class="tok-number">0xA6F1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L347"> <span class="tok-number">0xA8E0</span>...<span class="tok-number">0xA8F1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L348"> <span class="tok-number">0xAAB0</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L349"> <span class="tok-number">0xAAB2</span>...<span class="tok-number">0xAAB3</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L350"> <span class="tok-number">0xAAB7</span>...<span class="tok-number">0xAAB8</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L351"> <span class="tok-number">0xAABE</span>...<span class="tok-number">0xAABF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L352"> <span class="tok-number">0xAAC1</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L353"> <span class="tok-number">0xFE20</span>...<span class="tok-number">0xFE26</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L354"> <span class="tok-number">0xFE2E</span>...<span class="tok-number">0xFE2F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L355"> <span class="tok-number">0x10376</span>...<span class="tok-number">0x1037A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L356"> <span class="tok-number">0x10A0F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L357"> <span class="tok-number">0x10A38</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L358"> <span class="tok-number">0x10AE5</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L359"> <span class="tok-number">0x10D24</span>...<span class="tok-number">0x10D27</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L360"> <span class="tok-number">0x10EAB</span>...<span class="tok-number">0x10EAC</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L361"> <span class="tok-number">0x10F48</span>...<span class="tok-number">0x10F4A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L362"> <span class="tok-number">0x10F4C</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L363"> <span class="tok-number">0x10F82</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L364"> <span class="tok-number">0x10F84</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L365"> <span class="tok-number">0x11100</span>...<span class="tok-number">0x11102</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L366"> <span class="tok-number">0x11366</span>...<span class="tok-number">0x1136C</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L367"> <span class="tok-number">0x11370</span>...<span class="tok-number">0x11374</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L368"> <span class="tok-number">0x1145E</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L369"> <span class="tok-number">0x16B30</span>...<span class="tok-number">0x16B36</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L370"> <span class="tok-number">0x1D185</span>...<span class="tok-number">0x1D189</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L371"> <span class="tok-number">0x1D1AA</span>...<span class="tok-number">0x1D1AD</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L372"> <span class="tok-number">0x1D242</span>...<span class="tok-number">0x1D244</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L373"> <span class="tok-number">0x1E000</span>...<span class="tok-number">0x1E006</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L374"> <span class="tok-number">0x1E008</span>...<span class="tok-number">0x1E018</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L375"> <span class="tok-number">0x1E01B</span>...<span class="tok-number">0x1E021</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L376"> <span class="tok-number">0x1E023</span>...<span class="tok-number">0x1E024</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L377"> <span class="tok-number">0x1E026</span>...<span class="tok-number">0x1E02A</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L378"> <span class="tok-number">0x1E08F</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L379"> <span class="tok-number">0x1E130</span>...<span class="tok-number">0x1E136</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L380"> <span class="tok-number">0x1E2AE</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L381"> <span class="tok-number">0x1E2EC</span>...<span class="tok-number">0x1E2EF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L382"> <span class="tok-number">0x1E4EF</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L383"> <span class="tok-number">0x1E944</span>...<span class="tok-number">0x1E949</span> =&gt; <span class="tok-number">230</span>,</span>
<span class="line" id="L384"> <span class="tok-number">0x315</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L385"> <span class="tok-number">0x31A</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L386"> <span class="tok-number">0x358</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L387"> <span class="tok-number">0x1DF6</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L388"> <span class="tok-number">0x302C</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L389"> <span class="tok-number">0x1E4EC</span>...<span class="tok-number">0x1E4ED</span> =&gt; <span class="tok-number">232</span>,</span>
<span class="line" id="L390"> <span class="tok-number">0x35C</span> =&gt; <span class="tok-number">233</span>,</span>
<span class="line" id="L391"> <span class="tok-number">0x35F</span> =&gt; <span class="tok-number">233</span>,</span>
<span class="line" id="L392"> <span class="tok-number">0x362</span> =&gt; <span class="tok-number">233</span>,</span>
<span class="line" id="L393"> <span class="tok-number">0x1DFC</span> =&gt; <span class="tok-number">233</span>,</span>
<span class="line" id="L394"> <span class="tok-number">0x35D</span>...<span class="tok-number">0x35E</span> =&gt; <span class="tok-number">234</span>,</span>
<span class="line" id="L395"> <span class="tok-number">0x360</span>...<span class="tok-number">0x361</span> =&gt; <span class="tok-number">234</span>,</span>
<span class="line" id="L396"> <span class="tok-number">0x1DCD</span> =&gt; <span class="tok-number">234</span>,</span>
<span class="line" id="L397"> <span class="tok-number">0x345</span> =&gt; <span class="tok-number">240</span>,</span>
<span class="line" id="L398"> <span class="tok-kw">else</span> =&gt; <span class="tok-number">0</span>,</span>
<span class="line" id="L399"> };</span>
<span class="line" id="L400">}</span>
<span class="line" id="L401"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,382 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>autogen/derived_numeric_type.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Autogenerated from https://www.unicode.org/Public/15.0.0/ucd/</span>
</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isNumeric</span>(cp: <span class="tok-type">u21</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L4"> <span class="tok-kw">if</span> (cp &lt; <span class="tok-number">0xbc</span> <span class="tok-kw">or</span> cp &gt; <span class="tok-number">0x2f890</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L5"></span>
<span class="line" id="L6"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (cp) {</span>
<span class="line" id="L7"> <span class="tok-number">0xbc</span>...<span class="tok-number">0xbe</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L8"> <span class="tok-number">0x9f4</span>...<span class="tok-number">0x9f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L9"> <span class="tok-number">0xb72</span>...<span class="tok-number">0xb77</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L10"> <span class="tok-number">0xbf0</span>...<span class="tok-number">0xbf2</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L11"> <span class="tok-number">0xc78</span>...<span class="tok-number">0xc7e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L12"> <span class="tok-number">0xd58</span>...<span class="tok-number">0xd5e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L13"> <span class="tok-number">0xd70</span>...<span class="tok-number">0xd78</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L14"> <span class="tok-number">0xf2a</span>...<span class="tok-number">0xf33</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L15"> <span class="tok-number">0x1372</span>...<span class="tok-number">0x137c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L16"> <span class="tok-number">0x16ee</span>...<span class="tok-number">0x16f0</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L17"> <span class="tok-number">0x17f0</span>...<span class="tok-number">0x17f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L18"> <span class="tok-number">0x2150</span>...<span class="tok-number">0x215f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L19"> <span class="tok-number">0x2160</span>...<span class="tok-number">0x2182</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L20"> <span class="tok-number">0x2185</span>...<span class="tok-number">0x2188</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L21"> <span class="tok-number">0x2189</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L22"> <span class="tok-number">0x2469</span>...<span class="tok-number">0x2473</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L23"> <span class="tok-number">0x247d</span>...<span class="tok-number">0x2487</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L24"> <span class="tok-number">0x2491</span>...<span class="tok-number">0x249b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L25"> <span class="tok-number">0x24eb</span>...<span class="tok-number">0x24f4</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L26"> <span class="tok-number">0x24fe</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L27"> <span class="tok-number">0x277f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L28"> <span class="tok-number">0x2789</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L29"> <span class="tok-number">0x2793</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L30"> <span class="tok-number">0x2cfd</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L31"> <span class="tok-number">0x3007</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L32"> <span class="tok-number">0x3021</span>...<span class="tok-number">0x3029</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L33"> <span class="tok-number">0x3038</span>...<span class="tok-number">0x303a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L34"> <span class="tok-number">0x3192</span>...<span class="tok-number">0x3195</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L35"> <span class="tok-number">0x3220</span>...<span class="tok-number">0x3229</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L36"> <span class="tok-number">0x3248</span>...<span class="tok-number">0x324f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L37"> <span class="tok-number">0x3251</span>...<span class="tok-number">0x325f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L38"> <span class="tok-number">0x3280</span>...<span class="tok-number">0x3289</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L39"> <span class="tok-number">0x32b1</span>...<span class="tok-number">0x32bf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L40"> <span class="tok-number">0x3405</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L41"> <span class="tok-number">0x3483</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L42"> <span class="tok-number">0x382a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L43"> <span class="tok-number">0x3b4d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L44"> <span class="tok-number">0x4e00</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L45"> <span class="tok-number">0x4e03</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L46"> <span class="tok-number">0x4e07</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L47"> <span class="tok-number">0x4e09</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L48"> <span class="tok-number">0x4e5d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L49"> <span class="tok-number">0x4e8c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L50"> <span class="tok-number">0x4e94</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L51"> <span class="tok-number">0x4e96</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L52"> <span class="tok-number">0x4ebf</span>...<span class="tok-number">0x4ec0</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L53"> <span class="tok-number">0x4edf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L54"> <span class="tok-number">0x4ee8</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L55"> <span class="tok-number">0x4f0d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L56"> <span class="tok-number">0x4f70</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L57"> <span class="tok-number">0x5104</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L58"> <span class="tok-number">0x5146</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L59"> <span class="tok-number">0x5169</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L60"> <span class="tok-number">0x516b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L61"> <span class="tok-number">0x516d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L62"> <span class="tok-number">0x5341</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L63"> <span class="tok-number">0x5343</span>...<span class="tok-number">0x5345</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L64"> <span class="tok-number">0x534c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L65"> <span class="tok-number">0x53c1</span>...<span class="tok-number">0x53c4</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L66"> <span class="tok-number">0x56db</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L67"> <span class="tok-number">0x58f1</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L68"> <span class="tok-number">0x58f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L69"> <span class="tok-number">0x5e7a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L70"> <span class="tok-number">0x5efe</span>...<span class="tok-number">0x5eff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L71"> <span class="tok-number">0x5f0c</span>...<span class="tok-number">0x5f0e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L72"> <span class="tok-number">0x5f10</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L73"> <span class="tok-number">0x62fe</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L74"> <span class="tok-number">0x634c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L75"> <span class="tok-number">0x67d2</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L76"> <span class="tok-number">0x6f06</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L77"> <span class="tok-number">0x7396</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L78"> <span class="tok-number">0x767e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L79"> <span class="tok-number">0x8086</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L80"> <span class="tok-number">0x842c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L81"> <span class="tok-number">0x8cae</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L82"> <span class="tok-number">0x8cb3</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L83"> <span class="tok-number">0x8d30</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L84"> <span class="tok-number">0x9621</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L85"> <span class="tok-number">0x9646</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L86"> <span class="tok-number">0x964c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L87"> <span class="tok-number">0x9678</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L88"> <span class="tok-number">0x96f6</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L89"> <span class="tok-number">0xa6e6</span>...<span class="tok-number">0xa6ef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L90"> <span class="tok-number">0xa830</span>...<span class="tok-number">0xa835</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L91"> <span class="tok-number">0xf96b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L92"> <span class="tok-number">0xf973</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L93"> <span class="tok-number">0xf978</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L94"> <span class="tok-number">0xf9b2</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L95"> <span class="tok-number">0xf9d1</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L96"> <span class="tok-number">0xf9d3</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L97"> <span class="tok-number">0xf9fd</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L98"> <span class="tok-number">0x10107</span>...<span class="tok-number">0x10133</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L99"> <span class="tok-number">0x10140</span>...<span class="tok-number">0x10174</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L100"> <span class="tok-number">0x10175</span>...<span class="tok-number">0x10178</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L101"> <span class="tok-number">0x1018a</span>...<span class="tok-number">0x1018b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L102"> <span class="tok-number">0x102e1</span>...<span class="tok-number">0x102fb</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L103"> <span class="tok-number">0x10320</span>...<span class="tok-number">0x10323</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L104"> <span class="tok-number">0x10341</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L105"> <span class="tok-number">0x1034a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L106"> <span class="tok-number">0x103d1</span>...<span class="tok-number">0x103d5</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L107"> <span class="tok-number">0x10858</span>...<span class="tok-number">0x1085f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L108"> <span class="tok-number">0x10879</span>...<span class="tok-number">0x1087f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L109"> <span class="tok-number">0x108a7</span>...<span class="tok-number">0x108af</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L110"> <span class="tok-number">0x108fb</span>...<span class="tok-number">0x108ff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L111"> <span class="tok-number">0x10916</span>...<span class="tok-number">0x1091b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L112"> <span class="tok-number">0x109bc</span>...<span class="tok-number">0x109bd</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L113"> <span class="tok-number">0x109c0</span>...<span class="tok-number">0x109cf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L114"> <span class="tok-number">0x109d2</span>...<span class="tok-number">0x109ff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L115"> <span class="tok-number">0x10a44</span>...<span class="tok-number">0x10a48</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L116"> <span class="tok-number">0x10a7d</span>...<span class="tok-number">0x10a7e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L117"> <span class="tok-number">0x10a9d</span>...<span class="tok-number">0x10a9f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L118"> <span class="tok-number">0x10aeb</span>...<span class="tok-number">0x10aef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L119"> <span class="tok-number">0x10b58</span>...<span class="tok-number">0x10b5f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L120"> <span class="tok-number">0x10b78</span>...<span class="tok-number">0x10b7f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L121"> <span class="tok-number">0x10ba9</span>...<span class="tok-number">0x10baf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L122"> <span class="tok-number">0x10cfa</span>...<span class="tok-number">0x10cff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L123"> <span class="tok-number">0x10e69</span>...<span class="tok-number">0x10e7e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L124"> <span class="tok-number">0x10f1d</span>...<span class="tok-number">0x10f26</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L125"> <span class="tok-number">0x10f51</span>...<span class="tok-number">0x10f54</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L126"> <span class="tok-number">0x10fc5</span>...<span class="tok-number">0x10fcb</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L127"> <span class="tok-number">0x1105b</span>...<span class="tok-number">0x11065</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L128"> <span class="tok-number">0x111e1</span>...<span class="tok-number">0x111f4</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L129"> <span class="tok-number">0x1173a</span>...<span class="tok-number">0x1173b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L130"> <span class="tok-number">0x118ea</span>...<span class="tok-number">0x118f2</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L131"> <span class="tok-number">0x11c5a</span>...<span class="tok-number">0x11c6c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L132"> <span class="tok-number">0x11fc0</span>...<span class="tok-number">0x11fd4</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L133"> <span class="tok-number">0x12400</span>...<span class="tok-number">0x1246e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L134"> <span class="tok-number">0x16b5b</span>...<span class="tok-number">0x16b61</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L135"> <span class="tok-number">0x16e80</span>...<span class="tok-number">0x16e96</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L136"> <span class="tok-number">0x1d2c0</span>...<span class="tok-number">0x1d2d3</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L137"> <span class="tok-number">0x1d2e0</span>...<span class="tok-number">0x1d2f3</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L138"> <span class="tok-number">0x1d360</span>...<span class="tok-number">0x1d378</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L139"> <span class="tok-number">0x1e8c7</span>...<span class="tok-number">0x1e8cf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L140"> <span class="tok-number">0x1ec71</span>...<span class="tok-number">0x1ecab</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L141"> <span class="tok-number">0x1ecad</span>...<span class="tok-number">0x1ecaf</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L142"> <span class="tok-number">0x1ecb1</span>...<span class="tok-number">0x1ecb4</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L143"> <span class="tok-number">0x1ed01</span>...<span class="tok-number">0x1ed2d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L144"> <span class="tok-number">0x1ed2f</span>...<span class="tok-number">0x1ed3d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L145"> <span class="tok-number">0x1f10b</span>...<span class="tok-number">0x1f10c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L146"> <span class="tok-number">0x20001</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L147"> <span class="tok-number">0x20064</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L148"> <span class="tok-number">0x200e2</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L149"> <span class="tok-number">0x20121</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L150"> <span class="tok-number">0x2092a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L151"> <span class="tok-number">0x20983</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L152"> <span class="tok-number">0x2098c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L153"> <span class="tok-number">0x2099c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L154"> <span class="tok-number">0x20aea</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L155"> <span class="tok-number">0x20afd</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L156"> <span class="tok-number">0x20b19</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L157"> <span class="tok-number">0x22390</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L158"> <span class="tok-number">0x22998</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L159"> <span class="tok-number">0x23b1b</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L160"> <span class="tok-number">0x2626d</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L161"> <span class="tok-number">0x2f890</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L162"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L163"> };</span>
<span class="line" id="L164">}</span>
<span class="line" id="L165"></span>
<span class="line" id="L166"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isDigit</span>(cp: <span class="tok-type">u21</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L167"> <span class="tok-kw">if</span> (cp &lt; <span class="tok-number">0xb2</span> <span class="tok-kw">or</span> cp &gt; <span class="tok-number">0x1f10a</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L168"></span>
<span class="line" id="L169"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (cp) {</span>
<span class="line" id="L170"> <span class="tok-number">0xb2</span>...<span class="tok-number">0xb3</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L171"> <span class="tok-number">0xb9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L172"> <span class="tok-number">0x1369</span>...<span class="tok-number">0x1371</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L173"> <span class="tok-number">0x19da</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L174"> <span class="tok-number">0x2070</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L175"> <span class="tok-number">0x2074</span>...<span class="tok-number">0x2079</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L176"> <span class="tok-number">0x2080</span>...<span class="tok-number">0x2089</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L177"> <span class="tok-number">0x2460</span>...<span class="tok-number">0x2468</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L178"> <span class="tok-number">0x2474</span>...<span class="tok-number">0x247c</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L179"> <span class="tok-number">0x2488</span>...<span class="tok-number">0x2490</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L180"> <span class="tok-number">0x24ea</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L181"> <span class="tok-number">0x24f5</span>...<span class="tok-number">0x24fd</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L182"> <span class="tok-number">0x24ff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L183"> <span class="tok-number">0x2776</span>...<span class="tok-number">0x277e</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L184"> <span class="tok-number">0x2780</span>...<span class="tok-number">0x2788</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L185"> <span class="tok-number">0x278a</span>...<span class="tok-number">0x2792</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L186"> <span class="tok-number">0x10a40</span>...<span class="tok-number">0x10a43</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L187"> <span class="tok-number">0x10e60</span>...<span class="tok-number">0x10e68</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L188"> <span class="tok-number">0x11052</span>...<span class="tok-number">0x1105a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L189"> <span class="tok-number">0x1f100</span>...<span class="tok-number">0x1f10a</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L190"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L191"> };</span>
<span class="line" id="L192">}</span>
<span class="line" id="L193"></span>
<span class="line" id="L194"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">isDecimal</span>(cp: <span class="tok-type">u21</span>) <span class="tok-type">bool</span> {</span>
<span class="line" id="L195"> <span class="tok-kw">if</span> (cp &lt; <span class="tok-number">0x30</span> <span class="tok-kw">or</span> cp &gt; <span class="tok-number">0x1fbf9</span>) <span class="tok-kw">return</span> <span class="tok-null">false</span>;</span>
<span class="line" id="L196"></span>
<span class="line" id="L197"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (cp) {</span>
<span class="line" id="L198"> <span class="tok-number">0x30</span>...<span class="tok-number">0x39</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L199"> <span class="tok-number">0x660</span>...<span class="tok-number">0x669</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L200"> <span class="tok-number">0x6f0</span>...<span class="tok-number">0x6f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L201"> <span class="tok-number">0x7c0</span>...<span class="tok-number">0x7c9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L202"> <span class="tok-number">0x966</span>...<span class="tok-number">0x96f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L203"> <span class="tok-number">0x9e6</span>...<span class="tok-number">0x9ef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L204"> <span class="tok-number">0xa66</span>...<span class="tok-number">0xa6f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L205"> <span class="tok-number">0xae6</span>...<span class="tok-number">0xaef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L206"> <span class="tok-number">0xb66</span>...<span class="tok-number">0xb6f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L207"> <span class="tok-number">0xbe6</span>...<span class="tok-number">0xbef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L208"> <span class="tok-number">0xc66</span>...<span class="tok-number">0xc6f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L209"> <span class="tok-number">0xce6</span>...<span class="tok-number">0xcef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L210"> <span class="tok-number">0xd66</span>...<span class="tok-number">0xd6f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L211"> <span class="tok-number">0xde6</span>...<span class="tok-number">0xdef</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L212"> <span class="tok-number">0xe50</span>...<span class="tok-number">0xe59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L213"> <span class="tok-number">0xed0</span>...<span class="tok-number">0xed9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L214"> <span class="tok-number">0xf20</span>...<span class="tok-number">0xf29</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L215"> <span class="tok-number">0x1040</span>...<span class="tok-number">0x1049</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L216"> <span class="tok-number">0x1090</span>...<span class="tok-number">0x1099</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L217"> <span class="tok-number">0x17e0</span>...<span class="tok-number">0x17e9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L218"> <span class="tok-number">0x1810</span>...<span class="tok-number">0x1819</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L219"> <span class="tok-number">0x1946</span>...<span class="tok-number">0x194f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L220"> <span class="tok-number">0x19d0</span>...<span class="tok-number">0x19d9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L221"> <span class="tok-number">0x1a80</span>...<span class="tok-number">0x1a89</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L222"> <span class="tok-number">0x1a90</span>...<span class="tok-number">0x1a99</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L223"> <span class="tok-number">0x1b50</span>...<span class="tok-number">0x1b59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L224"> <span class="tok-number">0x1bb0</span>...<span class="tok-number">0x1bb9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L225"> <span class="tok-number">0x1c40</span>...<span class="tok-number">0x1c49</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L226"> <span class="tok-number">0x1c50</span>...<span class="tok-number">0x1c59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L227"> <span class="tok-number">0xa620</span>...<span class="tok-number">0xa629</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L228"> <span class="tok-number">0xa8d0</span>...<span class="tok-number">0xa8d9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L229"> <span class="tok-number">0xa900</span>...<span class="tok-number">0xa909</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L230"> <span class="tok-number">0xa9d0</span>...<span class="tok-number">0xa9d9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L231"> <span class="tok-number">0xa9f0</span>...<span class="tok-number">0xa9f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L232"> <span class="tok-number">0xaa50</span>...<span class="tok-number">0xaa59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L233"> <span class="tok-number">0xabf0</span>...<span class="tok-number">0xabf9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L234"> <span class="tok-number">0xff10</span>...<span class="tok-number">0xff19</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L235"> <span class="tok-number">0x104a0</span>...<span class="tok-number">0x104a9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L236"> <span class="tok-number">0x10d30</span>...<span class="tok-number">0x10d39</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L237"> <span class="tok-number">0x11066</span>...<span class="tok-number">0x1106f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L238"> <span class="tok-number">0x110f0</span>...<span class="tok-number">0x110f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L239"> <span class="tok-number">0x11136</span>...<span class="tok-number">0x1113f</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L240"> <span class="tok-number">0x111d0</span>...<span class="tok-number">0x111d9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L241"> <span class="tok-number">0x112f0</span>...<span class="tok-number">0x112f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L242"> <span class="tok-number">0x11450</span>...<span class="tok-number">0x11459</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L243"> <span class="tok-number">0x114d0</span>...<span class="tok-number">0x114d9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L244"> <span class="tok-number">0x11650</span>...<span class="tok-number">0x11659</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L245"> <span class="tok-number">0x116c0</span>...<span class="tok-number">0x116c9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L246"> <span class="tok-number">0x11730</span>...<span class="tok-number">0x11739</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L247"> <span class="tok-number">0x118e0</span>...<span class="tok-number">0x118e9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L248"> <span class="tok-number">0x11950</span>...<span class="tok-number">0x11959</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L249"> <span class="tok-number">0x11c50</span>...<span class="tok-number">0x11c59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L250"> <span class="tok-number">0x11d50</span>...<span class="tok-number">0x11d59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L251"> <span class="tok-number">0x11da0</span>...<span class="tok-number">0x11da9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L252"> <span class="tok-number">0x11f50</span>...<span class="tok-number">0x11f59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L253"> <span class="tok-number">0x16a60</span>...<span class="tok-number">0x16a69</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L254"> <span class="tok-number">0x16ac0</span>...<span class="tok-number">0x16ac9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L255"> <span class="tok-number">0x16b50</span>...<span class="tok-number">0x16b59</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L256"> <span class="tok-number">0x1d7ce</span>...<span class="tok-number">0x1d7ff</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L257"> <span class="tok-number">0x1e140</span>...<span class="tok-number">0x1e149</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L258"> <span class="tok-number">0x1e2f0</span>...<span class="tok-number">0x1e2f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L259"> <span class="tok-number">0x1e4f0</span>...<span class="tok-number">0x1e4f9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L260"> <span class="tok-number">0x1e950</span>...<span class="tok-number">0x1e959</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L261"> <span class="tok-number">0x1fbf0</span>...<span class="tok-number">0x1fbf9</span> =&gt; <span class="tok-null">true</span>,</span>
<span class="line" id="L262"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">false</span>,</span>
<span class="line" id="L263"> };</span>
<span class="line" id="L264">}</span>
<span class="line" id="L265"></span>
</code></pre></body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,938 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>autogen/hangul_syllable_type.zig - source view</title>
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAgklEQVR4AWMYWuD7EllJIM4G4g4g5oIJ/odhOJ8wToOxSTXgNxDHoeiBMfA4+wGShjyYOCkG/IGqWQziEzYAoUAeiF9D5U+DxEg14DRU7jWIT5IBIOdCxf+A+CQZAAoopEB7QJwBCBwHiip8UYmRdrAlDpIMgApwQZNnNii5Dq0MBgCxxycBnwEd+wAAAABJRU5ErkJggg==">
<link rel="icon" href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNTMgMTQwIj48ZyBmaWxsPSIjRjdBNDFEIj48Zz48cG9seWdvbiBwb2ludHM9IjQ2LDIyIDI4LDQ0IDE5LDMwIi8+PHBvbHlnb24gcG9pbnRzPSI0NiwyMiAzMywzMyAyOCw0NCAyMiw0NCAyMiw5NSAzMSw5NSAyMCwxMDAgMTIsMTE3IDAsMTE3IDAsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMzEsOTUgMTIsMTE3IDQsMTA2Ii8+PC9nPjxnPjxwb2x5Z29uIHBvaW50cz0iNTYsMjIgNjIsMzYgMzcsNDQiLz48cG9seWdvbiBwb2ludHM9IjU2LDIyIDExMSwyMiAxMTEsNDQgMzcsNDQgNTYsMzIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTE2LDk1IDk3LDExNyA5MCwxMDQiLz48cG9seWdvbiBwb2ludHM9IjExNiw5NSAxMDAsMTA0IDk3LDExNyA0MiwxMTcgNDIsOTUiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTUwLDAgNTIsMTE3IDMsMTQwIDEwMSwyMiIvPjwvZz48Zz48cG9seWdvbiBwb2ludHM9IjE0MSwyMiAxNDAsNDAgMTIyLDQ1Ii8+PHBvbHlnb24gcG9pbnRzPSIxNTMsMjIgMTUzLDExNyAxMDYsMTE3IDEyMCwxMDUgMTI1LDk1IDEzMSw5NSAxMzEsNDUgMTIyLDQ1IDEzMiwzNiAxNDEsMjIiIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyIvPjxwb2x5Z29uIHBvaW50cz0iMTI1LDk1IDEzMCwxMTAgMTA2LDExNyIvPjwvZz48L2c+PC9zdmc+">
<style>
body{
font-family: system-ui, -apple-system, Roboto, "Segoe UI", sans-serif;
margin: 0;
line-height: 1.5;
}
pre > code {
display: block;
overflow: auto;
line-height: normal;
margin: 0em;
}
.tok-kw {
color: #333;
font-weight: bold;
}
.tok-str {
color: #d14;
}
.tok-builtin {
color: #005C7A;
}
.tok-comment {
color: #545454;
font-style: italic;
}
.tok-fn {
color: #900;
font-weight: bold;
}
.tok-null {
color: #005C5C;
}
.tok-number {
color: #005C5C;
}
.tok-type {
color: #458;
font-weight: bold;
}
pre {
counter-reset: line;
}
pre .line:before {
counter-increment: line;
content: counter(line);
display: inline-block;
padding-right: 1em;
width: 2em;
text-align: right;
color: #999;
}
.line {
width: 100%;
display: inline-block;
}
.line:target {
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
background: #fafafa;
}
@media (prefers-color-scheme: dark) {
body{
background:#222;
color: #ccc;
}
pre > code {
color: #ccc;
background: #222;
border: unset;
}
.line:target {
border-top: 1px solid #444;
border-bottom: 1px solid #444;
background: #333;
}
.tok-kw {
color: #eee;
}
.tok-str {
color: #2e5;
}
.tok-builtin {
color: #ff894c;
}
.tok-comment {
color: #aa7;
}
.tok-fn {
color: #B1A0F8;
}
.tok-null {
color: #ff8080;
}
.tok-number {
color: #ff8080;
}
.tok-type {
color: #68f;
}
}
</style>
</head>
<body>
<pre><code><span class="line" id="L1"><span class="tok-comment">// Autogenerated from https://www.unicode.org/Public/15.0.0/ucd/</span>
</span>
<span class="line" id="L2"></span>
<span class="line" id="L3"><span class="tok-kw">pub</span> <span class="tok-kw">const</span> Kind = <span class="tok-kw">enum</span> {</span>
<span class="line" id="L4"> L,</span>
<span class="line" id="L5"> LV,</span>
<span class="line" id="L6"> LVT,</span>
<span class="line" id="L7"> T,</span>
<span class="line" id="L8"> V,</span>
<span class="line" id="L9">};</span>
<span class="line" id="L10"></span>
<span class="line" id="L11"><span class="tok-comment">/// `syllableType` maps the code point to its Hangul Syllable Type.</span></span>
<span class="line" id="L12"><span class="tok-kw">pub</span> <span class="tok-kw">fn</span> <span class="tok-fn">syllableType</span>(cp: <span class="tok-type">u21</span>) ?Kind {</span>
<span class="line" id="L13"> <span class="tok-kw">return</span> <span class="tok-kw">switch</span> (cp) {</span>
<span class="line" id="L14"> <span class="tok-number">0x1100</span>...<span class="tok-number">0x115F</span> =&gt; .L,</span>
<span class="line" id="L15"> <span class="tok-number">0xA960</span>...<span class="tok-number">0xA97C</span> =&gt; .L,</span>
<span class="line" id="L16"> <span class="tok-number">0x1160</span>...<span class="tok-number">0x11A7</span> =&gt; .V,</span>
<span class="line" id="L17"> <span class="tok-number">0xD7B0</span>...<span class="tok-number">0xD7C6</span> =&gt; .V,</span>
<span class="line" id="L18"> <span class="tok-number">0x11A8</span>...<span class="tok-number">0x11FF</span> =&gt; .T,</span>
<span class="line" id="L19"> <span class="tok-number">0xD7CB</span>...<span class="tok-number">0xD7FB</span> =&gt; .T,</span>
<span class="line" id="L20"> <span class="tok-number">0xAC00</span> =&gt; .LV,</span>
<span class="line" id="L21"> <span class="tok-number">0xAC1C</span> =&gt; .LV,</span>
<span class="line" id="L22"> <span class="tok-number">0xAC38</span> =&gt; .LV,</span>
<span class="line" id="L23"> <span class="tok-number">0xAC54</span> =&gt; .LV,</span>
<span class="line" id="L24"> <span class="tok-number">0xAC70</span> =&gt; .LV,</span>
<span class="line" id="L25"> <span class="tok-number">0xAC8C</span> =&gt; .LV,</span>
<span class="line" id="L26"> <span class="tok-number">0xACA8</span> =&gt; .LV,</span>
<span class="line" id="L27"> <span class="tok-number">0xACC4</span> =&gt; .LV,</span>
<span class="line" id="L28"> <span class="tok-number">0xACE0</span> =&gt; .LV,</span>
<span class="line" id="L29"> <span class="tok-number">0xACFC</span> =&gt; .LV,</span>
<span class="line" id="L30"> <span class="tok-number">0xAD18</span> =&gt; .LV,</span>
<span class="line" id="L31"> <span class="tok-number">0xAD34</span> =&gt; .LV,</span>
<span class="line" id="L32"> <span class="tok-number">0xAD50</span> =&gt; .LV,</span>
<span class="line" id="L33"> <span class="tok-number">0xAD6C</span> =&gt; .LV,</span>
<span class="line" id="L34"> <span class="tok-number">0xAD88</span> =&gt; .LV,</span>
<span class="line" id="L35"> <span class="tok-number">0xADA4</span> =&gt; .LV,</span>
<span class="line" id="L36"> <span class="tok-number">0xADC0</span> =&gt; .LV,</span>
<span class="line" id="L37"> <span class="tok-number">0xADDC</span> =&gt; .LV,</span>
<span class="line" id="L38"> <span class="tok-number">0xADF8</span> =&gt; .LV,</span>
<span class="line" id="L39"> <span class="tok-number">0xAE14</span> =&gt; .LV,</span>
<span class="line" id="L40"> <span class="tok-number">0xAE30</span> =&gt; .LV,</span>
<span class="line" id="L41"> <span class="tok-number">0xAE4C</span> =&gt; .LV,</span>
<span class="line" id="L42"> <span class="tok-number">0xAE68</span> =&gt; .LV,</span>
<span class="line" id="L43"> <span class="tok-number">0xAE84</span> =&gt; .LV,</span>
<span class="line" id="L44"> <span class="tok-number">0xAEA0</span> =&gt; .LV,</span>
<span class="line" id="L45"> <span class="tok-number">0xAEBC</span> =&gt; .LV,</span>
<span class="line" id="L46"> <span class="tok-number">0xAED8</span> =&gt; .LV,</span>
<span class="line" id="L47"> <span class="tok-number">0xAEF4</span> =&gt; .LV,</span>
<span class="line" id="L48"> <span class="tok-number">0xAF10</span> =&gt; .LV,</span>
<span class="line" id="L49"> <span class="tok-number">0xAF2C</span> =&gt; .LV,</span>
<span class="line" id="L50"> <span class="tok-number">0xAF48</span> =&gt; .LV,</span>
<span class="line" id="L51"> <span class="tok-number">0xAF64</span> =&gt; .LV,</span>
<span class="line" id="L52"> <span class="tok-number">0xAF80</span> =&gt; .LV,</span>
<span class="line" id="L53"> <span class="tok-number">0xAF9C</span> =&gt; .LV,</span>
<span class="line" id="L54"> <span class="tok-number">0xAFB8</span> =&gt; .LV,</span>
<span class="line" id="L55"> <span class="tok-number">0xAFD4</span> =&gt; .LV,</span>
<span class="line" id="L56"> <span class="tok-number">0xAFF0</span> =&gt; .LV,</span>
<span class="line" id="L57"> <span class="tok-number">0xB00C</span> =&gt; .LV,</span>
<span class="line" id="L58"> <span class="tok-number">0xB028</span> =&gt; .LV,</span>
<span class="line" id="L59"> <span class="tok-number">0xB044</span> =&gt; .LV,</span>
<span class="line" id="L60"> <span class="tok-number">0xB060</span> =&gt; .LV,</span>
<span class="line" id="L61"> <span class="tok-number">0xB07C</span> =&gt; .LV,</span>
<span class="line" id="L62"> <span class="tok-number">0xB098</span> =&gt; .LV,</span>
<span class="line" id="L63"> <span class="tok-number">0xB0B4</span> =&gt; .LV,</span>
<span class="line" id="L64"> <span class="tok-number">0xB0D0</span> =&gt; .LV,</span>
<span class="line" id="L65"> <span class="tok-number">0xB0EC</span> =&gt; .LV,</span>
<span class="line" id="L66"> <span class="tok-number">0xB108</span> =&gt; .LV,</span>
<span class="line" id="L67"> <span class="tok-number">0xB124</span> =&gt; .LV,</span>
<span class="line" id="L68"> <span class="tok-number">0xB140</span> =&gt; .LV,</span>
<span class="line" id="L69"> <span class="tok-number">0xB15C</span> =&gt; .LV,</span>
<span class="line" id="L70"> <span class="tok-number">0xB178</span> =&gt; .LV,</span>
<span class="line" id="L71"> <span class="tok-number">0xB194</span> =&gt; .LV,</span>
<span class="line" id="L72"> <span class="tok-number">0xB1B0</span> =&gt; .LV,</span>
<span class="line" id="L73"> <span class="tok-number">0xB1CC</span> =&gt; .LV,</span>
<span class="line" id="L74"> <span class="tok-number">0xB1E8</span> =&gt; .LV,</span>
<span class="line" id="L75"> <span class="tok-number">0xB204</span> =&gt; .LV,</span>
<span class="line" id="L76"> <span class="tok-number">0xB220</span> =&gt; .LV,</span>
<span class="line" id="L77"> <span class="tok-number">0xB23C</span> =&gt; .LV,</span>
<span class="line" id="L78"> <span class="tok-number">0xB258</span> =&gt; .LV,</span>
<span class="line" id="L79"> <span class="tok-number">0xB274</span> =&gt; .LV,</span>
<span class="line" id="L80"> <span class="tok-number">0xB290</span> =&gt; .LV,</span>
<span class="line" id="L81"> <span class="tok-number">0xB2AC</span> =&gt; .LV,</span>
<span class="line" id="L82"> <span class="tok-number">0xB2C8</span> =&gt; .LV,</span>
<span class="line" id="L83"> <span class="tok-number">0xB2E4</span> =&gt; .LV,</span>
<span class="line" id="L84"> <span class="tok-number">0xB300</span> =&gt; .LV,</span>
<span class="line" id="L85"> <span class="tok-number">0xB31C</span> =&gt; .LV,</span>
<span class="line" id="L86"> <span class="tok-number">0xB338</span> =&gt; .LV,</span>
<span class="line" id="L87"> <span class="tok-number">0xB354</span> =&gt; .LV,</span>
<span class="line" id="L88"> <span class="tok-number">0xB370</span> =&gt; .LV,</span>
<span class="line" id="L89"> <span class="tok-number">0xB38C</span> =&gt; .LV,</span>
<span class="line" id="L90"> <span class="tok-number">0xB3A8</span> =&gt; .LV,</span>
<span class="line" id="L91"> <span class="tok-number">0xB3C4</span> =&gt; .LV,</span>
<span class="line" id="L92"> <span class="tok-number">0xB3E0</span> =&gt; .LV,</span>
<span class="line" id="L93"> <span class="tok-number">0xB3FC</span> =&gt; .LV,</span>
<span class="line" id="L94"> <span class="tok-number">0xB418</span> =&gt; .LV,</span>
<span class="line" id="L95"> <span class="tok-number">0xB434</span> =&gt; .LV,</span>
<span class="line" id="L96"> <span class="tok-number">0xB450</span> =&gt; .LV,</span>
<span class="line" id="L97"> <span class="tok-number">0xB46C</span> =&gt; .LV,</span>
<span class="line" id="L98"> <span class="tok-number">0xB488</span> =&gt; .LV,</span>
<span class="line" id="L99"> <span class="tok-number">0xB4A4</span> =&gt; .LV,</span>
<span class="line" id="L100"> <span class="tok-number">0xB4C0</span> =&gt; .LV,</span>
<span class="line" id="L101"> <span class="tok-number">0xB4DC</span> =&gt; .LV,</span>
<span class="line" id="L102"> <span class="tok-number">0xB4F8</span> =&gt; .LV,</span>
<span class="line" id="L103"> <span class="tok-number">0xB514</span> =&gt; .LV,</span>
<span class="line" id="L104"> <span class="tok-number">0xB530</span> =&gt; .LV,</span>
<span class="line" id="L105"> <span class="tok-number">0xB54C</span> =&gt; .LV,</span>
<span class="line" id="L106"> <span class="tok-number">0xB568</span> =&gt; .LV,</span>
<span class="line" id="L107"> <span class="tok-number">0xB584</span> =&gt; .LV,</span>
<span class="line" id="L108"> <span class="tok-number">0xB5A0</span> =&gt; .LV,</span>
<span class="line" id="L109"> <span class="tok-number">0xB5BC</span> =&gt; .LV,</span>
<span class="line" id="L110"> <span class="tok-number">0xB5D8</span> =&gt; .LV,</span>
<span class="line" id="L111"> <span class="tok-number">0xB5F4</span> =&gt; .LV,</span>
<span class="line" id="L112"> <span class="tok-number">0xB610</span> =&gt; .LV,</span>
<span class="line" id="L113"> <span class="tok-number">0xB62C</span> =&gt; .LV,</span>
<span class="line" id="L114"> <span class="tok-number">0xB648</span> =&gt; .LV,</span>
<span class="line" id="L115"> <span class="tok-number">0xB664</span> =&gt; .LV,</span>
<span class="line" id="L116"> <span class="tok-number">0xB680</span> =&gt; .LV,</span>
<span class="line" id="L117"> <span class="tok-number">0xB69C</span> =&gt; .LV,</span>
<span class="line" id="L118"> <span class="tok-number">0xB6B8</span> =&gt; .LV,</span>
<span class="line" id="L119"> <span class="tok-number">0xB6D4</span> =&gt; .LV,</span>
<span class="line" id="L120"> <span class="tok-number">0xB6F0</span> =&gt; .LV,</span>
<span class="line" id="L121"> <span class="tok-number">0xB70C</span> =&gt; .LV,</span>
<span class="line" id="L122"> <span class="tok-number">0xB728</span> =&gt; .LV,</span>
<span class="line" id="L123"> <span class="tok-number">0xB744</span> =&gt; .LV,</span>
<span class="line" id="L124"> <span class="tok-number">0xB760</span> =&gt; .LV,</span>
<span class="line" id="L125"> <span class="tok-number">0xB77C</span> =&gt; .LV,</span>
<span class="line" id="L126"> <span class="tok-number">0xB798</span> =&gt; .LV,</span>
<span class="line" id="L127"> <span class="tok-number">0xB7B4</span> =&gt; .LV,</span>
<span class="line" id="L128"> <span class="tok-number">0xB7D0</span> =&gt; .LV,</span>
<span class="line" id="L129"> <span class="tok-number">0xB7EC</span> =&gt; .LV,</span>
<span class="line" id="L130"> <span class="tok-number">0xB808</span> =&gt; .LV,</span>
<span class="line" id="L131"> <span class="tok-number">0xB824</span> =&gt; .LV,</span>
<span class="line" id="L132"> <span class="tok-number">0xB840</span> =&gt; .LV,</span>
<span class="line" id="L133"> <span class="tok-number">0xB85C</span> =&gt; .LV,</span>
<span class="line" id="L134"> <span class="tok-number">0xB878</span> =&gt; .LV,</span>
<span class="line" id="L135"> <span class="tok-number">0xB894</span> =&gt; .LV,</span>
<span class="line" id="L136"> <span class="tok-number">0xB8B0</span> =&gt; .LV,</span>
<span class="line" id="L137"> <span class="tok-number">0xB8CC</span> =&gt; .LV,</span>
<span class="line" id="L138"> <span class="tok-number">0xB8E8</span> =&gt; .LV,</span>
<span class="line" id="L139"> <span class="tok-number">0xB904</span> =&gt; .LV,</span>
<span class="line" id="L140"> <span class="tok-number">0xB920</span> =&gt; .LV,</span>
<span class="line" id="L141"> <span class="tok-number">0xB93C</span> =&gt; .LV,</span>
<span class="line" id="L142"> <span class="tok-number">0xB958</span> =&gt; .LV,</span>
<span class="line" id="L143"> <span class="tok-number">0xB974</span> =&gt; .LV,</span>
<span class="line" id="L144"> <span class="tok-number">0xB990</span> =&gt; .LV,</span>
<span class="line" id="L145"> <span class="tok-number">0xB9AC</span> =&gt; .LV,</span>
<span class="line" id="L146"> <span class="tok-number">0xB9C8</span> =&gt; .LV,</span>
<span class="line" id="L147"> <span class="tok-number">0xB9E4</span> =&gt; .LV,</span>
<span class="line" id="L148"> <span class="tok-number">0xBA00</span> =&gt; .LV,</span>
<span class="line" id="L149"> <span class="tok-number">0xBA1C</span> =&gt; .LV,</span>
<span class="line" id="L150"> <span class="tok-number">0xBA38</span> =&gt; .LV,</span>
<span class="line" id="L151"> <span class="tok-number">0xBA54</span> =&gt; .LV,</span>
<span class="line" id="L152"> <span class="tok-number">0xBA70</span> =&gt; .LV,</span>
<span class="line" id="L153"> <span class="tok-number">0xBA8C</span> =&gt; .LV,</span>
<span class="line" id="L154"> <span class="tok-number">0xBAA8</span> =&gt; .LV,</span>
<span class="line" id="L155"> <span class="tok-number">0xBAC4</span> =&gt; .LV,</span>
<span class="line" id="L156"> <span class="tok-number">0xBAE0</span> =&gt; .LV,</span>
<span class="line" id="L157"> <span class="tok-number">0xBAFC</span> =&gt; .LV,</span>
<span class="line" id="L158"> <span class="tok-number">0xBB18</span> =&gt; .LV,</span>
<span class="line" id="L159"> <span class="tok-number">0xBB34</span> =&gt; .LV,</span>
<span class="line" id="L160"> <span class="tok-number">0xBB50</span> =&gt; .LV,</span>
<span class="line" id="L161"> <span class="tok-number">0xBB6C</span> =&gt; .LV,</span>
<span class="line" id="L162"> <span class="tok-number">0xBB88</span> =&gt; .LV,</span>
<span class="line" id="L163"> <span class="tok-number">0xBBA4</span> =&gt; .LV,</span>
<span class="line" id="L164"> <span class="tok-number">0xBBC0</span> =&gt; .LV,</span>
<span class="line" id="L165"> <span class="tok-number">0xBBDC</span> =&gt; .LV,</span>
<span class="line" id="L166"> <span class="tok-number">0xBBF8</span> =&gt; .LV,</span>
<span class="line" id="L167"> <span class="tok-number">0xBC14</span> =&gt; .LV,</span>
<span class="line" id="L168"> <span class="tok-number">0xBC30</span> =&gt; .LV,</span>
<span class="line" id="L169"> <span class="tok-number">0xBC4C</span> =&gt; .LV,</span>
<span class="line" id="L170"> <span class="tok-number">0xBC68</span> =&gt; .LV,</span>
<span class="line" id="L171"> <span class="tok-number">0xBC84</span> =&gt; .LV,</span>
<span class="line" id="L172"> <span class="tok-number">0xBCA0</span> =&gt; .LV,</span>
<span class="line" id="L173"> <span class="tok-number">0xBCBC</span> =&gt; .LV,</span>
<span class="line" id="L174"> <span class="tok-number">0xBCD8</span> =&gt; .LV,</span>
<span class="line" id="L175"> <span class="tok-number">0xBCF4</span> =&gt; .LV,</span>
<span class="line" id="L176"> <span class="tok-number">0xBD10</span> =&gt; .LV,</span>
<span class="line" id="L177"> <span class="tok-number">0xBD2C</span> =&gt; .LV,</span>
<span class="line" id="L178"> <span class="tok-number">0xBD48</span> =&gt; .LV,</span>
<span class="line" id="L179"> <span class="tok-number">0xBD64</span> =&gt; .LV,</span>
<span class="line" id="L180"> <span class="tok-number">0xBD80</span> =&gt; .LV,</span>
<span class="line" id="L181"> <span class="tok-number">0xBD9C</span> =&gt; .LV,</span>
<span class="line" id="L182"> <span class="tok-number">0xBDB8</span> =&gt; .LV,</span>
<span class="line" id="L183"> <span class="tok-number">0xBDD4</span> =&gt; .LV,</span>
<span class="line" id="L184"> <span class="tok-number">0xBDF0</span> =&gt; .LV,</span>
<span class="line" id="L185"> <span class="tok-number">0xBE0C</span> =&gt; .LV,</span>
<span class="line" id="L186"> <span class="tok-number">0xBE28</span> =&gt; .LV,</span>
<span class="line" id="L187"> <span class="tok-number">0xBE44</span> =&gt; .LV,</span>
<span class="line" id="L188"> <span class="tok-number">0xBE60</span> =&gt; .LV,</span>
<span class="line" id="L189"> <span class="tok-number">0xBE7C</span> =&gt; .LV,</span>
<span class="line" id="L190"> <span class="tok-number">0xBE98</span> =&gt; .LV,</span>
<span class="line" id="L191"> <span class="tok-number">0xBEB4</span> =&gt; .LV,</span>
<span class="line" id="L192"> <span class="tok-number">0xBED0</span> =&gt; .LV,</span>
<span class="line" id="L193"> <span class="tok-number">0xBEEC</span> =&gt; .LV,</span>
<span class="line" id="L194"> <span class="tok-number">0xBF08</span> =&gt; .LV,</span>
<span class="line" id="L195"> <span class="tok-number">0xBF24</span> =&gt; .LV,</span>
<span class="line" id="L196"> <span class="tok-number">0xBF40</span> =&gt; .LV,</span>
<span class="line" id="L197"> <span class="tok-number">0xBF5C</span> =&gt; .LV,</span>
<span class="line" id="L198"> <span class="tok-number">0xBF78</span> =&gt; .LV,</span>
<span class="line" id="L199"> <span class="tok-number">0xBF94</span> =&gt; .LV,</span>
<span class="line" id="L200"> <span class="tok-number">0xBFB0</span> =&gt; .LV,</span>
<span class="line" id="L201"> <span class="tok-number">0xBFCC</span> =&gt; .LV,</span>
<span class="line" id="L202"> <span class="tok-number">0xBFE8</span> =&gt; .LV,</span>
<span class="line" id="L203"> <span class="tok-number">0xC004</span> =&gt; .LV,</span>
<span class="line" id="L204"> <span class="tok-number">0xC020</span> =&gt; .LV,</span>
<span class="line" id="L205"> <span class="tok-number">0xC03C</span> =&gt; .LV,</span>
<span class="line" id="L206"> <span class="tok-number">0xC058</span> =&gt; .LV,</span>
<span class="line" id="L207"> <span class="tok-number">0xC074</span> =&gt; .LV,</span>
<span class="line" id="L208"> <span class="tok-number">0xC090</span> =&gt; .LV,</span>
<span class="line" id="L209"> <span class="tok-number">0xC0AC</span> =&gt; .LV,</span>
<span class="line" id="L210"> <span class="tok-number">0xC0C8</span> =&gt; .LV,</span>
<span class="line" id="L211"> <span class="tok-number">0xC0E4</span> =&gt; .LV,</span>
<span class="line" id="L212"> <span class="tok-number">0xC100</span> =&gt; .LV,</span>
<span class="line" id="L213"> <span class="tok-number">0xC11C</span> =&gt; .LV,</span>
<span class="line" id="L214"> <span class="tok-number">0xC138</span> =&gt; .LV,</span>
<span class="line" id="L215"> <span class="tok-number">0xC154</span> =&gt; .LV,</span>
<span class="line" id="L216"> <span class="tok-number">0xC170</span> =&gt; .LV,</span>
<span class="line" id="L217"> <span class="tok-number">0xC18C</span> =&gt; .LV,</span>
<span class="line" id="L218"> <span class="tok-number">0xC1A8</span> =&gt; .LV,</span>
<span class="line" id="L219"> <span class="tok-number">0xC1C4</span> =&gt; .LV,</span>
<span class="line" id="L220"> <span class="tok-number">0xC1E0</span> =&gt; .LV,</span>
<span class="line" id="L221"> <span class="tok-number">0xC1FC</span> =&gt; .LV,</span>
<span class="line" id="L222"> <span class="tok-number">0xC218</span> =&gt; .LV,</span>
<span class="line" id="L223"> <span class="tok-number">0xC234</span> =&gt; .LV,</span>
<span class="line" id="L224"> <span class="tok-number">0xC250</span> =&gt; .LV,</span>
<span class="line" id="L225"> <span class="tok-number">0xC26C</span> =&gt; .LV,</span>
<span class="line" id="L226"> <span class="tok-number">0xC288</span> =&gt; .LV,</span>
<span class="line" id="L227"> <span class="tok-number">0xC2A4</span> =&gt; .LV,</span>
<span class="line" id="L228"> <span class="tok-number">0xC2C0</span> =&gt; .LV,</span>
<span class="line" id="L229"> <span class="tok-number">0xC2DC</span> =&gt; .LV,</span>
<span class="line" id="L230"> <span class="tok-number">0xC2F8</span> =&gt; .LV,</span>
<span class="line" id="L231"> <span class="tok-number">0xC314</span> =&gt; .LV,</span>
<span class="line" id="L232"> <span class="tok-number">0xC330</span> =&gt; .LV,</span>
<span class="line" id="L233"> <span class="tok-number">0xC34C</span> =&gt; .LV,</span>
<span class="line" id="L234"> <span class="tok-number">0xC368</span> =&gt; .LV,</span>
<span class="line" id="L235"> <span class="tok-number">0xC384</span> =&gt; .LV,</span>
<span class="line" id="L236"> <span class="tok-number">0xC3A0</span> =&gt; .LV,</span>
<span class="line" id="L237"> <span class="tok-number">0xC3BC</span> =&gt; .LV,</span>
<span class="line" id="L238"> <span class="tok-number">0xC3D8</span> =&gt; .LV,</span>
<span class="line" id="L239"> <span class="tok-number">0xC3F4</span> =&gt; .LV,</span>
<span class="line" id="L240"> <span class="tok-number">0xC410</span> =&gt; .LV,</span>
<span class="line" id="L241"> <span class="tok-number">0xC42C</span> =&gt; .LV,</span>
<span class="line" id="L242"> <span class="tok-number">0xC448</span> =&gt; .LV,</span>
<span class="line" id="L243"> <span class="tok-number">0xC464</span> =&gt; .LV,</span>
<span class="line" id="L244"> <span class="tok-number">0xC480</span> =&gt; .LV,</span>
<span class="line" id="L245"> <span class="tok-number">0xC49C</span> =&gt; .LV,</span>
<span class="line" id="L246"> <span class="tok-number">0xC4B8</span> =&gt; .LV,</span>
<span class="line" id="L247"> <span class="tok-number">0xC4D4</span> =&gt; .LV,</span>
<span class="line" id="L248"> <span class="tok-number">0xC4F0</span> =&gt; .LV,</span>
<span class="line" id="L249"> <span class="tok-number">0xC50C</span> =&gt; .LV,</span>
<span class="line" id="L250"> <span class="tok-number">0xC528</span> =&gt; .LV,</span>
<span class="line" id="L251"> <span class="tok-number">0xC544</span> =&gt; .LV,</span>
<span class="line" id="L252"> <span class="tok-number">0xC560</span> =&gt; .LV,</span>
<span class="line" id="L253"> <span class="tok-number">0xC57C</span> =&gt; .LV,</span>
<span class="line" id="L254"> <span class="tok-number">0xC598</span> =&gt; .LV,</span>
<span class="line" id="L255"> <span class="tok-number">0xC5B4</span> =&gt; .LV,</span>
<span class="line" id="L256"> <span class="tok-number">0xC5D0</span> =&gt; .LV,</span>
<span class="line" id="L257"> <span class="tok-number">0xC5EC</span> =&gt; .LV,</span>
<span class="line" id="L258"> <span class="tok-number">0xC608</span> =&gt; .LV,</span>
<span class="line" id="L259"> <span class="tok-number">0xC624</span> =&gt; .LV,</span>
<span class="line" id="L260"> <span class="tok-number">0xC640</span> =&gt; .LV,</span>
<span class="line" id="L261"> <span class="tok-number">0xC65C</span> =&gt; .LV,</span>
<span class="line" id="L262"> <span class="tok-number">0xC678</span> =&gt; .LV,</span>
<span class="line" id="L263"> <span class="tok-number">0xC694</span> =&gt; .LV,</span>
<span class="line" id="L264"> <span class="tok-number">0xC6B0</span> =&gt; .LV,</span>
<span class="line" id="L265"> <span class="tok-number">0xC6CC</span> =&gt; .LV,</span>
<span class="line" id="L266"> <span class="tok-number">0xC6E8</span> =&gt; .LV,</span>
<span class="line" id="L267"> <span class="tok-number">0xC704</span> =&gt; .LV,</span>
<span class="line" id="L268"> <span class="tok-number">0xC720</span> =&gt; .LV,</span>
<span class="line" id="L269"> <span class="tok-number">0xC73C</span> =&gt; .LV,</span>
<span class="line" id="L270"> <span class="tok-number">0xC758</span> =&gt; .LV,</span>
<span class="line" id="L271"> <span class="tok-number">0xC774</span> =&gt; .LV,</span>
<span class="line" id="L272"> <span class="tok-number">0xC790</span> =&gt; .LV,</span>
<span class="line" id="L273"> <span class="tok-number">0xC7AC</span> =&gt; .LV,</span>
<span class="line" id="L274"> <span class="tok-number">0xC7C8</span> =&gt; .LV,</span>
<span class="line" id="L275"> <span class="tok-number">0xC7E4</span> =&gt; .LV,</span>
<span class="line" id="L276"> <span class="tok-number">0xC800</span> =&gt; .LV,</span>
<span class="line" id="L277"> <span class="tok-number">0xC81C</span> =&gt; .LV,</span>
<span class="line" id="L278"> <span class="tok-number">0xC838</span> =&gt; .LV,</span>
<span class="line" id="L279"> <span class="tok-number">0xC854</span> =&gt; .LV,</span>
<span class="line" id="L280"> <span class="tok-number">0xC870</span> =&gt; .LV,</span>
<span class="line" id="L281"> <span class="tok-number">0xC88C</span> =&gt; .LV,</span>
<span class="line" id="L282"> <span class="tok-number">0xC8A8</span> =&gt; .LV,</span>
<span class="line" id="L283"> <span class="tok-number">0xC8C4</span> =&gt; .LV,</span>
<span class="line" id="L284"> <span class="tok-number">0xC8E0</span> =&gt; .LV,</span>
<span class="line" id="L285"> <span class="tok-number">0xC8FC</span> =&gt; .LV,</span>
<span class="line" id="L286"> <span class="tok-number">0xC918</span> =&gt; .LV,</span>
<span class="line" id="L287"> <span class="tok-number">0xC934</span> =&gt; .LV,</span>
<span class="line" id="L288"> <span class="tok-number">0xC950</span> =&gt; .LV,</span>
<span class="line" id="L289"> <span class="tok-number">0xC96C</span> =&gt; .LV,</span>
<span class="line" id="L290"> <span class="tok-number">0xC988</span> =&gt; .LV,</span>
<span class="line" id="L291"> <span class="tok-number">0xC9A4</span> =&gt; .LV,</span>
<span class="line" id="L292"> <span class="tok-number">0xC9C0</span> =&gt; .LV,</span>
<span class="line" id="L293"> <span class="tok-number">0xC9DC</span> =&gt; .LV,</span>
<span class="line" id="L294"> <span class="tok-number">0xC9F8</span> =&gt; .LV,</span>
<span class="line" id="L295"> <span class="tok-number">0xCA14</span> =&gt; .LV,</span>
<span class="line" id="L296"> <span class="tok-number">0xCA30</span> =&gt; .LV,</span>
<span class="line" id="L297"> <span class="tok-number">0xCA4C</span> =&gt; .LV,</span>
<span class="line" id="L298"> <span class="tok-number">0xCA68</span> =&gt; .LV,</span>
<span class="line" id="L299"> <span class="tok-number">0xCA84</span> =&gt; .LV,</span>
<span class="line" id="L300"> <span class="tok-number">0xCAA0</span> =&gt; .LV,</span>
<span class="line" id="L301"> <span class="tok-number">0xCABC</span> =&gt; .LV,</span>
<span class="line" id="L302"> <span class="tok-number">0xCAD8</span> =&gt; .LV,</span>
<span class="line" id="L303"> <span class="tok-number">0xCAF4</span> =&gt; .LV,</span>
<span class="line" id="L304"> <span class="tok-number">0xCB10</span> =&gt; .LV,</span>
<span class="line" id="L305"> <span class="tok-number">0xCB2C</span> =&gt; .LV,</span>
<span class="line" id="L306"> <span class="tok-number">0xCB48</span> =&gt; .LV,</span>
<span class="line" id="L307"> <span class="tok-number">0xCB64</span> =&gt; .LV,</span>
<span class="line" id="L308"> <span class="tok-number">0xCB80</span> =&gt; .LV,</span>
<span class="line" id="L309"> <span class="tok-number">0xCB9C</span> =&gt; .LV,</span>
<span class="line" id="L310"> <span class="tok-number">0xCBB8</span> =&gt; .LV,</span>
<span class="line" id="L311"> <span class="tok-number">0xCBD4</span> =&gt; .LV,</span>
<span class="line" id="L312"> <span class="tok-number">0xCBF0</span> =&gt; .LV,</span>
<span class="line" id="L313"> <span class="tok-number">0xCC0C</span> =&gt; .LV,</span>
<span class="line" id="L314"> <span class="tok-number">0xCC28</span> =&gt; .LV,</span>
<span class="line" id="L315"> <span class="tok-number">0xCC44</span> =&gt; .LV,</span>
<span class="line" id="L316"> <span class="tok-number">0xCC60</span> =&gt; .LV,</span>
<span class="line" id="L317"> <span class="tok-number">0xCC7C</span> =&gt; .LV,</span>
<span class="line" id="L318"> <span class="tok-number">0xCC98</span> =&gt; .LV,</span>
<span class="line" id="L319"> <span class="tok-number">0xCCB4</span> =&gt; .LV,</span>
<span class="line" id="L320"> <span class="tok-number">0xCCD0</span> =&gt; .LV,</span>
<span class="line" id="L321"> <span class="tok-number">0xCCEC</span> =&gt; .LV,</span>
<span class="line" id="L322"> <span class="tok-number">0xCD08</span> =&gt; .LV,</span>
<span class="line" id="L323"> <span class="tok-number">0xCD24</span> =&gt; .LV,</span>
<span class="line" id="L324"> <span class="tok-number">0xCD40</span> =&gt; .LV,</span>
<span class="line" id="L325"> <span class="tok-number">0xCD5C</span> =&gt; .LV,</span>
<span class="line" id="L326"> <span class="tok-number">0xCD78</span> =&gt; .LV,</span>
<span class="line" id="L327"> <span class="tok-number">0xCD94</span> =&gt; .LV,</span>
<span class="line" id="L328"> <span class="tok-number">0xCDB0</span> =&gt; .LV,</span>
<span class="line" id="L329"> <span class="tok-number">0xCDCC</span> =&gt; .LV,</span>
<span class="line" id="L330"> <span class="tok-number">0xCDE8</span> =&gt; .LV,</span>
<span class="line" id="L331"> <span class="tok-number">0xCE04</span> =&gt; .LV,</span>
<span class="line" id="L332"> <span class="tok-number">0xCE20</span> =&gt; .LV,</span>
<span class="line" id="L333"> <span class="tok-number">0xCE3C</span> =&gt; .LV,</span>
<span class="line" id="L334"> <span class="tok-number">0xCE58</span> =&gt; .LV,</span>
<span class="line" id="L335"> <span class="tok-number">0xCE74</span> =&gt; .LV,</span>
<span class="line" id="L336"> <span class="tok-number">0xCE90</span> =&gt; .LV,</span>
<span class="line" id="L337"> <span class="tok-number">0xCEAC</span> =&gt; .LV,</span>
<span class="line" id="L338"> <span class="tok-number">0xCEC8</span> =&gt; .LV,</span>
<span class="line" id="L339"> <span class="tok-number">0xCEE4</span> =&gt; .LV,</span>
<span class="line" id="L340"> <span class="tok-number">0xCF00</span> =&gt; .LV,</span>
<span class="line" id="L341"> <span class="tok-number">0xCF1C</span> =&gt; .LV,</span>
<span class="line" id="L342"> <span class="tok-number">0xCF38</span> =&gt; .LV,</span>
<span class="line" id="L343"> <span class="tok-number">0xCF54</span> =&gt; .LV,</span>
<span class="line" id="L344"> <span class="tok-number">0xCF70</span> =&gt; .LV,</span>
<span class="line" id="L345"> <span class="tok-number">0xCF8C</span> =&gt; .LV,</span>
<span class="line" id="L346"> <span class="tok-number">0xCFA8</span> =&gt; .LV,</span>
<span class="line" id="L347"> <span class="tok-number">0xCFC4</span> =&gt; .LV,</span>
<span class="line" id="L348"> <span class="tok-number">0xCFE0</span> =&gt; .LV,</span>
<span class="line" id="L349"> <span class="tok-number">0xCFFC</span> =&gt; .LV,</span>
<span class="line" id="L350"> <span class="tok-number">0xD018</span> =&gt; .LV,</span>
<span class="line" id="L351"> <span class="tok-number">0xD034</span> =&gt; .LV,</span>
<span class="line" id="L352"> <span class="tok-number">0xD050</span> =&gt; .LV,</span>
<span class="line" id="L353"> <span class="tok-number">0xD06C</span> =&gt; .LV,</span>
<span class="line" id="L354"> <span class="tok-number">0xD088</span> =&gt; .LV,</span>
<span class="line" id="L355"> <span class="tok-number">0xD0A4</span> =&gt; .LV,</span>
<span class="line" id="L356"> <span class="tok-number">0xD0C0</span> =&gt; .LV,</span>
<span class="line" id="L357"> <span class="tok-number">0xD0DC</span> =&gt; .LV,</span>
<span class="line" id="L358"> <span class="tok-number">0xD0F8</span> =&gt; .LV,</span>
<span class="line" id="L359"> <span class="tok-number">0xD114</span> =&gt; .LV,</span>
<span class="line" id="L360"> <span class="tok-number">0xD130</span> =&gt; .LV,</span>
<span class="line" id="L361"> <span class="tok-number">0xD14C</span> =&gt; .LV,</span>
<span class="line" id="L362"> <span class="tok-number">0xD168</span> =&gt; .LV,</span>
<span class="line" id="L363"> <span class="tok-number">0xD184</span> =&gt; .LV,</span>
<span class="line" id="L364"> <span class="tok-number">0xD1A0</span> =&gt; .LV,</span>
<span class="line" id="L365"> <span class="tok-number">0xD1BC</span> =&gt; .LV,</span>
<span class="line" id="L366"> <span class="tok-number">0xD1D8</span> =&gt; .LV,</span>
<span class="line" id="L367"> <span class="tok-number">0xD1F4</span> =&gt; .LV,</span>
<span class="line" id="L368"> <span class="tok-number">0xD210</span> =&gt; .LV,</span>
<span class="line" id="L369"> <span class="tok-number">0xD22C</span> =&gt; .LV,</span>
<span class="line" id="L370"> <span class="tok-number">0xD248</span> =&gt; .LV,</span>
<span class="line" id="L371"> <span class="tok-number">0xD264</span> =&gt; .LV,</span>
<span class="line" id="L372"> <span class="tok-number">0xD280</span> =&gt; .LV,</span>
<span class="line" id="L373"> <span class="tok-number">0xD29C</span> =&gt; .LV,</span>
<span class="line" id="L374"> <span class="tok-number">0xD2B8</span> =&gt; .LV,</span>
<span class="line" id="L375"> <span class="tok-number">0xD2D4</span> =&gt; .LV,</span>
<span class="line" id="L376"> <span class="tok-number">0xD2F0</span> =&gt; .LV,</span>
<span class="line" id="L377"> <span class="tok-number">0xD30C</span> =&gt; .LV,</span>
<span class="line" id="L378"> <span class="tok-number">0xD328</span> =&gt; .LV,</span>
<span class="line" id="L379"> <span class="tok-number">0xD344</span> =&gt; .LV,</span>
<span class="line" id="L380"> <span class="tok-number">0xD360</span> =&gt; .LV,</span>
<span class="line" id="L381"> <span class="tok-number">0xD37C</span> =&gt; .LV,</span>
<span class="line" id="L382"> <span class="tok-number">0xD398</span> =&gt; .LV,</span>
<span class="line" id="L383"> <span class="tok-number">0xD3B4</span> =&gt; .LV,</span>
<span class="line" id="L384"> <span class="tok-number">0xD3D0</span> =&gt; .LV,</span>
<span class="line" id="L385"> <span class="tok-number">0xD3EC</span> =&gt; .LV,</span>
<span class="line" id="L386"> <span class="tok-number">0xD408</span> =&gt; .LV,</span>
<span class="line" id="L387"> <span class="tok-number">0xD424</span> =&gt; .LV,</span>
<span class="line" id="L388"> <span class="tok-number">0xD440</span> =&gt; .LV,</span>
<span class="line" id="L389"> <span class="tok-number">0xD45C</span> =&gt; .LV,</span>
<span class="line" id="L390"> <span class="tok-number">0xD478</span> =&gt; .LV,</span>
<span class="line" id="L391"> <span class="tok-number">0xD494</span> =&gt; .LV,</span>
<span class="line" id="L392"> <span class="tok-number">0xD4B0</span> =&gt; .LV,</span>
<span class="line" id="L393"> <span class="tok-number">0xD4CC</span> =&gt; .LV,</span>
<span class="line" id="L394"> <span class="tok-number">0xD4E8</span> =&gt; .LV,</span>
<span class="line" id="L395"> <span class="tok-number">0xD504</span> =&gt; .LV,</span>
<span class="line" id="L396"> <span class="tok-number">0xD520</span> =&gt; .LV,</span>
<span class="line" id="L397"> <span class="tok-number">0xD53C</span> =&gt; .LV,</span>
<span class="line" id="L398"> <span class="tok-number">0xD558</span> =&gt; .LV,</span>
<span class="line" id="L399"> <span class="tok-number">0xD574</span> =&gt; .LV,</span>
<span class="line" id="L400"> <span class="tok-number">0xD590</span> =&gt; .LV,</span>
<span class="line" id="L401"> <span class="tok-number">0xD5AC</span> =&gt; .LV,</span>
<span class="line" id="L402"> <span class="tok-number">0xD5C8</span> =&gt; .LV,</span>
<span class="line" id="L403"> <span class="tok-number">0xD5E4</span> =&gt; .LV,</span>
<span class="line" id="L404"> <span class="tok-number">0xD600</span> =&gt; .LV,</span>
<span class="line" id="L405"> <span class="tok-number">0xD61C</span> =&gt; .LV,</span>
<span class="line" id="L406"> <span class="tok-number">0xD638</span> =&gt; .LV,</span>
<span class="line" id="L407"> <span class="tok-number">0xD654</span> =&gt; .LV,</span>
<span class="line" id="L408"> <span class="tok-number">0xD670</span> =&gt; .LV,</span>
<span class="line" id="L409"> <span class="tok-number">0xD68C</span> =&gt; .LV,</span>
<span class="line" id="L410"> <span class="tok-number">0xD6A8</span> =&gt; .LV,</span>
<span class="line" id="L411"> <span class="tok-number">0xD6C4</span> =&gt; .LV,</span>
<span class="line" id="L412"> <span class="tok-number">0xD6E0</span> =&gt; .LV,</span>
<span class="line" id="L413"> <span class="tok-number">0xD6FC</span> =&gt; .LV,</span>
<span class="line" id="L414"> <span class="tok-number">0xD718</span> =&gt; .LV,</span>
<span class="line" id="L415"> <span class="tok-number">0xD734</span> =&gt; .LV,</span>
<span class="line" id="L416"> <span class="tok-number">0xD750</span> =&gt; .LV,</span>
<span class="line" id="L417"> <span class="tok-number">0xD76C</span> =&gt; .LV,</span>
<span class="line" id="L418"> <span class="tok-number">0xD788</span> =&gt; .LV,</span>
<span class="line" id="L419"> <span class="tok-number">0xAC01</span>...<span class="tok-number">0xAC1B</span> =&gt; .LVT,</span>
<span class="line" id="L420"> <span class="tok-number">0xAC1D</span>...<span class="tok-number">0xAC37</span> =&gt; .LVT,</span>
<span class="line" id="L421"> <span class="tok-number">0xAC39</span>...<span class="tok-number">0xAC53</span> =&gt; .LVT,</span>
<span class="line" id="L422"> <span class="tok-number">0xAC55</span>...<span class="tok-number">0xAC6F</span> =&gt; .LVT,</span>
<span class="line" id="L423"> <span class="tok-number">0xAC71</span>...<span class="tok-number">0xAC8B</span> =&gt; .LVT,</span>
<span class="line" id="L424"> <span class="tok-number">0xAC8D</span>...<span class="tok-number">0xACA7</span> =&gt; .LVT,</span>
<span class="line" id="L425"> <span class="tok-number">0xACA9</span>...<span class="tok-number">0xACC3</span> =&gt; .LVT,</span>
<span class="line" id="L426"> <span class="tok-number">0xACC5</span>...<span class="tok-number">0xACDF</span> =&gt; .LVT,</span>
<span class="line" id="L427"> <span class="tok-number">0xACE1</span>...<span class="tok-number">0xACFB</span> =&gt; .LVT,</span>
<span class="line" id="L428"> <span class="tok-number">0xACFD</span>...<span class="tok-number">0xAD17</span> =&gt; .LVT,</span>
<span class="line" id="L429"> <span class="tok-number">0xAD19</span>...<span class="tok-number">0xAD33</span> =&gt; .LVT,</span>
<span class="line" id="L430"> <span class="tok-number">0xAD35</span>...<span class="tok-number">0xAD4F</span> =&gt; .LVT,</span>
<span class="line" id="L431"> <span class="tok-number">0xAD51</span>...<span class="tok-number">0xAD6B</span> =&gt; .LVT,</span>
<span class="line" id="L432"> <span class="tok-number">0xAD6D</span>...<span class="tok-number">0xAD87</span> =&gt; .LVT,</span>
<span class="line" id="L433"> <span class="tok-number">0xAD89</span>...<span class="tok-number">0xADA3</span> =&gt; .LVT,</span>
<span class="line" id="L434"> <span class="tok-number">0xADA5</span>...<span class="tok-number">0xADBF</span> =&gt; .LVT,</span>
<span class="line" id="L435"> <span class="tok-number">0xADC1</span>...<span class="tok-number">0xADDB</span> =&gt; .LVT,</span>
<span class="line" id="L436"> <span class="tok-number">0xADDD</span>...<span class="tok-number">0xADF7</span> =&gt; .LVT,</span>
<span class="line" id="L437"> <span class="tok-number">0xADF9</span>...<span class="tok-number">0xAE13</span> =&gt; .LVT,</span>
<span class="line" id="L438"> <span class="tok-number">0xAE15</span>...<span class="tok-number">0xAE2F</span> =&gt; .LVT,</span>
<span class="line" id="L439"> <span class="tok-number">0xAE31</span>...<span class="tok-number">0xAE4B</span> =&gt; .LVT,</span>
<span class="line" id="L440"> <span class="tok-number">0xAE4D</span>...<span class="tok-number">0xAE67</span> =&gt; .LVT,</span>
<span class="line" id="L441"> <span class="tok-number">0xAE69</span>...<span class="tok-number">0xAE83</span> =&gt; .LVT,</span>
<span class="line" id="L442"> <span class="tok-number">0xAE85</span>...<span class="tok-number">0xAE9F</span> =&gt; .LVT,</span>
<span class="line" id="L443"> <span class="tok-number">0xAEA1</span>...<span class="tok-number">0xAEBB</span> =&gt; .LVT,</span>
<span class="line" id="L444"> <span class="tok-number">0xAEBD</span>...<span class="tok-number">0xAED7</span> =&gt; .LVT,</span>
<span class="line" id="L445"> <span class="tok-number">0xAED9</span>...<span class="tok-number">0xAEF3</span> =&gt; .LVT,</span>
<span class="line" id="L446"> <span class="tok-number">0xAEF5</span>...<span class="tok-number">0xAF0F</span> =&gt; .LVT,</span>
<span class="line" id="L447"> <span class="tok-number">0xAF11</span>...<span class="tok-number">0xAF2B</span> =&gt; .LVT,</span>
<span class="line" id="L448"> <span class="tok-number">0xAF2D</span>...<span class="tok-number">0xAF47</span> =&gt; .LVT,</span>
<span class="line" id="L449"> <span class="tok-number">0xAF49</span>...<span class="tok-number">0xAF63</span> =&gt; .LVT,</span>
<span class="line" id="L450"> <span class="tok-number">0xAF65</span>...<span class="tok-number">0xAF7F</span> =&gt; .LVT,</span>
<span class="line" id="L451"> <span class="tok-number">0xAF81</span>...<span class="tok-number">0xAF9B</span> =&gt; .LVT,</span>
<span class="line" id="L452"> <span class="tok-number">0xAF9D</span>...<span class="tok-number">0xAFB7</span> =&gt; .LVT,</span>
<span class="line" id="L453"> <span class="tok-number">0xAFB9</span>...<span class="tok-number">0xAFD3</span> =&gt; .LVT,</span>
<span class="line" id="L454"> <span class="tok-number">0xAFD5</span>...<span class="tok-number">0xAFEF</span> =&gt; .LVT,</span>
<span class="line" id="L455"> <span class="tok-number">0xAFF1</span>...<span class="tok-number">0xB00B</span> =&gt; .LVT,</span>
<span class="line" id="L456"> <span class="tok-number">0xB00D</span>...<span class="tok-number">0xB027</span> =&gt; .LVT,</span>
<span class="line" id="L457"> <span class="tok-number">0xB029</span>...<span class="tok-number">0xB043</span> =&gt; .LVT,</span>
<span class="line" id="L458"> <span class="tok-number">0xB045</span>...<span class="tok-number">0xB05F</span> =&gt; .LVT,</span>
<span class="line" id="L459"> <span class="tok-number">0xB061</span>...<span class="tok-number">0xB07B</span> =&gt; .LVT,</span>
<span class="line" id="L460"> <span class="tok-number">0xB07D</span>...<span class="tok-number">0xB097</span> =&gt; .LVT,</span>
<span class="line" id="L461"> <span class="tok-number">0xB099</span>...<span class="tok-number">0xB0B3</span> =&gt; .LVT,</span>
<span class="line" id="L462"> <span class="tok-number">0xB0B5</span>...<span class="tok-number">0xB0CF</span> =&gt; .LVT,</span>
<span class="line" id="L463"> <span class="tok-number">0xB0D1</span>...<span class="tok-number">0xB0EB</span> =&gt; .LVT,</span>
<span class="line" id="L464"> <span class="tok-number">0xB0ED</span>...<span class="tok-number">0xB107</span> =&gt; .LVT,</span>
<span class="line" id="L465"> <span class="tok-number">0xB109</span>...<span class="tok-number">0xB123</span> =&gt; .LVT,</span>
<span class="line" id="L466"> <span class="tok-number">0xB125</span>...<span class="tok-number">0xB13F</span> =&gt; .LVT,</span>
<span class="line" id="L467"> <span class="tok-number">0xB141</span>...<span class="tok-number">0xB15B</span> =&gt; .LVT,</span>
<span class="line" id="L468"> <span class="tok-number">0xB15D</span>...<span class="tok-number">0xB177</span> =&gt; .LVT,</span>
<span class="line" id="L469"> <span class="tok-number">0xB179</span>...<span class="tok-number">0xB193</span> =&gt; .LVT,</span>
<span class="line" id="L470"> <span class="tok-number">0xB195</span>...<span class="tok-number">0xB1AF</span> =&gt; .LVT,</span>
<span class="line" id="L471"> <span class="tok-number">0xB1B1</span>...<span class="tok-number">0xB1CB</span> =&gt; .LVT,</span>
<span class="line" id="L472"> <span class="tok-number">0xB1CD</span>...<span class="tok-number">0xB1E7</span> =&gt; .LVT,</span>
<span class="line" id="L473"> <span class="tok-number">0xB1E9</span>...<span class="tok-number">0xB203</span> =&gt; .LVT,</span>
<span class="line" id="L474"> <span class="tok-number">0xB205</span>...<span class="tok-number">0xB21F</span> =&gt; .LVT,</span>
<span class="line" id="L475"> <span class="tok-number">0xB221</span>...<span class="tok-number">0xB23B</span> =&gt; .LVT,</span>
<span class="line" id="L476"> <span class="tok-number">0xB23D</span>...<span class="tok-number">0xB257</span> =&gt; .LVT,</span>
<span class="line" id="L477"> <span class="tok-number">0xB259</span>...<span class="tok-number">0xB273</span> =&gt; .LVT,</span>
<span class="line" id="L478"> <span class="tok-number">0xB275</span>...<span class="tok-number">0xB28F</span> =&gt; .LVT,</span>
<span class="line" id="L479"> <span class="tok-number">0xB291</span>...<span class="tok-number">0xB2AB</span> =&gt; .LVT,</span>
<span class="line" id="L480"> <span class="tok-number">0xB2AD</span>...<span class="tok-number">0xB2C7</span> =&gt; .LVT,</span>
<span class="line" id="L481"> <span class="tok-number">0xB2C9</span>...<span class="tok-number">0xB2E3</span> =&gt; .LVT,</span>
<span class="line" id="L482"> <span class="tok-number">0xB2E5</span>...<span class="tok-number">0xB2FF</span> =&gt; .LVT,</span>
<span class="line" id="L483"> <span class="tok-number">0xB301</span>...<span class="tok-number">0xB31B</span> =&gt; .LVT,</span>
<span class="line" id="L484"> <span class="tok-number">0xB31D</span>...<span class="tok-number">0xB337</span> =&gt; .LVT,</span>
<span class="line" id="L485"> <span class="tok-number">0xB339</span>...<span class="tok-number">0xB353</span> =&gt; .LVT,</span>
<span class="line" id="L486"> <span class="tok-number">0xB355</span>...<span class="tok-number">0xB36F</span> =&gt; .LVT,</span>
<span class="line" id="L487"> <span class="tok-number">0xB371</span>...<span class="tok-number">0xB38B</span> =&gt; .LVT,</span>
<span class="line" id="L488"> <span class="tok-number">0xB38D</span>...<span class="tok-number">0xB3A7</span> =&gt; .LVT,</span>
<span class="line" id="L489"> <span class="tok-number">0xB3A9</span>...<span class="tok-number">0xB3C3</span> =&gt; .LVT,</span>
<span class="line" id="L490"> <span class="tok-number">0xB3C5</span>...<span class="tok-number">0xB3DF</span> =&gt; .LVT,</span>
<span class="line" id="L491"> <span class="tok-number">0xB3E1</span>...<span class="tok-number">0xB3FB</span> =&gt; .LVT,</span>
<span class="line" id="L492"> <span class="tok-number">0xB3FD</span>...<span class="tok-number">0xB417</span> =&gt; .LVT,</span>
<span class="line" id="L493"> <span class="tok-number">0xB419</span>...<span class="tok-number">0xB433</span> =&gt; .LVT,</span>
<span class="line" id="L494"> <span class="tok-number">0xB435</span>...<span class="tok-number">0xB44F</span> =&gt; .LVT,</span>
<span class="line" id="L495"> <span class="tok-number">0xB451</span>...<span class="tok-number">0xB46B</span> =&gt; .LVT,</span>
<span class="line" id="L496"> <span class="tok-number">0xB46D</span>...<span class="tok-number">0xB487</span> =&gt; .LVT,</span>
<span class="line" id="L497"> <span class="tok-number">0xB489</span>...<span class="tok-number">0xB4A3</span> =&gt; .LVT,</span>
<span class="line" id="L498"> <span class="tok-number">0xB4A5</span>...<span class="tok-number">0xB4BF</span> =&gt; .LVT,</span>
<span class="line" id="L499"> <span class="tok-number">0xB4C1</span>...<span class="tok-number">0xB4DB</span> =&gt; .LVT,</span>
<span class="line" id="L500"> <span class="tok-number">0xB4DD</span>...<span class="tok-number">0xB4F7</span> =&gt; .LVT,</span>
<span class="line" id="L501"> <span class="tok-number">0xB4F9</span>...<span class="tok-number">0xB513</span> =&gt; .LVT,</span>
<span class="line" id="L502"> <span class="tok-number">0xB515</span>...<span class="tok-number">0xB52F</span> =&gt; .LVT,</span>
<span class="line" id="L503"> <span class="tok-number">0xB531</span>...<span class="tok-number">0xB54B</span> =&gt; .LVT,</span>
<span class="line" id="L504"> <span class="tok-number">0xB54D</span>...<span class="tok-number">0xB567</span> =&gt; .LVT,</span>
<span class="line" id="L505"> <span class="tok-number">0xB569</span>...<span class="tok-number">0xB583</span> =&gt; .LVT,</span>
<span class="line" id="L506"> <span class="tok-number">0xB585</span>...<span class="tok-number">0xB59F</span> =&gt; .LVT,</span>
<span class="line" id="L507"> <span class="tok-number">0xB5A1</span>...<span class="tok-number">0xB5BB</span> =&gt; .LVT,</span>
<span class="line" id="L508"> <span class="tok-number">0xB5BD</span>...<span class="tok-number">0xB5D7</span> =&gt; .LVT,</span>
<span class="line" id="L509"> <span class="tok-number">0xB5D9</span>...<span class="tok-number">0xB5F3</span> =&gt; .LVT,</span>
<span class="line" id="L510"> <span class="tok-number">0xB5F5</span>...<span class="tok-number">0xB60F</span> =&gt; .LVT,</span>
<span class="line" id="L511"> <span class="tok-number">0xB611</span>...<span class="tok-number">0xB62B</span> =&gt; .LVT,</span>
<span class="line" id="L512"> <span class="tok-number">0xB62D</span>...<span class="tok-number">0xB647</span> =&gt; .LVT,</span>
<span class="line" id="L513"> <span class="tok-number">0xB649</span>...<span class="tok-number">0xB663</span> =&gt; .LVT,</span>
<span class="line" id="L514"> <span class="tok-number">0xB665</span>...<span class="tok-number">0xB67F</span> =&gt; .LVT,</span>
<span class="line" id="L515"> <span class="tok-number">0xB681</span>...<span class="tok-number">0xB69B</span> =&gt; .LVT,</span>
<span class="line" id="L516"> <span class="tok-number">0xB69D</span>...<span class="tok-number">0xB6B7</span> =&gt; .LVT,</span>
<span class="line" id="L517"> <span class="tok-number">0xB6B9</span>...<span class="tok-number">0xB6D3</span> =&gt; .LVT,</span>
<span class="line" id="L518"> <span class="tok-number">0xB6D5</span>...<span class="tok-number">0xB6EF</span> =&gt; .LVT,</span>
<span class="line" id="L519"> <span class="tok-number">0xB6F1</span>...<span class="tok-number">0xB70B</span> =&gt; .LVT,</span>
<span class="line" id="L520"> <span class="tok-number">0xB70D</span>...<span class="tok-number">0xB727</span> =&gt; .LVT,</span>
<span class="line" id="L521"> <span class="tok-number">0xB729</span>...<span class="tok-number">0xB743</span> =&gt; .LVT,</span>
<span class="line" id="L522"> <span class="tok-number">0xB745</span>...<span class="tok-number">0xB75F</span> =&gt; .LVT,</span>
<span class="line" id="L523"> <span class="tok-number">0xB761</span>...<span class="tok-number">0xB77B</span> =&gt; .LVT,</span>
<span class="line" id="L524"> <span class="tok-number">0xB77D</span>...<span class="tok-number">0xB797</span> =&gt; .LVT,</span>
<span class="line" id="L525"> <span class="tok-number">0xB799</span>...<span class="tok-number">0xB7B3</span> =&gt; .LVT,</span>
<span class="line" id="L526"> <span class="tok-number">0xB7B5</span>...<span class="tok-number">0xB7CF</span> =&gt; .LVT,</span>
<span class="line" id="L527"> <span class="tok-number">0xB7D1</span>...<span class="tok-number">0xB7EB</span> =&gt; .LVT,</span>
<span class="line" id="L528"> <span class="tok-number">0xB7ED</span>...<span class="tok-number">0xB807</span> =&gt; .LVT,</span>
<span class="line" id="L529"> <span class="tok-number">0xB809</span>...<span class="tok-number">0xB823</span> =&gt; .LVT,</span>
<span class="line" id="L530"> <span class="tok-number">0xB825</span>...<span class="tok-number">0xB83F</span> =&gt; .LVT,</span>
<span class="line" id="L531"> <span class="tok-number">0xB841</span>...<span class="tok-number">0xB85B</span> =&gt; .LVT,</span>
<span class="line" id="L532"> <span class="tok-number">0xB85D</span>...<span class="tok-number">0xB877</span> =&gt; .LVT,</span>
<span class="line" id="L533"> <span class="tok-number">0xB879</span>...<span class="tok-number">0xB893</span> =&gt; .LVT,</span>
<span class="line" id="L534"> <span class="tok-number">0xB895</span>...<span class="tok-number">0xB8AF</span> =&gt; .LVT,</span>
<span class="line" id="L535"> <span class="tok-number">0xB8B1</span>...<span class="tok-number">0xB8CB</span> =&gt; .LVT,</span>
<span class="line" id="L536"> <span class="tok-number">0xB8CD</span>...<span class="tok-number">0xB8E7</span> =&gt; .LVT,</span>
<span class="line" id="L537"> <span class="tok-number">0xB8E9</span>...<span class="tok-number">0xB903</span> =&gt; .LVT,</span>
<span class="line" id="L538"> <span class="tok-number">0xB905</span>...<span class="tok-number">0xB91F</span> =&gt; .LVT,</span>
<span class="line" id="L539"> <span class="tok-number">0xB921</span>...<span class="tok-number">0xB93B</span> =&gt; .LVT,</span>
<span class="line" id="L540"> <span class="tok-number">0xB93D</span>...<span class="tok-number">0xB957</span> =&gt; .LVT,</span>
<span class="line" id="L541"> <span class="tok-number">0xB959</span>...<span class="tok-number">0xB973</span> =&gt; .LVT,</span>
<span class="line" id="L542"> <span class="tok-number">0xB975</span>...<span class="tok-number">0xB98F</span> =&gt; .LVT,</span>
<span class="line" id="L543"> <span class="tok-number">0xB991</span>...<span class="tok-number">0xB9AB</span> =&gt; .LVT,</span>
<span class="line" id="L544"> <span class="tok-number">0xB9AD</span>...<span class="tok-number">0xB9C7</span> =&gt; .LVT,</span>
<span class="line" id="L545"> <span class="tok-number">0xB9C9</span>...<span class="tok-number">0xB9E3</span> =&gt; .LVT,</span>
<span class="line" id="L546"> <span class="tok-number">0xB9E5</span>...<span class="tok-number">0xB9FF</span> =&gt; .LVT,</span>
<span class="line" id="L547"> <span class="tok-number">0xBA01</span>...<span class="tok-number">0xBA1B</span> =&gt; .LVT,</span>
<span class="line" id="L548"> <span class="tok-number">0xBA1D</span>...<span class="tok-number">0xBA37</span> =&gt; .LVT,</span>
<span class="line" id="L549"> <span class="tok-number">0xBA39</span>...<span class="tok-number">0xBA53</span> =&gt; .LVT,</span>
<span class="line" id="L550"> <span class="tok-number">0xBA55</span>...<span class="tok-number">0xBA6F</span> =&gt; .LVT,</span>
<span class="line" id="L551"> <span class="tok-number">0xBA71</span>...<span class="tok-number">0xBA8B</span> =&gt; .LVT,</span>
<span class="line" id="L552"> <span class="tok-number">0xBA8D</span>...<span class="tok-number">0xBAA7</span> =&gt; .LVT,</span>
<span class="line" id="L553"> <span class="tok-number">0xBAA9</span>...<span class="tok-number">0xBAC3</span> =&gt; .LVT,</span>
<span class="line" id="L554"> <span class="tok-number">0xBAC5</span>...<span class="tok-number">0xBADF</span> =&gt; .LVT,</span>
<span class="line" id="L555"> <span class="tok-number">0xBAE1</span>...<span class="tok-number">0xBAFB</span> =&gt; .LVT,</span>
<span class="line" id="L556"> <span class="tok-number">0xBAFD</span>...<span class="tok-number">0xBB17</span> =&gt; .LVT,</span>
<span class="line" id="L557"> <span class="tok-number">0xBB19</span>...<span class="tok-number">0xBB33</span> =&gt; .LVT,</span>
<span class="line" id="L558"> <span class="tok-number">0xBB35</span>...<span class="tok-number">0xBB4F</span> =&gt; .LVT,</span>
<span class="line" id="L559"> <span class="tok-number">0xBB51</span>...<span class="tok-number">0xBB6B</span> =&gt; .LVT,</span>
<span class="line" id="L560"> <span class="tok-number">0xBB6D</span>...<span class="tok-number">0xBB87</span> =&gt; .LVT,</span>
<span class="line" id="L561"> <span class="tok-number">0xBB89</span>...<span class="tok-number">0xBBA3</span> =&gt; .LVT,</span>
<span class="line" id="L562"> <span class="tok-number">0xBBA5</span>...<span class="tok-number">0xBBBF</span> =&gt; .LVT,</span>
<span class="line" id="L563"> <span class="tok-number">0xBBC1</span>...<span class="tok-number">0xBBDB</span> =&gt; .LVT,</span>
<span class="line" id="L564"> <span class="tok-number">0xBBDD</span>...<span class="tok-number">0xBBF7</span> =&gt; .LVT,</span>
<span class="line" id="L565"> <span class="tok-number">0xBBF9</span>...<span class="tok-number">0xBC13</span> =&gt; .LVT,</span>
<span class="line" id="L566"> <span class="tok-number">0xBC15</span>...<span class="tok-number">0xBC2F</span> =&gt; .LVT,</span>
<span class="line" id="L567"> <span class="tok-number">0xBC31</span>...<span class="tok-number">0xBC4B</span> =&gt; .LVT,</span>
<span class="line" id="L568"> <span class="tok-number">0xBC4D</span>...<span class="tok-number">0xBC67</span> =&gt; .LVT,</span>
<span class="line" id="L569"> <span class="tok-number">0xBC69</span>...<span class="tok-number">0xBC83</span> =&gt; .LVT,</span>
<span class="line" id="L570"> <span class="tok-number">0xBC85</span>...<span class="tok-number">0xBC9F</span> =&gt; .LVT,</span>
<span class="line" id="L571"> <span class="tok-number">0xBCA1</span>...<span class="tok-number">0xBCBB</span> =&gt; .LVT,</span>
<span class="line" id="L572"> <span class="tok-number">0xBCBD</span>...<span class="tok-number">0xBCD7</span> =&gt; .LVT,</span>
<span class="line" id="L573"> <span class="tok-number">0xBCD9</span>...<span class="tok-number">0xBCF3</span> =&gt; .LVT,</span>
<span class="line" id="L574"> <span class="tok-number">0xBCF5</span>...<span class="tok-number">0xBD0F</span> =&gt; .LVT,</span>
<span class="line" id="L575"> <span class="tok-number">0xBD11</span>...<span class="tok-number">0xBD2B</span> =&gt; .LVT,</span>
<span class="line" id="L576"> <span class="tok-number">0xBD2D</span>...<span class="tok-number">0xBD47</span> =&gt; .LVT,</span>
<span class="line" id="L577"> <span class="tok-number">0xBD49</span>...<span class="tok-number">0xBD63</span> =&gt; .LVT,</span>
<span class="line" id="L578"> <span class="tok-number">0xBD65</span>...<span class="tok-number">0xBD7F</span> =&gt; .LVT,</span>
<span class="line" id="L579"> <span class="tok-number">0xBD81</span>...<span class="tok-number">0xBD9B</span> =&gt; .LVT,</span>
<span class="line" id="L580"> <span class="tok-number">0xBD9D</span>...<span class="tok-number">0xBDB7</span> =&gt; .LVT,</span>
<span class="line" id="L581"> <span class="tok-number">0xBDB9</span>...<span class="tok-number">0xBDD3</span> =&gt; .LVT,</span>
<span class="line" id="L582"> <span class="tok-number">0xBDD5</span>...<span class="tok-number">0xBDEF</span> =&gt; .LVT,</span>
<span class="line" id="L583"> <span class="tok-number">0xBDF1</span>...<span class="tok-number">0xBE0B</span> =&gt; .LVT,</span>
<span class="line" id="L584"> <span class="tok-number">0xBE0D</span>...<span class="tok-number">0xBE27</span> =&gt; .LVT,</span>
<span class="line" id="L585"> <span class="tok-number">0xBE29</span>...<span class="tok-number">0xBE43</span> =&gt; .LVT,</span>
<span class="line" id="L586"> <span class="tok-number">0xBE45</span>...<span class="tok-number">0xBE5F</span> =&gt; .LVT,</span>
<span class="line" id="L587"> <span class="tok-number">0xBE61</span>...<span class="tok-number">0xBE7B</span> =&gt; .LVT,</span>
<span class="line" id="L588"> <span class="tok-number">0xBE7D</span>...<span class="tok-number">0xBE97</span> =&gt; .LVT,</span>
<span class="line" id="L589"> <span class="tok-number">0xBE99</span>...<span class="tok-number">0xBEB3</span> =&gt; .LVT,</span>
<span class="line" id="L590"> <span class="tok-number">0xBEB5</span>...<span class="tok-number">0xBECF</span> =&gt; .LVT,</span>
<span class="line" id="L591"> <span class="tok-number">0xBED1</span>...<span class="tok-number">0xBEEB</span> =&gt; .LVT,</span>
<span class="line" id="L592"> <span class="tok-number">0xBEED</span>...<span class="tok-number">0xBF07</span> =&gt; .LVT,</span>
<span class="line" id="L593"> <span class="tok-number">0xBF09</span>...<span class="tok-number">0xBF23</span> =&gt; .LVT,</span>
<span class="line" id="L594"> <span class="tok-number">0xBF25</span>...<span class="tok-number">0xBF3F</span> =&gt; .LVT,</span>
<span class="line" id="L595"> <span class="tok-number">0xBF41</span>...<span class="tok-number">0xBF5B</span> =&gt; .LVT,</span>
<span class="line" id="L596"> <span class="tok-number">0xBF5D</span>...<span class="tok-number">0xBF77</span> =&gt; .LVT,</span>
<span class="line" id="L597"> <span class="tok-number">0xBF79</span>...<span class="tok-number">0xBF93</span> =&gt; .LVT,</span>
<span class="line" id="L598"> <span class="tok-number">0xBF95</span>...<span class="tok-number">0xBFAF</span> =&gt; .LVT,</span>
<span class="line" id="L599"> <span class="tok-number">0xBFB1</span>...<span class="tok-number">0xBFCB</span> =&gt; .LVT,</span>
<span class="line" id="L600"> <span class="tok-number">0xBFCD</span>...<span class="tok-number">0xBFE7</span> =&gt; .LVT,</span>
<span class="line" id="L601"> <span class="tok-number">0xBFE9</span>...<span class="tok-number">0xC003</span> =&gt; .LVT,</span>
<span class="line" id="L602"> <span class="tok-number">0xC005</span>...<span class="tok-number">0xC01F</span> =&gt; .LVT,</span>
<span class="line" id="L603"> <span class="tok-number">0xC021</span>...<span class="tok-number">0xC03B</span> =&gt; .LVT,</span>
<span class="line" id="L604"> <span class="tok-number">0xC03D</span>...<span class="tok-number">0xC057</span> =&gt; .LVT,</span>
<span class="line" id="L605"> <span class="tok-number">0xC059</span>...<span class="tok-number">0xC073</span> =&gt; .LVT,</span>
<span class="line" id="L606"> <span class="tok-number">0xC075</span>...<span class="tok-number">0xC08F</span> =&gt; .LVT,</span>
<span class="line" id="L607"> <span class="tok-number">0xC091</span>...<span class="tok-number">0xC0AB</span> =&gt; .LVT,</span>
<span class="line" id="L608"> <span class="tok-number">0xC0AD</span>...<span class="tok-number">0xC0C7</span> =&gt; .LVT,</span>
<span class="line" id="L609"> <span class="tok-number">0xC0C9</span>...<span class="tok-number">0xC0E3</span> =&gt; .LVT,</span>
<span class="line" id="L610"> <span class="tok-number">0xC0E5</span>...<span class="tok-number">0xC0FF</span> =&gt; .LVT,</span>
<span class="line" id="L611"> <span class="tok-number">0xC101</span>...<span class="tok-number">0xC11B</span> =&gt; .LVT,</span>
<span class="line" id="L612"> <span class="tok-number">0xC11D</span>...<span class="tok-number">0xC137</span> =&gt; .LVT,</span>
<span class="line" id="L613"> <span class="tok-number">0xC139</span>...<span class="tok-number">0xC153</span> =&gt; .LVT,</span>
<span class="line" id="L614"> <span class="tok-number">0xC155</span>...<span class="tok-number">0xC16F</span> =&gt; .LVT,</span>
<span class="line" id="L615"> <span class="tok-number">0xC171</span>...<span class="tok-number">0xC18B</span> =&gt; .LVT,</span>
<span class="line" id="L616"> <span class="tok-number">0xC18D</span>...<span class="tok-number">0xC1A7</span> =&gt; .LVT,</span>
<span class="line" id="L617"> <span class="tok-number">0xC1A9</span>...<span class="tok-number">0xC1C3</span> =&gt; .LVT,</span>
<span class="line" id="L618"> <span class="tok-number">0xC1C5</span>...<span class="tok-number">0xC1DF</span> =&gt; .LVT,</span>
<span class="line" id="L619"> <span class="tok-number">0xC1E1</span>...<span class="tok-number">0xC1FB</span> =&gt; .LVT,</span>
<span class="line" id="L620"> <span class="tok-number">0xC1FD</span>...<span class="tok-number">0xC217</span> =&gt; .LVT,</span>
<span class="line" id="L621"> <span class="tok-number">0xC219</span>...<span class="tok-number">0xC233</span> =&gt; .LVT,</span>
<span class="line" id="L622"> <span class="tok-number">0xC235</span>...<span class="tok-number">0xC24F</span> =&gt; .LVT,</span>
<span class="line" id="L623"> <span class="tok-number">0xC251</span>...<span class="tok-number">0xC26B</span> =&gt; .LVT,</span>
<span class="line" id="L624"> <span class="tok-number">0xC26D</span>...<span class="tok-number">0xC287</span> =&gt; .LVT,</span>
<span class="line" id="L625"> <span class="tok-number">0xC289</span>...<span class="tok-number">0xC2A3</span> =&gt; .LVT,</span>
<span class="line" id="L626"> <span class="tok-number">0xC2A5</span>...<span class="tok-number">0xC2BF</span> =&gt; .LVT,</span>
<span class="line" id="L627"> <span class="tok-number">0xC2C1</span>...<span class="tok-number">0xC2DB</span> =&gt; .LVT,</span>
<span class="line" id="L628"> <span class="tok-number">0xC2DD</span>...<span class="tok-number">0xC2F7</span> =&gt; .LVT,</span>
<span class="line" id="L629"> <span class="tok-number">0xC2F9</span>...<span class="tok-number">0xC313</span> =&gt; .LVT,</span>
<span class="line" id="L630"> <span class="tok-number">0xC315</span>...<span class="tok-number">0xC32F</span> =&gt; .LVT,</span>
<span class="line" id="L631"> <span class="tok-number">0xC331</span>...<span class="tok-number">0xC34B</span> =&gt; .LVT,</span>
<span class="line" id="L632"> <span class="tok-number">0xC34D</span>...<span class="tok-number">0xC367</span> =&gt; .LVT,</span>
<span class="line" id="L633"> <span class="tok-number">0xC369</span>...<span class="tok-number">0xC383</span> =&gt; .LVT,</span>
<span class="line" id="L634"> <span class="tok-number">0xC385</span>...<span class="tok-number">0xC39F</span> =&gt; .LVT,</span>
<span class="line" id="L635"> <span class="tok-number">0xC3A1</span>...<span class="tok-number">0xC3BB</span> =&gt; .LVT,</span>
<span class="line" id="L636"> <span class="tok-number">0xC3BD</span>...<span class="tok-number">0xC3D7</span> =&gt; .LVT,</span>
<span class="line" id="L637"> <span class="tok-number">0xC3D9</span>...<span class="tok-number">0xC3F3</span> =&gt; .LVT,</span>
<span class="line" id="L638"> <span class="tok-number">0xC3F5</span>...<span class="tok-number">0xC40F</span> =&gt; .LVT,</span>
<span class="line" id="L639"> <span class="tok-number">0xC411</span>...<span class="tok-number">0xC42B</span> =&gt; .LVT,</span>
<span class="line" id="L640"> <span class="tok-number">0xC42D</span>...<span class="tok-number">0xC447</span> =&gt; .LVT,</span>
<span class="line" id="L641"> <span class="tok-number">0xC449</span>...<span class="tok-number">0xC463</span> =&gt; .LVT,</span>
<span class="line" id="L642"> <span class="tok-number">0xC465</span>...<span class="tok-number">0xC47F</span> =&gt; .LVT,</span>
<span class="line" id="L643"> <span class="tok-number">0xC481</span>...<span class="tok-number">0xC49B</span> =&gt; .LVT,</span>
<span class="line" id="L644"> <span class="tok-number">0xC49D</span>...<span class="tok-number">0xC4B7</span> =&gt; .LVT,</span>
<span class="line" id="L645"> <span class="tok-number">0xC4B9</span>...<span class="tok-number">0xC4D3</span> =&gt; .LVT,</span>
<span class="line" id="L646"> <span class="tok-number">0xC4D5</span>...<span class="tok-number">0xC4EF</span> =&gt; .LVT,</span>
<span class="line" id="L647"> <span class="tok-number">0xC4F1</span>...<span class="tok-number">0xC50B</span> =&gt; .LVT,</span>
<span class="line" id="L648"> <span class="tok-number">0xC50D</span>...<span class="tok-number">0xC527</span> =&gt; .LVT,</span>
<span class="line" id="L649"> <span class="tok-number">0xC529</span>...<span class="tok-number">0xC543</span> =&gt; .LVT,</span>
<span class="line" id="L650"> <span class="tok-number">0xC545</span>...<span class="tok-number">0xC55F</span> =&gt; .LVT,</span>
<span class="line" id="L651"> <span class="tok-number">0xC561</span>...<span class="tok-number">0xC57B</span> =&gt; .LVT,</span>
<span class="line" id="L652"> <span class="tok-number">0xC57D</span>...<span class="tok-number">0xC597</span> =&gt; .LVT,</span>
<span class="line" id="L653"> <span class="tok-number">0xC599</span>...<span class="tok-number">0xC5B3</span> =&gt; .LVT,</span>
<span class="line" id="L654"> <span class="tok-number">0xC5B5</span>...<span class="tok-number">0xC5CF</span> =&gt; .LVT,</span>
<span class="line" id="L655"> <span class="tok-number">0xC5D1</span>...<span class="tok-number">0xC5EB</span> =&gt; .LVT,</span>
<span class="line" id="L656"> <span class="tok-number">0xC5ED</span>...<span class="tok-number">0xC607</span> =&gt; .LVT,</span>
<span class="line" id="L657"> <span class="tok-number">0xC609</span>...<span class="tok-number">0xC623</span> =&gt; .LVT,</span>
<span class="line" id="L658"> <span class="tok-number">0xC625</span>...<span class="tok-number">0xC63F</span> =&gt; .LVT,</span>
<span class="line" id="L659"> <span class="tok-number">0xC641</span>...<span class="tok-number">0xC65B</span> =&gt; .LVT,</span>
<span class="line" id="L660"> <span class="tok-number">0xC65D</span>...<span class="tok-number">0xC677</span> =&gt; .LVT,</span>
<span class="line" id="L661"> <span class="tok-number">0xC679</span>...<span class="tok-number">0xC693</span> =&gt; .LVT,</span>
<span class="line" id="L662"> <span class="tok-number">0xC695</span>...<span class="tok-number">0xC6AF</span> =&gt; .LVT,</span>
<span class="line" id="L663"> <span class="tok-number">0xC6B1</span>...<span class="tok-number">0xC6CB</span> =&gt; .LVT,</span>
<span class="line" id="L664"> <span class="tok-number">0xC6CD</span>...<span class="tok-number">0xC6E7</span> =&gt; .LVT,</span>
<span class="line" id="L665"> <span class="tok-number">0xC6E9</span>...<span class="tok-number">0xC703</span> =&gt; .LVT,</span>
<span class="line" id="L666"> <span class="tok-number">0xC705</span>...<span class="tok-number">0xC71F</span> =&gt; .LVT,</span>
<span class="line" id="L667"> <span class="tok-number">0xC721</span>...<span class="tok-number">0xC73B</span> =&gt; .LVT,</span>
<span class="line" id="L668"> <span class="tok-number">0xC73D</span>...<span class="tok-number">0xC757</span> =&gt; .LVT,</span>
<span class="line" id="L669"> <span class="tok-number">0xC759</span>...<span class="tok-number">0xC773</span> =&gt; .LVT,</span>
<span class="line" id="L670"> <span class="tok-number">0xC775</span>...<span class="tok-number">0xC78F</span> =&gt; .LVT,</span>
<span class="line" id="L671"> <span class="tok-number">0xC791</span>...<span class="tok-number">0xC7AB</span> =&gt; .LVT,</span>
<span class="line" id="L672"> <span class="tok-number">0xC7AD</span>...<span class="tok-number">0xC7C7</span> =&gt; .LVT,</span>
<span class="line" id="L673"> <span class="tok-number">0xC7C9</span>...<span class="tok-number">0xC7E3</span> =&gt; .LVT,</span>
<span class="line" id="L674"> <span class="tok-number">0xC7E5</span>...<span class="tok-number">0xC7FF</span> =&gt; .LVT,</span>
<span class="line" id="L675"> <span class="tok-number">0xC801</span>...<span class="tok-number">0xC81B</span> =&gt; .LVT,</span>
<span class="line" id="L676"> <span class="tok-number">0xC81D</span>...<span class="tok-number">0xC837</span> =&gt; .LVT,</span>
<span class="line" id="L677"> <span class="tok-number">0xC839</span>...<span class="tok-number">0xC853</span> =&gt; .LVT,</span>
<span class="line" id="L678"> <span class="tok-number">0xC855</span>...<span class="tok-number">0xC86F</span> =&gt; .LVT,</span>
<span class="line" id="L679"> <span class="tok-number">0xC871</span>...<span class="tok-number">0xC88B</span> =&gt; .LVT,</span>
<span class="line" id="L680"> <span class="tok-number">0xC88D</span>...<span class="tok-number">0xC8A7</span> =&gt; .LVT,</span>
<span class="line" id="L681"> <span class="tok-number">0xC8A9</span>...<span class="tok-number">0xC8C3</span> =&gt; .LVT,</span>
<span class="line" id="L682"> <span class="tok-number">0xC8C5</span>...<span class="tok-number">0xC8DF</span> =&gt; .LVT,</span>
<span class="line" id="L683"> <span class="tok-number">0xC8E1</span>...<span class="tok-number">0xC8FB</span> =&gt; .LVT,</span>
<span class="line" id="L684"> <span class="tok-number">0xC8FD</span>...<span class="tok-number">0xC917</span> =&gt; .LVT,</span>
<span class="line" id="L685"> <span class="tok-number">0xC919</span>...<span class="tok-number">0xC933</span> =&gt; .LVT,</span>
<span class="line" id="L686"> <span class="tok-number">0xC935</span>...<span class="tok-number">0xC94F</span> =&gt; .LVT,</span>
<span class="line" id="L687"> <span class="tok-number">0xC951</span>...<span class="tok-number">0xC96B</span> =&gt; .LVT,</span>
<span class="line" id="L688"> <span class="tok-number">0xC96D</span>...<span class="tok-number">0xC987</span> =&gt; .LVT,</span>
<span class="line" id="L689"> <span class="tok-number">0xC989</span>...<span class="tok-number">0xC9A3</span> =&gt; .LVT,</span>
<span class="line" id="L690"> <span class="tok-number">0xC9A5</span>...<span class="tok-number">0xC9BF</span> =&gt; .LVT,</span>
<span class="line" id="L691"> <span class="tok-number">0xC9C1</span>...<span class="tok-number">0xC9DB</span> =&gt; .LVT,</span>
<span class="line" id="L692"> <span class="tok-number">0xC9DD</span>...<span class="tok-number">0xC9F7</span> =&gt; .LVT,</span>
<span class="line" id="L693"> <span class="tok-number">0xC9F9</span>...<span class="tok-number">0xCA13</span> =&gt; .LVT,</span>
<span class="line" id="L694"> <span class="tok-number">0xCA15</span>...<span class="tok-number">0xCA2F</span> =&gt; .LVT,</span>
<span class="line" id="L695"> <span class="tok-number">0xCA31</span>...<span class="tok-number">0xCA4B</span> =&gt; .LVT,</span>
<span class="line" id="L696"> <span class="tok-number">0xCA4D</span>...<span class="tok-number">0xCA67</span> =&gt; .LVT,</span>
<span class="line" id="L697"> <span class="tok-number">0xCA69</span>...<span class="tok-number">0xCA83</span> =&gt; .LVT,</span>
<span class="line" id="L698"> <span class="tok-number">0xCA85</span>...<span class="tok-number">0xCA9F</span> =&gt; .LVT,</span>
<span class="line" id="L699"> <span class="tok-number">0xCAA1</span>...<span class="tok-number">0xCABB</span> =&gt; .LVT,</span>
<span class="line" id="L700"> <span class="tok-number">0xCABD</span>...<span class="tok-number">0xCAD7</span> =&gt; .LVT,</span>
<span class="line" id="L701"> <span class="tok-number">0xCAD9</span>...<span class="tok-number">0xCAF3</span> =&gt; .LVT,</span>
<span class="line" id="L702"> <span class="tok-number">0xCAF5</span>...<span class="tok-number">0xCB0F</span> =&gt; .LVT,</span>
<span class="line" id="L703"> <span class="tok-number">0xCB11</span>...<span class="tok-number">0xCB2B</span> =&gt; .LVT,</span>
<span class="line" id="L704"> <span class="tok-number">0xCB2D</span>...<span class="tok-number">0xCB47</span> =&gt; .LVT,</span>
<span class="line" id="L705"> <span class="tok-number">0xCB49</span>...<span class="tok-number">0xCB63</span> =&gt; .LVT,</span>
<span class="line" id="L706"> <span class="tok-number">0xCB65</span>...<span class="tok-number">0xCB7F</span> =&gt; .LVT,</span>
<span class="line" id="L707"> <span class="tok-number">0xCB81</span>...<span class="tok-number">0xCB9B</span> =&gt; .LVT,</span>
<span class="line" id="L708"> <span class="tok-number">0xCB9D</span>...<span class="tok-number">0xCBB7</span> =&gt; .LVT,</span>
<span class="line" id="L709"> <span class="tok-number">0xCBB9</span>...<span class="tok-number">0xCBD3</span> =&gt; .LVT,</span>
<span class="line" id="L710"> <span class="tok-number">0xCBD5</span>...<span class="tok-number">0xCBEF</span> =&gt; .LVT,</span>
<span class="line" id="L711"> <span class="tok-number">0xCBF1</span>...<span class="tok-number">0xCC0B</span> =&gt; .LVT,</span>
<span class="line" id="L712"> <span class="tok-number">0xCC0D</span>...<span class="tok-number">0xCC27</span> =&gt; .LVT,</span>
<span class="line" id="L713"> <span class="tok-number">0xCC29</span>...<span class="tok-number">0xCC43</span> =&gt; .LVT,</span>
<span class="line" id="L714"> <span class="tok-number">0xCC45</span>...<span class="tok-number">0xCC5F</span> =&gt; .LVT,</span>
<span class="line" id="L715"> <span class="tok-number">0xCC61</span>...<span class="tok-number">0xCC7B</span> =&gt; .LVT,</span>
<span class="line" id="L716"> <span class="tok-number">0xCC7D</span>...<span class="tok-number">0xCC97</span> =&gt; .LVT,</span>
<span class="line" id="L717"> <span class="tok-number">0xCC99</span>...<span class="tok-number">0xCCB3</span> =&gt; .LVT,</span>
<span class="line" id="L718"> <span class="tok-number">0xCCB5</span>...<span class="tok-number">0xCCCF</span> =&gt; .LVT,</span>
<span class="line" id="L719"> <span class="tok-number">0xCCD1</span>...<span class="tok-number">0xCCEB</span> =&gt; .LVT,</span>
<span class="line" id="L720"> <span class="tok-number">0xCCED</span>...<span class="tok-number">0xCD07</span> =&gt; .LVT,</span>
<span class="line" id="L721"> <span class="tok-number">0xCD09</span>...<span class="tok-number">0xCD23</span> =&gt; .LVT,</span>
<span class="line" id="L722"> <span class="tok-number">0xCD25</span>...<span class="tok-number">0xCD3F</span> =&gt; .LVT,</span>
<span class="line" id="L723"> <span class="tok-number">0xCD41</span>...<span class="tok-number">0xCD5B</span> =&gt; .LVT,</span>
<span class="line" id="L724"> <span class="tok-number">0xCD5D</span>...<span class="tok-number">0xCD77</span> =&gt; .LVT,</span>
<span class="line" id="L725"> <span class="tok-number">0xCD79</span>...<span class="tok-number">0xCD93</span> =&gt; .LVT,</span>
<span class="line" id="L726"> <span class="tok-number">0xCD95</span>...<span class="tok-number">0xCDAF</span> =&gt; .LVT,</span>
<span class="line" id="L727"> <span class="tok-number">0xCDB1</span>...<span class="tok-number">0xCDCB</span> =&gt; .LVT,</span>
<span class="line" id="L728"> <span class="tok-number">0xCDCD</span>...<span class="tok-number">0xCDE7</span> =&gt; .LVT,</span>
<span class="line" id="L729"> <span class="tok-number">0xCDE9</span>...<span class="tok-number">0xCE03</span> =&gt; .LVT,</span>
<span class="line" id="L730"> <span class="tok-number">0xCE05</span>...<span class="tok-number">0xCE1F</span> =&gt; .LVT,</span>
<span class="line" id="L731"> <span class="tok-number">0xCE21</span>...<span class="tok-number">0xCE3B</span> =&gt; .LVT,</span>
<span class="line" id="L732"> <span class="tok-number">0xCE3D</span>...<span class="tok-number">0xCE57</span> =&gt; .LVT,</span>
<span class="line" id="L733"> <span class="tok-number">0xCE59</span>...<span class="tok-number">0xCE73</span> =&gt; .LVT,</span>
<span class="line" id="L734"> <span class="tok-number">0xCE75</span>...<span class="tok-number">0xCE8F</span> =&gt; .LVT,</span>
<span class="line" id="L735"> <span class="tok-number">0xCE91</span>...<span class="tok-number">0xCEAB</span> =&gt; .LVT,</span>
<span class="line" id="L736"> <span class="tok-number">0xCEAD</span>...<span class="tok-number">0xCEC7</span> =&gt; .LVT,</span>
<span class="line" id="L737"> <span class="tok-number">0xCEC9</span>...<span class="tok-number">0xCEE3</span> =&gt; .LVT,</span>
<span class="line" id="L738"> <span class="tok-number">0xCEE5</span>...<span class="tok-number">0xCEFF</span> =&gt; .LVT,</span>
<span class="line" id="L739"> <span class="tok-number">0xCF01</span>...<span class="tok-number">0xCF1B</span> =&gt; .LVT,</span>
<span class="line" id="L740"> <span class="tok-number">0xCF1D</span>...<span class="tok-number">0xCF37</span> =&gt; .LVT,</span>
<span class="line" id="L741"> <span class="tok-number">0xCF39</span>...<span class="tok-number">0xCF53</span> =&gt; .LVT,</span>
<span class="line" id="L742"> <span class="tok-number">0xCF55</span>...<span class="tok-number">0xCF6F</span> =&gt; .LVT,</span>
<span class="line" id="L743"> <span class="tok-number">0xCF71</span>...<span class="tok-number">0xCF8B</span> =&gt; .LVT,</span>
<span class="line" id="L744"> <span class="tok-number">0xCF8D</span>...<span class="tok-number">0xCFA7</span> =&gt; .LVT,</span>
<span class="line" id="L745"> <span class="tok-number">0xCFA9</span>...<span class="tok-number">0xCFC3</span> =&gt; .LVT,</span>
<span class="line" id="L746"> <span class="tok-number">0xCFC5</span>...<span class="tok-number">0xCFDF</span> =&gt; .LVT,</span>
<span class="line" id="L747"> <span class="tok-number">0xCFE1</span>...<span class="tok-number">0xCFFB</span> =&gt; .LVT,</span>
<span class="line" id="L748"> <span class="tok-number">0xCFFD</span>...<span class="tok-number">0xD017</span> =&gt; .LVT,</span>
<span class="line" id="L749"> <span class="tok-number">0xD019</span>...<span class="tok-number">0xD033</span> =&gt; .LVT,</span>
<span class="line" id="L750"> <span class="tok-number">0xD035</span>...<span class="tok-number">0xD04F</span> =&gt; .LVT,</span>
<span class="line" id="L751"> <span class="tok-number">0xD051</span>...<span class="tok-number">0xD06B</span> =&gt; .LVT,</span>
<span class="line" id="L752"> <span class="tok-number">0xD06D</span>...<span class="tok-number">0xD087</span> =&gt; .LVT,</span>
<span class="line" id="L753"> <span class="tok-number">0xD089</span>...<span class="tok-number">0xD0A3</span> =&gt; .LVT,</span>
<span class="line" id="L754"> <span class="tok-number">0xD0A5</span>...<span class="tok-number">0xD0BF</span> =&gt; .LVT,</span>
<span class="line" id="L755"> <span class="tok-number">0xD0C1</span>...<span class="tok-number">0xD0DB</span> =&gt; .LVT,</span>
<span class="line" id="L756"> <span class="tok-number">0xD0DD</span>...<span class="tok-number">0xD0F7</span> =&gt; .LVT,</span>
<span class="line" id="L757"> <span class="tok-number">0xD0F9</span>...<span class="tok-number">0xD113</span> =&gt; .LVT,</span>
<span class="line" id="L758"> <span class="tok-number">0xD115</span>...<span class="tok-number">0xD12F</span> =&gt; .LVT,</span>
<span class="line" id="L759"> <span class="tok-number">0xD131</span>...<span class="tok-number">0xD14B</span> =&gt; .LVT,</span>
<span class="line" id="L760"> <span class="tok-number">0xD14D</span>...<span class="tok-number">0xD167</span> =&gt; .LVT,</span>
<span class="line" id="L761"> <span class="tok-number">0xD169</span>...<span class="tok-number">0xD183</span> =&gt; .LVT,</span>
<span class="line" id="L762"> <span class="tok-number">0xD185</span>...<span class="tok-number">0xD19F</span> =&gt; .LVT,</span>
<span class="line" id="L763"> <span class="tok-number">0xD1A1</span>...<span class="tok-number">0xD1BB</span> =&gt; .LVT,</span>
<span class="line" id="L764"> <span class="tok-number">0xD1BD</span>...<span class="tok-number">0xD1D7</span> =&gt; .LVT,</span>
<span class="line" id="L765"> <span class="tok-number">0xD1D9</span>...<span class="tok-number">0xD1F3</span> =&gt; .LVT,</span>
<span class="line" id="L766"> <span class="tok-number">0xD1F5</span>...<span class="tok-number">0xD20F</span> =&gt; .LVT,</span>
<span class="line" id="L767"> <span class="tok-number">0xD211</span>...<span class="tok-number">0xD22B</span> =&gt; .LVT,</span>
<span class="line" id="L768"> <span class="tok-number">0xD22D</span>...<span class="tok-number">0xD247</span> =&gt; .LVT,</span>
<span class="line" id="L769"> <span class="tok-number">0xD249</span>...<span class="tok-number">0xD263</span> =&gt; .LVT,</span>
<span class="line" id="L770"> <span class="tok-number">0xD265</span>...<span class="tok-number">0xD27F</span> =&gt; .LVT,</span>
<span class="line" id="L771"> <span class="tok-number">0xD281</span>...<span class="tok-number">0xD29B</span> =&gt; .LVT,</span>
<span class="line" id="L772"> <span class="tok-number">0xD29D</span>...<span class="tok-number">0xD2B7</span> =&gt; .LVT,</span>
<span class="line" id="L773"> <span class="tok-number">0xD2B9</span>...<span class="tok-number">0xD2D3</span> =&gt; .LVT,</span>
<span class="line" id="L774"> <span class="tok-number">0xD2D5</span>...<span class="tok-number">0xD2EF</span> =&gt; .LVT,</span>
<span class="line" id="L775"> <span class="tok-number">0xD2F1</span>...<span class="tok-number">0xD30B</span> =&gt; .LVT,</span>
<span class="line" id="L776"> <span class="tok-number">0xD30D</span>...<span class="tok-number">0xD327</span> =&gt; .LVT,</span>
<span class="line" id="L777"> <span class="tok-number">0xD329</span>...<span class="tok-number">0xD343</span> =&gt; .LVT,</span>
<span class="line" id="L778"> <span class="tok-number">0xD345</span>...<span class="tok-number">0xD35F</span> =&gt; .LVT,</span>
<span class="line" id="L779"> <span class="tok-number">0xD361</span>...<span class="tok-number">0xD37B</span> =&gt; .LVT,</span>
<span class="line" id="L780"> <span class="tok-number">0xD37D</span>...<span class="tok-number">0xD397</span> =&gt; .LVT,</span>
<span class="line" id="L781"> <span class="tok-number">0xD399</span>...<span class="tok-number">0xD3B3</span> =&gt; .LVT,</span>
<span class="line" id="L782"> <span class="tok-number">0xD3B5</span>...<span class="tok-number">0xD3CF</span> =&gt; .LVT,</span>
<span class="line" id="L783"> <span class="tok-number">0xD3D1</span>...<span class="tok-number">0xD3EB</span> =&gt; .LVT,</span>
<span class="line" id="L784"> <span class="tok-number">0xD3ED</span>...<span class="tok-number">0xD407</span> =&gt; .LVT,</span>
<span class="line" id="L785"> <span class="tok-number">0xD409</span>...<span class="tok-number">0xD423</span> =&gt; .LVT,</span>
<span class="line" id="L786"> <span class="tok-number">0xD425</span>...<span class="tok-number">0xD43F</span> =&gt; .LVT,</span>
<span class="line" id="L787"> <span class="tok-number">0xD441</span>...<span class="tok-number">0xD45B</span> =&gt; .LVT,</span>
<span class="line" id="L788"> <span class="tok-number">0xD45D</span>...<span class="tok-number">0xD477</span> =&gt; .LVT,</span>
<span class="line" id="L789"> <span class="tok-number">0xD479</span>...<span class="tok-number">0xD493</span> =&gt; .LVT,</span>
<span class="line" id="L790"> <span class="tok-number">0xD495</span>...<span class="tok-number">0xD4AF</span> =&gt; .LVT,</span>
<span class="line" id="L791"> <span class="tok-number">0xD4B1</span>...<span class="tok-number">0xD4CB</span> =&gt; .LVT,</span>
<span class="line" id="L792"> <span class="tok-number">0xD4CD</span>...<span class="tok-number">0xD4E7</span> =&gt; .LVT,</span>
<span class="line" id="L793"> <span class="tok-number">0xD4E9</span>...<span class="tok-number">0xD503</span> =&gt; .LVT,</span>
<span class="line" id="L794"> <span class="tok-number">0xD505</span>...<span class="tok-number">0xD51F</span> =&gt; .LVT,</span>
<span class="line" id="L795"> <span class="tok-number">0xD521</span>...<span class="tok-number">0xD53B</span> =&gt; .LVT,</span>
<span class="line" id="L796"> <span class="tok-number">0xD53D</span>...<span class="tok-number">0xD557</span> =&gt; .LVT,</span>
<span class="line" id="L797"> <span class="tok-number">0xD559</span>...<span class="tok-number">0xD573</span> =&gt; .LVT,</span>
<span class="line" id="L798"> <span class="tok-number">0xD575</span>...<span class="tok-number">0xD58F</span> =&gt; .LVT,</span>
<span class="line" id="L799"> <span class="tok-number">0xD591</span>...<span class="tok-number">0xD5AB</span> =&gt; .LVT,</span>
<span class="line" id="L800"> <span class="tok-number">0xD5AD</span>...<span class="tok-number">0xD5C7</span> =&gt; .LVT,</span>
<span class="line" id="L801"> <span class="tok-number">0xD5C9</span>...<span class="tok-number">0xD5E3</span> =&gt; .LVT,</span>
<span class="line" id="L802"> <span class="tok-number">0xD5E5</span>...<span class="tok-number">0xD5FF</span> =&gt; .LVT,</span>
<span class="line" id="L803"> <span class="tok-number">0xD601</span>...<span class="tok-number">0xD61B</span> =&gt; .LVT,</span>
<span class="line" id="L804"> <span class="tok-number">0xD61D</span>...<span class="tok-number">0xD637</span> =&gt; .LVT,</span>
<span class="line" id="L805"> <span class="tok-number">0xD639</span>...<span class="tok-number">0xD653</span> =&gt; .LVT,</span>
<span class="line" id="L806"> <span class="tok-number">0xD655</span>...<span class="tok-number">0xD66F</span> =&gt; .LVT,</span>
<span class="line" id="L807"> <span class="tok-number">0xD671</span>...<span class="tok-number">0xD68B</span> =&gt; .LVT,</span>
<span class="line" id="L808"> <span class="tok-number">0xD68D</span>...<span class="tok-number">0xD6A7</span> =&gt; .LVT,</span>
<span class="line" id="L809"> <span class="tok-number">0xD6A9</span>...<span class="tok-number">0xD6C3</span> =&gt; .LVT,</span>
<span class="line" id="L810"> <span class="tok-number">0xD6C5</span>...<span class="tok-number">0xD6DF</span> =&gt; .LVT,</span>
<span class="line" id="L811"> <span class="tok-number">0xD6E1</span>...<span class="tok-number">0xD6FB</span> =&gt; .LVT,</span>
<span class="line" id="L812"> <span class="tok-number">0xD6FD</span>...<span class="tok-number">0xD717</span> =&gt; .LVT,</span>
<span class="line" id="L813"> <span class="tok-number">0xD719</span>...<span class="tok-number">0xD733</span> =&gt; .LVT,</span>
<span class="line" id="L814"> <span class="tok-number">0xD735</span>...<span class="tok-number">0xD74F</span> =&gt; .LVT,</span>
<span class="line" id="L815"> <span class="tok-number">0xD751</span>...<span class="tok-number">0xD76B</span> =&gt; .LVT,</span>
<span class="line" id="L816"> <span class="tok-number">0xD76D</span>...<span class="tok-number">0xD787</span> =&gt; .LVT,</span>
<span class="line" id="L817"> <span class="tok-number">0xD789</span>...<span class="tok-number">0xD7A3</span> =&gt; .LVT,</span>
<span class="line" id="L818"> <span class="tok-kw">else</span> =&gt; <span class="tok-null">null</span>,</span>
<span class="line" id="L819"> };</span>
<span class="line" id="L820">}</span>
<span class="line" id="L821"></span>
</code></pre></body>
</html>

Some files were not shown because too many files have changed in this diff Show more