╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Title.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
338 ".#..#.", 339 }, 340 'X' => .{ 341 "#....#", 342 ".#..#.", 343 ".#..#.", 344 "..##..", 345 "..##..", 346 "..##..", 347 ".#..#.", 348 ".#..#.", 349 "#....#", 350 }, 351 'Y' => .{ 352 "#....#", 353 ".#..#.", 354 ".#..#.", 355 "..##..", 356 "..##..", 357 "..##..", 358 "..##..", 359 "..##..", 360 "..##..", 361 }, 362 'Z' => .{ 363 "######", 364 "....#.", 365 "....#.", 366 "...#..", 367 "..##..", 368 "..#...", 369 ".#....", 370 ".#....", 371 "######", 372 }, 373 '0' => .{ 374 ".####.", 375 "#...##", 376 "#..#.#", 377 "#..#.#", 378 "#.#..#", 379 "#.#..#", 380 "##...#", 381 "#....#", 382 ".####.", 383 }, 384 '1' => .{ 385 "..##..", 386 ".###..", 387 "..##..", 388 "..##..", 389 "..##..", 390 "..##..", 391 "..##..", 392 "..##..", 393 "######", 394 }, 395 '2' => .{ 396 ".####.", 397 "#....#", 398 ".....#", 399 "....#.", 400 "...#..", 401 "..#...", 402 ".#....", 403 "#.....", 404 "######", 405 }, 406 '3' => .{ 407 ".####.", 408 "#....#", 409 ".....#", 410 ".....#", 411 ".####.", 412 ".....#", 413 ".....#", 414 "#....#", 415 ".####.", 416 }, 417 '4' => .{ 418 "....#.", 419 "...##.", 420 "..#.#.", 421 ".#..#.", 422 "#...#.", 423 "######", 424 "....#.", 425 "....#.", 426 "....#.", 427 }, 428 '5' => .{ 429 "######", 430 "#.....", 431 "#.....", 432 "#.....", 433 "#####.", 434 ".....#", 435 ".....#", 436 "#....#", 437 ".####.", 438 }, 439 '6' => .{ 440 ".####.", 441 "#....#", 442 "#.....", 443 "#.....", 444 "#####.", 445 "#....#", 446 "#....#", 447 "#....#", 448 ".####.", 449 }, 450 '7' => .{ 451 "######", 452 ".....#", 453 "....#.", 454 "....#.", 455 "...#..", 456 "...#..", 457 "..#...", 458 "..#...", 459 ".#....", 460 }, 461 '8' => .{ 462 ".####.", 463 "#....#", 464 "#....#", 465 "#....#", 466 ".####.", 467 "#....#", 468 "#....#", 469 "#....#", 470 ".####.", 471 }, 472 '9' => .{ 473 ".####.", 474 "#....#", 475 "#....#", 476 "#....#", 477 ".#####", 478 ".....#", 479 ".....#", 480 "#....#", 481 ".####.", 482 }, 483 '-' => .{ 484 "......", 485 "......", 486 "......", 487 "......", 488 ".####.", 489 "......", 490 "......", 491 "......", 492 "......", 493 }, 494 '.' => .{ 495 "......", 496 "......", 497 "......", 498 "......", 499 "......", 500 "......", 501 "......", 502 "..##..", 503 "..##..", 504 }, 505 '?' => .{ 506 ".####.", 507 "#....#", 508 ".....#", 509 "....#.", 510 "..##..", 511 "..##..", 512 "......", 513 "..##..", 514 "..##..", 515 }, 516 '!' => .{ 517 "..##..", 518 "..##..", 519 "..##..", 520 "..##..", 521 "..##..", 522 "..##..", 523 "......", 524 "..##..", 525 "..##..", 526 }, 527 '\'' => .{ 528 "..##..", 529 "..##..", 530 "...#..", 531 "......", 532 "......", 533 "......", 534 "......", 535 "......", 536 "......", 537 }, 538 ',' => .{ 539 "......", 540 "......", 541 "......", 542 "......", 543 "......", 544 "......", 545 "..##..", 546 "..##..", 547 "..#...", 548 }, 549 ':' => .{ 550 "......", 551 "......", 552 "..##..", 553 "..##..", 554 "......", 555 "......", 556 "......", 557 "..##..", 558 "..##..", 559 }, 560 '/' => .{ 561 ".....#", 562 "....#.", 563 "....#.", 564 "...#..", 565 "...#..", 566 "..#...", 567 "..#...", 568 ".#....", 569 "#.....", 570 }, 571 else => null, 572 }; 573 } 574 575 // whether every char of `text` has a glyph 576 pub fn covers(text: []const u8) bool { 577 for (text) |c| { 578 if (glyphFor(c) == null) return false; 579 } 580 return true; 581 } 582 583 // map a 2x3 sub-pixel pattern to its corresponding sextant codepoint 584 fn sextantCodepoint(pattern: u6) u21 { 585 return switch (pattern) { 586 0b000000 => ' ', 587 0b010101 => 0x258C, // ▌ left half block 588 0b101010 => 0x2590, // ▐ right half block 589 0b111111 => 0x2588, // █ full block 590 else => blk: { 591 var offset: u21 = @as(u21, pattern) - 1; 592 if (pattern > 0b010101) offset -= 1; 593 if (pattern > 0b101010) offset -= 1; 594 break :blk 0x1FB00 + offset; 595 }, 596 }; 597 } 598 599 fn renderTitle(allocator: std.mem.Allocator, input: []const u8, style: Style) ![]const u8 { 600 var rows: [3]std.ArrayList(u8) = .{ .empty, .empty, .empty }; 601 defer for (&rows) |*r| r.deinit(allocator); 602 603 var first = true; 604 for (input) |c| { 605 const glyph = glyphFor(c) orelse continue; 606 607 // scanlines: keep on-pixels only at even bitmap rows. 608 var kept: [9][6]bool = std.mem.zeroes([9][6]bool); 609 for (0..9) |r| { 610 if (style == .scanlines and r % 2 != 0) continue; 611 for (0..6) |col| { 612 kept[r][col] = glyph[r][col] == '#'; 613 } 614 } 615 616 if (!first) { 617 for (&rows) |*r| try r.append(allocator, ' '); 618 } 619 first = false; 620 621 for (0..3) |text_row| { 622 for (0..3) |text_col| { 623 var pattern: u6 = 0; 624 for (0..3) |sub_row| { 625 for (0..2) |sub_col| { 626 const row_idx = text_row * 3 + sub_row; 627 const col_idx = text_col * 2 + sub_col; 628 if (kept[row_idx][col_idx]) { 629 pattern |= @as(u6, 1) << @intCast(sub_row * 2 + sub_col); 630 } 631 } 632 } 633 const cp = sextantCodepoint(pattern); 634 var utf8_buf: [4]u8 = undefined; 635 const len = try std.unicode.utf8Encode(cp, &utf8_buf); 636 try rows[text_row].appendSlice(allocator, utf8_buf[0..len]); 637 } 638 } 639 } 640 641 var out: std.ArrayList(u8) = .empty; 642 errdefer out.deinit(allocator); 643 try out.appendSlice(allocator, rows[0].items); 644 try out.append(allocator, '\n'); 645 try out.appendSlice(allocator, rows[1].items); 646 try out.append(allocator, '\n'); 647 try out.appendSlice(allocator, rows[2].items); 648 return out.toOwnedSlice(allocator); 649 } 650