GUACAMOLE-278: Copy terminal color values rather than referencing only by palette index.

This commit is contained in:
Michael Jumper 2017-04-23 11:02:25 -07:00
parent 69caa9936b
commit 48fc4afc5b
7 changed files with 124 additions and 73 deletions

View File

@ -105,3 +105,23 @@ int guac_terminal_write_all(int fd, const char* buffer, int size) {
}
int guac_terminal_colorcmp(const guac_terminal_color* a,
const guac_terminal_color* b) {
/* Consider red component highest order ... */
if (a->red != b->red)
return a->red - b->red;
/* ... followed by green ... */
if (a->green != b->green)
return a->green - b->green;
/* ... followed by blue */
if (a->blue != b->blue)
return a->blue - b->blue;
/* If all components match, colors are equal */
return 0;
}

View File

@ -39,24 +39,24 @@
const guac_terminal_color guac_terminal_palette[16] = {
/* Normal colors */
{0x00, 0x00, 0x00}, /* Black */
{0x99, 0x3E, 0x3E}, /* Red */
{0x3E, 0x99, 0x3E}, /* Green */
{0x99, 0x99, 0x3E}, /* Brown */
{0x3E, 0x3E, 0x99}, /* Blue */
{0x99, 0x3E, 0x99}, /* Magenta */
{0x3E, 0x99, 0x99}, /* Cyan */
{0x99, 0x99, 0x99}, /* White */
{0, 0x00, 0x00, 0x00}, /* Black */
{1, 0x99, 0x3E, 0x3E}, /* Red */
{2, 0x3E, 0x99, 0x3E}, /* Green */
{3, 0x99, 0x99, 0x3E}, /* Brown */
{4, 0x3E, 0x3E, 0x99}, /* Blue */
{5, 0x99, 0x3E, 0x99}, /* Magenta */
{6, 0x3E, 0x99, 0x99}, /* Cyan */
{7, 0x99, 0x99, 0x99}, /* White */
/* Intense colors */
{0x3E, 0x3E, 0x3E}, /* Black */
{0xFF, 0x67, 0x67}, /* Red */
{0x67, 0xFF, 0x67}, /* Green */
{0xFF, 0xFF, 0x67}, /* Brown */
{0x67, 0x67, 0xFF}, /* Blue */
{0xFF, 0x67, 0xFF}, /* Magenta */
{0x67, 0xFF, 0xFF}, /* Cyan */
{0xFF, 0xFF, 0xFF}, /* White */
{8, 0x3E, 0x3E, 0x3E}, /* Black */
{9, 0xFF, 0x67, 0x67}, /* Red */
{10, 0x67, 0xFF, 0x67}, /* Green */
{11, 0xFF, 0xFF, 0x67}, /* Brown */
{12, 0x67, 0x67, 0xFF}, /* Blue */
{13, 0xFF, 0x67, 0xFF}, /* Magenta */
{14, 0x67, 0xFF, 0xFF}, /* Cyan */
{15, 0xFF, 0xFF, 0xFF}, /* White */
};
@ -127,24 +127,27 @@ int __guac_terminal_hash_codepoint(int codepoint) {
int __guac_terminal_set_colors(guac_terminal_display* display,
guac_terminal_attributes* attributes) {
int background, foreground;
const guac_terminal_color* background;
const guac_terminal_color* foreground;
/* Handle reverse video */
if (attributes->reverse != attributes->cursor) {
background = attributes->foreground;
foreground = attributes->background;
background = &attributes->foreground;
foreground = &attributes->background;
}
else {
foreground = attributes->foreground;
background = attributes->background;
foreground = &attributes->foreground;
background = &attributes->background;
}
/* Handle bold */
if (attributes->bold && foreground <= 7)
foreground += 8;
if (attributes->bold && foreground->palette_index >= 0
&& foreground->palette_index <= 7) {
foreground = &guac_terminal_palette[foreground->palette_index + 8];
}
display->glyph_foreground = foreground;
display->glyph_background = background;
display->glyph_foreground = *foreground;
display->glyph_background = *background;
return 0;
@ -163,12 +166,10 @@ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int co
char utf8[4];
/* Use foreground color */
const guac_terminal_color* color =
&guac_terminal_palette[display->glyph_foreground];
const guac_terminal_color* color = &display->glyph_foreground;
/* Use background color */
const guac_terminal_color* background =
&guac_terminal_palette[display->glyph_background];
const guac_terminal_color* background = &display->glyph_background;
cairo_surface_t* surface;
cairo_t* cairo;
@ -259,7 +260,7 @@ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int co
guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
const char* font_name, int font_size, int dpi,
int foreground, int background) {
guac_terminal_color* foreground, guac_terminal_color* background) {
PangoFontMap* font_map;
PangoFont* font;
@ -303,8 +304,8 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
return NULL;
}
display->default_foreground = display->glyph_foreground = foreground;
display->default_background = display->glyph_background = background;
display->default_foreground = display->glyph_foreground = *foreground;
display->default_background = display->glyph_background = *background;
/* Calculate character dimensions */
display->char_width =
@ -688,14 +689,11 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
int rect_width, rect_height;
/* Color of the rectangle to draw */
int color;
const guac_terminal_color* color;
if (current->character.attributes.reverse != current->character.attributes.cursor)
color = current->character.attributes.foreground;
color = &current->character.attributes.foreground;
else
color = current->character.attributes.background;
const guac_terminal_color* guac_color =
&guac_terminal_palette[color];
color = &current->character.attributes.background;
/* Current row within a subrect */
guac_terminal_operation* rect_current_row;
@ -709,16 +707,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
/* Find width */
for (rect_col=col; rect_col<display->width; rect_col++) {
int joining_color;
const guac_terminal_color* joining_color;
if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor)
joining_color = rect_current->character.attributes.foreground;
joining_color = &rect_current->character.attributes.foreground;
else
joining_color = rect_current->character.attributes.background;
joining_color = &rect_current->character.attributes.background;
/* If not identical operation, stop */
if (rect_current->type != GUAC_CHAR_SET
|| guac_terminal_has_glyph(rect_current->character.value)
|| joining_color != color)
|| guac_terminal_colorcmp(joining_color, color) != 0)
break;
/* Next column */
@ -754,16 +752,16 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
for (rect_col=0; rect_col<rect_width; rect_col++) {
int joining_color;
const guac_terminal_color* joining_color;
if (rect_current->character.attributes.reverse != rect_current->character.attributes.cursor)
joining_color = rect_current->character.attributes.foreground;
joining_color = &rect_current->character.attributes.foreground;
else
joining_color = rect_current->character.attributes.background;
joining_color = &rect_current->character.attributes.background;
/* Mark clear operations as NOP */
if (rect_current->type == GUAC_CHAR_SET
&& !guac_terminal_has_glyph(rect_current->character.value)
&& joining_color == color)
&& guac_terminal_colorcmp(joining_color, color) == 0)
rect_current->type = GUAC_CHAR_NOP;
/* Next column */
@ -783,7 +781,7 @@ void __guac_terminal_display_flush_clear(guac_terminal_display* display) {
row * display->char_height,
rect_width * display->char_width,
rect_height * display->char_height,
guac_color->red, guac_color->green, guac_color->blue,
color->red, color->green, color->blue,
0xFF);
} /* end if clear operation */

