sdlterm/src/sdlterm.cc
changeset 52 50a1857557da
parent 51 dce7325109c1
child 53 c4263588b716
equal deleted inserted replaced
51:dce7325109c1 52:50a1857557da
    10     color.g = _map[index][1];
    10     color.g = _map[index][1];
    11     color.b = _map[index][2];
    11     color.b = _map[index][2];
    12 }
    12 }
    13 
    13 
    14 
    14 
    15 SDL_Surface *GlyphCache::lookup_glyph(Uint16 ch)
    15 SDL_Surface *GlyphCache::lookup_glyph(Uint64 id)
    16 {
    16 {
    17     auto iter = _glyph_map.find(ch);
    17     auto iter = _glyph_map.find(id);
    18     if (iter == _glyph_map.end())
    18     if (iter == _glyph_map.end())
    19     {
    19     {
    20         return NULL;
    20         return NULL;
    21     }
    21     }
    22     return iter->second;
    22     return iter->second;
    23 }
    23 }
    24 
    24 
    25 
    25 
    26 void GlyphCache::put_glyph(Uint16 ch, SDL_Surface *srf)
    26 void GlyphCache::put_glyph(Uint64 id, SDL_Surface *srf)
    27 {
    27 {
    28     _glyph_map[ch] = srf;
    28     _glyph_map[id] = srf;
    29 }
    29 }
    30 
    30 
    31 
    31 
    32 void GlyphCache::flush()
    32 void GlyphCache::flush()
    33 {
    33 {
   117         _font_bold = NULL;
   117         _font_bold = NULL;
   118     }
   118     }
   119 }
   119 }
   120 
   120 
   121 
   121 
   122 SDL_Surface *GlyphRenderer::render_cell(Uint16 ch, Uint16 attr)
   122 SDL_Surface *GlyphRenderer::render_cell(Uint32 ch, Uint32 attr)
   123 {
   123 {
   124     SDL_Surface *cell_surface;
   124     SDL_Surface *cell_surface;
   125     TTF_Font *font;
   125     TTF_Font *font;
   126     SDL_Color fgcolor, bgcolor;
   126     SDL_Color fgcolor, bgcolor;
   127 
   127 
   128     // try cache
   128     // try cache
   129     cell_surface = _cache.lookup_glyph(ch);
   129     Uint64 id = (Uint64)ch | (Uint64)attr << 32;
       
   130     cell_surface = _cache.lookup_glyph(id);
   130     if (cell_surface)
   131     if (cell_surface)
   131     {
   132     {
   132         return cell_surface;
   133         return cell_surface;
   133     }
   134     }
   134 
   135 
   135     // load attributes
   136     // load attributes
   136     _colormap.index_to_rgb(attr & 0x000F, fgcolor);
   137     _colormap.index_to_rgb((attr & 0x000000FF), fgcolor);
   137     _colormap.index_to_rgb((attr & 0x00F0) >> 4, bgcolor);
   138     _colormap.index_to_rgb((attr & 0x0000FF00) >> 8, bgcolor);
   138     Style style = (Style) ((attr & 0xFF00) >> 8);
   139     int style = (attr & 0xFF000000) >> 24;
   139     font = (style == Style::BOLD) ? _font_bold : _font_regular;
   140     font = (style & Style::BOLD) ? _font_bold : _font_regular;
       
   141     if (style & Style::STANDOUT)
       
   142     {
       
   143         std::swap(fgcolor, bgcolor);
       
   144     }
   140 
   145 
   141     // create surface for whole cell and fill it with bg color
   146     // create surface for whole cell and fill it with bg color
   142     cell_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
   147     cell_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
   143             _cell_width, _cell_height, 32, 0, 0, 0, 0);
   148             _cell_width, _cell_height, 32, 0, 0, 0, 0);
   144     SDL_Rect dst_rect;
   149     SDL_Rect dst_rect;
   150     SDL_FillRect(cell_surface, &dst_rect, bgcolor_mapped);
   155     SDL_FillRect(cell_surface, &dst_rect, bgcolor_mapped);
   151 
   156 
   152     // render glyph, blit it onto cell surface
   157     // render glyph, blit it onto cell surface
   153     if (ch)
   158     if (ch)
   154     {
   159     {
   155         SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, fgcolor, bgcolor);
   160         // when glyph is not provided by BOLD font but is provided by REGULAR font, use that (better than nothing)
   156         int minx, maxy;
   161         if ((style & Style::BOLD) && !TTF_GlyphIsProvided(font, ch) && TTF_GlyphIsProvided(_font_regular, ch))
   157         TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL);
   162         {
   158         dst_rect.x = minx;
   163             // use bold style of regular font instead of bold font
   159         dst_rect.y = TTF_FontAscent(font) - maxy;
   164             TTF_SetFontStyle(_font_regular, TTF_STYLE_BOLD);
   160         SDL_BlitSurface(glyph_surface, NULL, cell_surface, &dst_rect);
   165             _render_glyph(cell_surface, _font_regular, ch, fgcolor, bgcolor);
   161         SDL_FreeSurface(glyph_surface);
   166             TTF_SetFontStyle(_font_regular, TTF_STYLE_NORMAL);
       
   167         }
       
   168         else
       
   169         {
       
   170             // normal case
       
   171             _render_glyph(cell_surface, font, ch, fgcolor, bgcolor);
       
   172         }
       
   173         if (style & Style::UNDERLINE)
       
   174         {
       
   175             // draw underline
       
   176             SDL_LockSurface(cell_surface);
       
   177             int y = 1 + TTF_FontAscent(font);
       
   178             Uint32 fgcolor_mapped = SDL_MapRGB(cell_surface->format, fgcolor.r, fgcolor.g, fgcolor.b);
       
   179             Uint32 *p = (Uint32 *)(cell_surface->pixels + y * cell_surface->pitch);
       
   180             for (int x = 0; x < _cell_width; x++)
       
   181                 *p++ = fgcolor_mapped;
       
   182             SDL_UnlockSurface(cell_surface);
       
   183         }
   162     }
   184     }
   163 
   185 
   164     // convert to display format
   186     // convert to display format
   165     SDL_Surface *tmp_surface = cell_surface;
   187     SDL_Surface *tmp_surface = cell_surface;
   166     cell_surface = SDL_DisplayFormat(tmp_surface);
   188     cell_surface = SDL_DisplayFormat(tmp_surface);
   167     SDL_FreeSurface(tmp_surface);
   189     SDL_FreeSurface(tmp_surface);
   168 
   190 
   169     // put to cache
   191     // put to cache
   170     _cache.put_glyph(ch, cell_surface);
   192     _cache.put_glyph(id, cell_surface);
   171 
   193 
   172     return cell_surface;
   194     return cell_surface;
       
   195 }
       
   196 
       
   197 
       
   198 void GlyphRenderer::_render_glyph(SDL_Surface *cell_surface, TTF_Font *font, Uint32 ch,
       
   199         SDL_Color fgcolor, SDL_Color bgcolor)
       
   200 {
       
   201     int minx, maxy;
       
   202     SDL_Rect dst_rect;
       
   203     SDL_Surface *glyph_surface = TTF_RenderGlyph_Shaded(font, ch, fgcolor, bgcolor);
       
   204     TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL);
       
   205     dst_rect.x = minx;
       
   206     dst_rect.y = TTF_FontAscent(font) - maxy;
       
   207     SDL_BlitSurface(glyph_surface, NULL, cell_surface, &dst_rect);
       
   208     SDL_FreeSurface(glyph_surface);
   173 }
   209 }
   174 
   210 
   175 
   211 
   176 void TerminalScreen::select_font(const char *fname_regular, const char *fname_bold, int ptsize)
   212 void TerminalScreen::select_font(const char *fname_regular, const char *fname_bold, int ptsize)
   177 {
   213 {
   202 {
   238 {
   203     std::fill(_cells_front.begin(), _cells_front.end(), TerminalCell());
   239     std::fill(_cells_front.begin(), _cells_front.end(), TerminalCell());
   204 }
   240 }
   205 
   241 
   206 
   242 
   207 void TerminalScreen::putch(int x, int y, Uint16 ch, Uint16 attr)
   243 void TerminalScreen::putch(int x, int y, Uint32 ch, Uint32 attr)
   208 {
   244 {
   209     TerminalCell &cell = _cells_front[y * _width + x];
   245     TerminalCell &cell = _cells_front[y * _width + x];
   210     cell.ch = ch;
   246     cell.ch = ch;
   211     cell.attr = attr;
   247     cell.attr = attr;
   212 }
   248 }