1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 15:47:35 +00:00

Get nyancat nyanning in Serenity.

I found a cute program that renders an animated nyancat in the terminal.
This patch adds enough hackery to get it working correctly. :^)
This commit is contained in:
Andreas Kling 2019-02-03 16:11:28 +01:00
parent 3944c00f23
commit dddd0e7b03
15 changed files with 341 additions and 64 deletions

View file

@ -1,4 +1,5 @@
#include "Terminal.h"
#include "XtermColors.h"
#include <AK/AKString.h>
#include <AK/StringBuilder.h>
#include <SharedGraphics/Font.h>
@ -72,12 +73,12 @@ Terminal::Line::~Line()
delete [] attributes;
}
void Terminal::Line::clear()
void Terminal::Line::clear(Attribute attribute)
{
dirty = true;
memset(characters, ' ', length);
for (word i = 0 ; i < length; ++i)
attributes[i].reset();
attributes[i] = attribute;
}
Terminal::~Terminal()
@ -91,7 +92,7 @@ Terminal::~Terminal()
void Terminal::clear()
{
for (size_t i = 0; i < rows(); ++i)
line(i).clear();
line(i).clear(m_current_attribute);
set_cursor(0, 0);
}
@ -125,50 +126,22 @@ unsigned parse_uint(const String& str, bool& ok)
return value;
}
enum ANSIColor : byte {
Black = 0,
Red,
Green,
Brown,
Blue,
Magenta,
Cyan,
LightGray,
DarkGray,
BrightRed,
BrightGreen,
Yellow,
BrightBlue,
BrightMagenta,
BrightCyan,
White,
};
static inline Color ansi_color(unsigned color)
static inline Color lookup_color(unsigned color)
{
static const RGBA32 s_ansi_color[16] = {
make_rgb(0, 0, 0), // Black
make_rgb(225, 56, 43), // Red
make_rgb(57, 181, 74), // Green
make_rgb(255, 199, 6), // Brown
make_rgb(0, 111, 184), // Blue
make_rgb(118, 38, 113), // Magenta
make_rgb(44, 181, 233), // Cyan
make_rgb(204, 204, 204), // LightGray
make_rgb(128, 128, 128), // DarkGray
make_rgb(255, 0, 0), // BrightRed
make_rgb(0, 255, 0), // BrightGreen
make_rgb(255, 255, 0), // Yellow
make_rgb(0, 0, 255), // BrightBlue
make_rgb(255, 0, 255), // BrightMagenta
make_rgb(0, 255, 255), // BrightCyan
make_rgb(255, 255, 255), // White
};
return s_ansi_color[color];
return xterm_colors[color];
}
void Terminal::escape$m(const Vector<unsigned>& params)
{
if (params.size() == 3 && params[1] == 5) {
if (params[0] == 38) {
m_current_attribute.foreground_color = params[2];
return;
} else if (params[0] == 48) {
m_current_attribute.background_color = params[2];
return;
}
}
for (auto param : params) {
switch (param) {
case 0:
@ -364,6 +337,8 @@ void Terminal::execute_xterm_command()
if (ok) {
switch (value) {
case 0:
case 1:
case 2:
set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size()));
break;
default:
@ -384,6 +359,8 @@ void Terminal::execute_escape_sequence(byte final)
bool ok;
unsigned value = parse_uint(parampart, ok);
if (!ok) {
m_parameters.clear_with_capacity();
m_intermediates.clear_with_capacity();
// FIXME: Should we do something else?
return;
}
@ -406,8 +383,8 @@ void Terminal::execute_escape_sequence(byte final)
break;
}
m_parameters.clear();
m_intermediates.clear();
m_parameters.clear_with_capacity();
m_intermediates.clear_with_capacity();
}
void Terminal::newline()
@ -463,7 +440,7 @@ void Terminal::put_character_at(unsigned row, unsigned column, byte ch)
void Terminal::on_char(byte ch)
{
#ifdef TERMINAL_DEBUG
dbgprintf("Terminal::on_char: %b (%c)\n", ch, ch);
dbgprintf("Terminal::on_char: %b (%c), fg=%u, bg=%u\n", ch, ch, m_current_attribute.foreground_color, m_current_attribute.background_color);
#endif
switch (m_escape_state) {
case ExpectBracket:
@ -617,14 +594,9 @@ Rect Terminal::glyph_rect(word row, word column)
Rect Terminal::row_rect(word row)
{
int y = row * m_line_height;
return { m_inset, y + m_inset, font().glyph_width() * m_columns, font().glyph_height() };
}
inline Terminal::Attribute& Terminal::attribute_at(word row, word column)
{
ASSERT(row < m_rows);
ASSERT(column < m_columns);
return line(row).attributes[column];
Rect rect = { m_inset, y + m_inset, font().glyph_width() * m_columns, font().glyph_height() };
rect.inflate(0, m_line_spacing);
return rect;
}
bool Terminal::Line::has_only_one_background_color() const
@ -671,25 +643,29 @@ void Terminal::paint()
continue;
line.dirty = false;
bool has_only_one_background_color = line.has_only_one_background_color();
if (has_only_one_background_color)
painter.fill_rect(row_rect(row), line.attributes[0].background_color);
if (has_only_one_background_color) {
painter.fill_rect(row_rect(row), lookup_color(line.attributes[0].background_color));
}
for (word column = 0; column < m_columns; ++column) {
bool should_reverse_fill_for_cursor = m_in_active_window && row == m_cursor_row && column == m_cursor_column;
auto& attribute = line.attributes[column];
line.did_paint = true;
char ch = line.characters[column];
auto character_rect = glyph_rect(row, column);
if (!has_only_one_background_color || should_reverse_fill_for_cursor)
painter.fill_rect(character_rect, ansi_color(should_reverse_fill_for_cursor ? attribute.foreground_color : attribute.background_color));
if (!has_only_one_background_color || should_reverse_fill_for_cursor) {
auto cell_rect = character_rect;
cell_rect.inflate(0, m_line_spacing);
painter.fill_rect(cell_rect, lookup_color(should_reverse_fill_for_cursor ? attribute.foreground_color : attribute.background_color));
}
if (ch == ' ')
continue;
painter.draw_glyph(character_rect.location(), ch, ansi_color(should_reverse_fill_for_cursor ? attribute.background_color : attribute.foreground_color));
painter.draw_glyph(character_rect.location(), ch, lookup_color(should_reverse_fill_for_cursor ? attribute.background_color : attribute.foreground_color));
}
}
if (!m_in_active_window) {
auto cursor_rect = glyph_rect(m_cursor_row, m_cursor_column);
painter.draw_rect(cursor_rect, ansi_color(line(m_cursor_row).attributes[m_cursor_column].foreground_color));
painter.draw_rect(cursor_rect, lookup_color(line(m_cursor_row).attributes[m_cursor_column].foreground_color));
}
line(m_cursor_row).did_paint = true;

View file

@ -63,8 +63,8 @@ private:
background_color = 0;
//bold = false;
}
unsigned foreground_color : 4;
unsigned background_color : 4;
byte foreground_color;
byte background_color;
//bool bold : 1;
bool operator==(const Attribute& other) const
{
@ -75,7 +75,7 @@ private:
struct Line {
explicit Line(word columns);
~Line();
void clear();
void clear(Attribute);
bool has_only_one_background_color() const;
byte* characters { nullptr };
Attribute* attributes { nullptr };
@ -98,8 +98,6 @@ private:
Attribute m_current_attribute;
Attribute& attribute_at(word row, word column);
void execute_escape_sequence(byte final);
void execute_xterm_command();

260
Terminal/XtermColors.h Normal file
View file

@ -0,0 +1,260 @@
#pragma once
static const unsigned xterm_colors[256] = {
0x000000,
0xcc0000,
0x3e9a06,
0xc4a000,
0x3465a4,
0x75507b,
0x06989a,
0xeeeeec,
0x555753,
0xef2929,
0x8ae234,
0xfce94f,
0x729fcf,
0xad7fa8,
0x34e2e2,
0xFFFFFF,
0x000000,
0x00005f,
0x000087,
0x0000af,
0x0000d7,
0x0000ff,
0x005f00,
0x005f5f,
0x005f87,
0x005faf,
0x005fd7,
0x005fff,
0x008700,
0x00875f,
0x008787,
0x0087af,
0x0087d7,
0x0087ff,
0x00af00,
0x00af5f,
0x00af87,
0x00afaf,
0x00afd7,
0x00afff,
0x00d700,
0x00d75f,
0x00d787,
0x00d7af,
0x00d7d7,
0x00d7ff,
0x00ff00,
0x00ff5f,
0x00ff87,
0x00ffaf,
0x00ffd7,
0x00ffff,
0x5f0000,
0x5f005f,
0x5f0087,
0x5f00af,
0x5f00d7,
0x5f00ff,
0x5f5f00,
0x5f5f5f,
0x5f5f87,
0x5f5faf,
0x5f5fd7,
0x5f5fff,
0x5f8700,
0x5f875f,
0x5f8787,
0x5f87af,
0x5f87d7,
0x5f87ff,
0x5faf00,
0x5faf5f,
0x5faf87,
0x5fafaf,
0x5fafd7,
0x5fafff,
0x5fd700,
0x5fd75f,
0x5fd787,
0x5fd7af,
0x5fd7d7,
0x5fd7ff,
0x5fff00,
0x5fff5f,
0x5fff87,
0x5fffaf,
0x5fffd7,
0x5fffff,
0x870000,
0x87005f,
0x870087,
0x8700af,
0x8700d7,
0x8700ff,
0x875f00,
0x875f5f,
0x875f87,
0x875faf,
0x875fd7,
0x875fff,
0x878700,
0x87875f,
0x878787,
0x8787af,
0x8787d7,
0x8787ff,
0x87af00,
0x87af5f,
0x87af87,
0x87afaf,
0x87afd7,
0x87afff,
0x87d700,
0x87d75f,
0x87d787,
0x87d7af,
0x87d7d7,
0x87d7ff,
0x87ff00,
0x87ff5f,
0x87ff87,
0x87ffaf,
0x87ffd7,
0x87ffff,
0xaf0000,
0xaf005f,
0xaf0087,
0xaf00af,
0xaf00d7,
0xaf00ff,
0xaf5f00,
0xaf5f5f,
0xaf5f87,
0xaf5faf,
0xaf5fd7,
0xaf5fff,
0xaf8700,
0xaf875f,
0xaf8787,
0xaf87af,
0xaf87d7,
0xaf87ff,
0xafaf00,
0xafaf5f,
0xafaf87,
0xafafaf,
0xafafd7,
0xafafff,
0xafd700,
0xafd75f,
0xafd787,
0xafd7af,
0xafd7d7,
0xafd7ff,
0xafff00,
0xafff5f,
0xafff87,
0xafffaf,
0xafffd7,
0xafffff,
0xd70000,
0xd7005f,
0xd70087,
0xd700af,
0xd700d7,
0xd700ff,
0xd75f00,
0xd75f5f,
0xd75f87,
0xd75faf,
0xd75fd7,
0xd75fff,
0xd78700,
0xd7875f,
0xd78787,
0xd787af,
0xd787d7,
0xd787ff,
0xd7af00,
0xd7af5f,
0xd7af87,
0xd7afaf,
0xd7afd7,
0xd7afff,
0xd7d700,
0xd7d75f,
0xd7d787,
0xd7d7af,
0xd7d7d7,
0xd7d7ff,
0xd7ff00,
0xd7ff5f,
0xd7ff87,
0xd7ffaf,
0xd7ffd7,
0xd7ffff,
0xff0000,
0xff005f,
0xff0087,
0xff00af,
0xff00d7,
0xff00ff,
0xff5f00,
0xff5f5f,
0xff5f87,
0xff5faf,
0xff5fd7,
0xff5fff,
0xff8700,
0xff875f,
0xff8787,
0xff87af,
0xff87d7,
0xff87ff,
0xffaf00,
0xffaf5f,
0xffaf87,
0xffafaf,
0xffafd7,
0xffafff,
0xffd700,
0xffd75f,
0xffd787,
0xffd7af,
0xffd7d7,
0xffd7ff,
0xffff00,
0xffff5f,
0xffff87,
0xffffaf,
0xffffd7,
0xffffff,
0x080808,
0x121212,
0x1c1c1c,
0x262626,
0x303030,
0x3a3a3a,
0x444444,
0x4e4e4e,
0x585858,
0x626262,
0x6c6c6c,
0x767676,
0x808080,
0x8a8a8a,
0x949494,
0x9e9e9e,
0xa8a8a8,
0xb2b2b2,
0xbcbcbc,
0xc6c6c6,
0xd0d0d0,
0xdadada,
0xe4e4e4,
0xeeeeee,
};