sdlterm/src/sdlterm.cc
changeset 52 50a1857557da
parent 51 dce7325109c1
child 53 c4263588b716
--- a/sdlterm/src/sdlterm.cc	Sat Jan 05 18:56:45 2013 +0100
+++ b/sdlterm/src/sdlterm.cc	Sat Jan 05 23:00:41 2013 +0100
@@ -12,9 +12,9 @@
 }
 
 
-SDL_Surface *GlyphCache::lookup_glyph(Uint16 ch)
+SDL_Surface *GlyphCache::lookup_glyph(Uint64 id)
 {
-    auto iter = _glyph_map.find(ch);
+    auto iter = _glyph_map.find(id);
     if (iter == _glyph_map.end())
     {
         return NULL;
@@ -23,9 +23,9 @@
 }
 
 
-void GlyphCache::put_glyph(Uint16 ch, SDL_Surface *srf)
+void GlyphCache::put_glyph(Uint64 id, SDL_Surface *srf)
 {
-    _glyph_map[ch] = srf;
+    _glyph_map[id] = srf;
 }
 
 
@@ -119,24 +119,29 @@
 }
 
 
-SDL_Surface *GlyphRenderer::render_cell(Uint16 ch, Uint16 attr)
+SDL_Surface *GlyphRenderer::render_cell(Uint32 ch, Uint32 attr)
 {
     SDL_Surface *cell_surface;
     TTF_Font *font;
     SDL_Color fgcolor, bgcolor;
 
     // try cache
-    cell_surface = _cache.lookup_glyph(ch);
+    Uint64 id = (Uint64)ch | (Uint64)attr << 32;
+    cell_surface = _cache.lookup_glyph(id);
     if (cell_surface)
     {
         return cell_surface;
     }
 
     // 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;
+    _colormap.index_to_rgb((attr & 0x000000FF), fgcolor);
+    _colormap.index_to_rgb((attr & 0x0000FF00) >> 8, bgcolor);
+    int style = (attr & 0xFF000000) >> 24;
+    font = (style & Style::BOLD) ? _font_bold : _font_regular;
+    if (style & Style::STANDOUT)
+    {
+        std::swap(fgcolor, bgcolor);
+    }
 
     // create surface for whole cell and fill it with bg color
     cell_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
@@ -152,13 +157,30 @@
     // render glyph, blit it onto cell surface
     if (ch)
     {
-        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;
-        dst_rect.y = TTF_FontAscent(font) - maxy;
-        SDL_BlitSurface(glyph_surface, NULL, cell_surface, &dst_rect);
-        SDL_FreeSurface(glyph_surface);
+        // when glyph is not provided by BOLD font but is provided by REGULAR font, use that (better than nothing)
+        if ((style & Style::BOLD) && !TTF_GlyphIsProvided(font, ch) && TTF_GlyphIsProvided(_font_regular, ch))
+        {
+            // use bold style of regular font instead of bold font
+            TTF_SetFontStyle(_font_regular, TTF_STYLE_BOLD);
+            _render_glyph(cell_surface, _font_regular, ch, fgcolor, bgcolor);
+            TTF_SetFontStyle(_font_regular, TTF_STYLE_NORMAL);
+        }
+        else
+        {
+            // normal case
+            _render_glyph(cell_surface, font, ch, fgcolor, bgcolor);
+        }
+        if (style & Style::UNDERLINE)
+        {
+            // draw underline
+            SDL_LockSurface(cell_surface);
+            int y = 1 + TTF_FontAscent(font);
+            Uint32 fgcolor_mapped = SDL_MapRGB(cell_surface->format, fgcolor.r, fgcolor.g, fgcolor.b);
+            Uint32 *p = (Uint32 *)(cell_surface->pixels + y * cell_surface->pitch);
+            for (int x = 0; x < _cell_width; x++)
+                *p++ = fgcolor_mapped;
+            SDL_UnlockSurface(cell_surface);
+        }
     }
 
     // convert to display format
@@ -167,12 +189,26 @@
     SDL_FreeSurface(tmp_surface);
 
     // put to cache
-    _cache.put_glyph(ch, cell_surface);
+    _cache.put_glyph(id, cell_surface);
 
     return cell_surface;
 }
 
 
+void GlyphRenderer::_render_glyph(SDL_Surface *cell_surface, TTF_Font *font, Uint32 ch,
+        SDL_Color fgcolor, SDL_Color bgcolor)
+{
+    int minx, maxy;
+    SDL_Rect dst_rect;
+    SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, fgcolor, bgcolor);
+    TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL);
+    dst_rect.x = minx;
+    dst_rect.y = TTF_FontAscent(font) - maxy;
+    SDL_BlitSurface(glyph_surface, NULL, cell_surface, &dst_rect);
+    SDL_FreeSurface(glyph_surface);
+}
+
+
 void TerminalScreen::select_font(const char *fname_regular, const char *fname_bold, int ptsize)
 {
     _render.open_font(fname_regular, fname_bold, ptsize);
@@ -204,7 +240,7 @@
 }
 
 
-void TerminalScreen::putch(int x, int y, Uint16 ch, Uint16 attr)
+void TerminalScreen::putch(int x, int y, Uint32 ch, Uint32 attr)
 {
     TerminalCell &cell = _cells_front[y * _width + x];
     cell.ch = ch;