DriverSDL: Implement colors.
--- a/sdlterm/cython/sdlterm.pyx Sat Jan 05 16:47:30 2013 +0100
+++ b/sdlterm/cython/sdlterm.pyx Sat Jan 05 18:44:56 2013 +0100
@@ -77,6 +77,11 @@
def commit(self):
self.thisptr.commit()
+ def prepare_attr(self, fg, bg, style):
+ return self.thisptr.prepare_attr(fg, bg, style)
+ def set_attr(self, value):
+ self.thisptr.set_attr(value)
+
def get_next_event(self):
self.thisptr.get_next_event(self.event)
event = self.event
--- a/sdlterm/demo.cc Sat Jan 05 16:47:30 2013 +0100
+++ b/sdlterm/demo.cc Sat Jan 05 18:44:56 2013 +0100
@@ -19,7 +19,13 @@
term.resize(800, 600);
term.select_font("font/DejaVuSansMono.ttf", "font/DejaVuSansMono-Bold.ttf", 12);
term.erase();
- term.putch(5, 5, 'W');
+ term.set_attr( term.prepare_attr(14, 1, 1) );
+
+ char hello[] = "Hello World!";
+ for (char *c = hello; *c; c++)
+ {
+ term.putch(5 + (c - hello), 5, *c);
+ }
term.commit();
}
--- a/sdlterm/src/sdlterm.cc Sat Jan 05 16:47:30 2013 +0100
+++ b/sdlterm/src/sdlterm.cc Sat Jan 05 18:44:56 2013 +0100
@@ -4,6 +4,14 @@
#include <algorithm>
+void ColorMap::index_to_rgb(int index, SDL_Color &color)
+{
+ color.r = _map[index][0];
+ color.g = _map[index][1];
+ color.b = _map[index][2];
+}
+
+
SDL_Surface *GlyphCache::lookup_glyph(Uint16 ch)
{
auto iter = _glyph_map.find(ch);
@@ -32,7 +40,7 @@
GlyphRenderer::GlyphRenderer()
- : _font_regular(NULL), _font_bold(NULL)
+ : _font_regular(NULL), _font_bold(NULL), _cell_width(0), _cell_height(0), _cache(), _colormap()
{
if (TTF_Init() == -1)
{
@@ -111,9 +119,11 @@
}
-SDL_Surface *GlyphRenderer::render_glyph(Uint16 ch)
+SDL_Surface *GlyphRenderer::render_cell(Uint16 ch, Uint16 attr)
{
SDL_Surface *cell_surface;
+ TTF_Font *font;
+ SDL_Color fgcolor, bgcolor;
// try cache
cell_surface = _cache.lookup_glyph(ch);
@@ -122,8 +132,11 @@
return cell_surface;
}
- TTF_Font *font = _font_regular;
- SDL_Color color={0xff,0xff,0xff}, bgcolor={0,0,0};
+ // load attributes
+ _colormap.index_to_rgb(attr & 0x000F, fgcolor);
+ _colormap.index_to_rgb((attr & 0x00F0) >> 4, bgcolor);
+ Style style = (Style) ((attr & 0xFF00) >> 8);
+ font = (style == Style::BOLD) ? _font_bold : _font_regular;
// create surface for whole cell and fill it with bg color
cell_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
@@ -139,7 +152,7 @@
// render glyph, blit it onto cell surface
if (ch)
{
- SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, color, bgcolor);
+ SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, fgcolor, bgcolor);
int minx, maxy;
TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL);
dst_rect.x = minx;
@@ -203,7 +216,7 @@
{
auto front_iter = _cells_front.begin();
auto back_iter = _cells_back.begin();
- SDL_Surface *glyph_surface;
+ SDL_Surface *cell_surface;
SDL_Rect dst_rect;
for (int y = 0; y < _height; y++)
{
@@ -213,8 +226,8 @@
{
dst_rect.x = x * _cell_width;
dst_rect.y = y * _cell_height;
- glyph_surface = _render.render_glyph(front_iter->ch);
- SDL_BlitSurface(glyph_surface, NULL, _screen_surface, &dst_rect);
+ cell_surface = _render.render_cell(front_iter->ch, front_iter->attr);
+ SDL_BlitSurface(cell_surface, NULL, _screen_surface, &dst_rect);
*back_iter = *front_iter;
}
front_iter++;
@@ -230,17 +243,22 @@
{
_cell_width = _render.get_cell_width();
_cell_height = _render.get_cell_height();
+ if (!_cell_width || !_cell_height)
+ return;
+
_width = _pixel_width / _cell_width;
_height = _pixel_height / _cell_height;
+ if (!_width || !_height)
+ return;
int num_cells = _width * _height;
- _cells_front.resize(num_cells);
- _cells_back.resize(num_cells);
+ _cells_front.resize(num_cells, TerminalCell());
+ _cells_back.resize(num_cells, TerminalCell());
}
Terminal::Terminal()
- : _screen(), _mousemove_last_x(-1)
+ : _screen(), _attr(7), _mousemove_last_x(-1)
{
if (SDL_Init(SDL_INIT_VIDEO) == -1)
{
@@ -327,7 +345,6 @@
case SDLK_TAB: return "tab";
case SDLK_RETURN: return "enter";
case SDLK_KP_ENTER: return "enter";
- case SDLK_PAUSE: return "pause";
case SDLK_ESCAPE: return "escape";
case SDLK_DELETE: return "delete";
case SDLK_INSERT: return "insert";
@@ -351,6 +368,9 @@
case SDLK_F10: return "f10";
case SDLK_F11: return "f11";
case SDLK_F12: return "f12";
+ case SDLK_PRINT: return "print";
+ case SDLK_SCROLLOCK: return "scrllock";
+ case SDLK_PAUSE: return "pause";
default: return NULL;
}
}
--- a/sdlterm/src/sdlterm.h Sat Jan 05 16:47:30 2013 +0100
+++ b/sdlterm/src/sdlterm.h Sat Jan 05 18:44:56 2013 +0100
@@ -5,6 +5,42 @@
#include <vector>
+enum class Style: Uint16
+{
+ BOLD = 1 << 0, // bold font
+ UNDERLINE = 1 << 1, // underline text
+ STANDOUT = 1 << 2, // inverse bg/fg
+ BLINK = 1 << 3, // blinking
+};
+
+
+class ColorMap
+{
+private:
+ Uint8 _map[16][3] = {
+ {0,0,0}, // 0 - black
+ {23,23,178}, // 1 - blue
+ {23,178,23}, // 2 - green
+ {23,178,178}, // 3 - cyan
+ {178,23,23}, // 4 - red
+ {178,23,178}, // 5 - magenta
+ {178,103,23}, // 6 - brown
+ {178,178,178}, // 7 - light gray
+ {104,104,104}, // 8 - gray
+ {84,84,255}, // 9 - light blue
+ {84,255,84}, // 10 - light green
+ {84,255,255}, // 11 - light cyan
+ {255,84,84}, // 12 - light red
+ {255,84,255}, // 13 - light magenta
+ {255,255,84}, // 14 - yellow
+ {255,255,255}, // 15 - white
+ };
+
+public:
+ void index_to_rgb(int index, SDL_Color &color);
+};
+
+
class GlyphCache
{
public:
@@ -27,7 +63,7 @@
void close_font();
// do not free surface returned!
- SDL_Surface *render_glyph(Uint16 ch);
+ SDL_Surface *render_cell(Uint16 ch, Uint16 attr);
int get_cell_width() { return _cell_width; };
int get_cell_height() { return _cell_height; };
@@ -38,6 +74,7 @@
int _cell_width;
int _cell_height;
GlyphCache _cache;
+ ColorMap _colormap;
};
@@ -52,7 +89,9 @@
class TerminalScreen
{
public:
- TerminalScreen(): _screen_surface(NULL), _render() {};
+ TerminalScreen():
+ _screen_surface(NULL), _cells_front(0), _cells_back(0), _render(),
+ _pixel_width(0), _pixel_height(0) {};
~TerminalScreen() {};
void select_font(const char *fname_regular, const char *fname_bold, int ptsize);
@@ -119,7 +158,7 @@
void putch(int x, int y, Uint16 ch) { _screen.putch(x, y, ch, _attr); };
void commit() { _screen.commit(); };
- Uint16 prepare_attr(Uint8 fg, Uint8 bg, Uint8 style) { return fg | bg << 8 | style << 16; };
+ Uint16 prepare_attr(Uint8 fg, Uint8 bg, Uint8 style) { return fg | bg << 4 | style << 8; };
void set_attr(Uint16 value) { _attr = value; };
void set_cursor(int x, int y) { _cursor_x = x; _cursor_y = y; };
--- a/tuikit/driver_sdl.py Sat Jan 05 16:47:30 2013 +0100
+++ b/tuikit/driver_sdl.py Sat Jan 05 18:44:56 2013 +0100
@@ -19,11 +19,40 @@
'''SDL driver class'''
+ color_map = {
+ 'black' : 0,
+ 'blue' : 1,
+ 'green' : 2,
+ 'cyan' : 3,
+ 'red' : 4,
+ 'magenta' : 5,
+ 'brown' : 6,
+ 'lightgray' : 7,
+ 'gray' : 8,
+ 'lightblue' : 9,
+ 'lightgreen' : 10,
+ 'lightcyan' : 11,
+ 'lightred' : 12,
+ 'lightmagenta' : 13,
+ 'yellow' : 14,
+ 'white' : 15,
+ }
+
+ style_map = {
+ 'bold' : 1 << 0, # bold font
+ 'underline' : 1 << 1, # underline text
+ 'standout' : 1 << 2, # inverse bg/fg
+ 'blink' : 1 << 3, # blinking text
+ 'dim' : 0,
+ }
+
def __init__(self):
'''Initialize instance attributes'''
Driver.__init__(self)
self.log = logging.getLogger('tuikit')
self.sdlterm = SDLTerminal()
+ self.colors = {} # maps names to attributes
+ self.colorstack = [] # pushcolor/popcolor puts or gets attributes from this
def start(self, mainfunc):
'''Start driver and run mainfunc.'''
@@ -67,15 +96,43 @@
desc - color description - foreground, background, attributes (e.g. 'black on white, bold')
'''
- self.log.info('DummyDriver.setcolor(name=%r, desc=%r)', name, desc)
+ parts = desc.split(',')
+ fg, bg = parts[0].split(' on ')
+ style = parts[1:]
+ fg = self._color_by_name(fg)
+ bg = self._color_by_name(bg)
+ style = self._style_by_names(style)
+ self.colors[name] = self.sdlterm.prepare_attr(fg, bg, style);
def pushcolor(self, name):
'''Add color on top of stack and use this color for following output.'''
- self.log.info('DummyDriver.pushcolor(name=%r)', name)
+ if len(self.colorprefix):
+ prefixname = self.colorprefix[-1] + name
+ if prefixname in self.colors:
+ name = prefixname
+ attr = self.colors[name]
+ self.sdlterm.set_attr(attr)
+ self.colorstack.append(attr)
def popcolor(self):
'''Remove color from top of stack and use new top color for following output.'''
- self.log.info('DummyDriver.popcolor()')
+ self.colorstack.pop()
+ if len(self.colorstack):
+ attr = self.colorstack[-1]
+ else:
+ attr = 0
+ self.sdlterm.set_attr(attr)
+
+ def _color_by_name(self, name):
+ name = name.lower().strip()
+ return self.color_map[name]
+
+ def _style_by_names(self, names):
+ style = 0
+ for name in names:
+ name = name.lower().strip()
+ style |= self.style_map[name]
+ return style
## cursor ##