View File

@ -205,8 +205,7 @@ static void guac_terminal_repaint_default_layer(guac_terminal* terminal,
guac_terminal_display* display = terminal->display;
/* Get background color */
const guac_terminal_color* color =
&guac_terminal_palette[display->default_background];
const guac_terminal_color* color = &display->default_background;
/* Reset size */
guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height);
@ -296,8 +295,8 @@ guac_terminal* guac_terminal_create(guac_client* client,
guac_terminal_char default_char = {
.value = 0,
.attributes = {
.foreground = default_foreground,
.background = default_background,
.foreground = guac_terminal_palette[default_foreground],
.background = guac_terminal_palette[default_background],
.bold = false,
.reverse = false,
.underscore = false
@ -326,8 +325,8 @@ guac_terminal* guac_terminal_create(guac_client* client,
/* Init display */
term->display = guac_terminal_display_alloc(client,
font_name, font_size, dpi,
default_char.attributes.foreground,
default_char.attributes.background);
&default_char.attributes.foreground,
&default_char.attributes.background);
/* Fail if display init failed */
if (term->display == NULL) {
@ -875,17 +874,18 @@ static bool guac_terminal_is_visible(guac_terminal* term,
if (guac_terminal_has_glyph(c->value))
return true;
int background;
const guac_terminal_color* background;
/* Determine actual background color of character */
if (c->attributes.reverse != c->attributes.cursor)
background = c->attributes.foreground;
background = &c->attributes.foreground;
else
background = c->attributes.background;
background = &c->attributes.background;
/* Blank characters are visible if their background color differs from that
* of the terminal */
return background != term->default_char.attributes.background;
return guac_terminal_colorcmp(background,
&term->default_char.attributes.background) != 0;
}

View File

@ -22,6 +22,7 @@
#define _GUAC_TERMINAL_COMMON_H
#include "config.h"
#include "types.h"
#include <stdbool.h>
@ -49,5 +50,26 @@ bool guac_terminal_has_glyph(int codepoint);
*/
int guac_terminal_write_all(int fd, const char* buffer, int size);
/**
* Compares two colors, returning a negative value if the first color is less
* than the second, a positive value if the first color is greater than the
* second, and zero if the colors are identical. Only the color components are
* compared (not the palette index). The red component is considered the
* highest order component, followed by green, followed by blue.
*
* @param a
* The first color to compare.
*
* @param b
* The second color to compare.
*
* @return
* A negative value if the first color is less than the second, a positive
* value if the first color is greater than the second, and zero if the
* colors are identical.
*/
int guac_terminal_colorcmp(const guac_terminal_color* a,
const guac_terminal_color* b);
#endif

View File

@ -220,22 +220,24 @@ typedef struct guac_terminal_display {
/**
* Default foreground color for all glyphs.
*/
int default_foreground;
guac_terminal_color default_foreground;
/**
* Default background color for all glyphs and the terminal itself.
*/
int default_background;
guac_terminal_color default_background;
/**
* Color of glyphs in copy buffer
* The foreground color to be used for the next glyph rendered to the
* terminal.
*/
int glyph_foreground;
guac_terminal_color glyph_foreground;
/**
* Color of glyphs in copy buffer
* The background color to be used for the next glyph rendered to the
* terminal.
*/
int glyph_background;
guac_terminal_color glyph_background;
/**
* The surface containing the actual terminal.
@ -292,7 +294,7 @@ typedef struct guac_terminal_display {
*/
guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
const char* font_name, int font_size, int dpi,
int foreground, int background);
guac_terminal_color* foreground, guac_terminal_color* background);
/**
* Frees the given display.

View File

@ -24,6 +24,7 @@
#include "config.h"
#include <stdbool.h>
#include <stdint.h>
/**
* A character which is not truly a character, but rather part of an
@ -39,20 +40,26 @@
*/
typedef struct guac_terminal_color {
/**
* The index of this color within the terminal palette, or -1 if the color
* does not exist within the terminal palette.
*/
int palette_index;
/**
* The red component of this color.
*/
int red;
uint8_t red;
/**
* The green component of this color.
*/
int green;
uint8_t green;
/**
* The blue component of this color.
*/
int blue;
uint8_t blue;
} guac_terminal_color;
@ -83,14 +90,14 @@ typedef struct guac_terminal_attributes {
bool underscore;
/**
* The foreground color of this character, as a palette index.
* The foreground color of this character.
*/
int foreground;
guac_terminal_color foreground;
/**
* The background color of this character, as a palette index.
* The background color of this character.
*/
int background;
guac_terminal_color background;
} guac_terminal_attributes;

View File

@ -779,7 +779,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
/* Foreground */
else if (value >= 30 && value <= 37)
term->current_attributes.foreground = value - 30;
term->current_attributes.foreground =
guac_terminal_palette[value - 30];
/* Underscore on, default foreground */
else if (value == 38) {
@ -797,7 +798,8 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
/* Background */
else if (value >= 40 && value <= 47)
term->current_attributes.background = value - 40;
term->current_attributes.background =
guac_terminal_palette[value - 40];
/* Reset background */
else if (value == 49)