# HG changeset patch # User Radek Brich # Date 1357407896 -3600 # Node ID c5b8b9d2da959060aa51c5723124a626a08aee0f # Parent 1611c462c3e392e9f341363e3b92f857edd40cb7 DriverSDL: Implement colors. diff -r 1611c462c3e3 -r c5b8b9d2da95 sdlterm/cython/sdlterm.pyx --- 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 diff -r 1611c462c3e3 -r c5b8b9d2da95 sdlterm/demo.cc --- 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(); } diff -r 1611c462c3e3 -r c5b8b9d2da95 sdlterm/src/sdlterm.cc --- 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 +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; } } diff -r 1611c462c3e3 -r c5b8b9d2da95 sdlterm/src/sdlterm.h --- 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 +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; }; diff -r 1611c462c3e3 -r c5b8b9d2da95 tuikit/driver_sdl.py --- 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 ##