void Text::Draw(Bitmap& dest, int x, int y, Color color, std::string const& text) { if (text.length() == 0) return; FontRef font = dest.GetFont(); int next_glyph_pos = 0; for (boost::u8_to_u32_iterator<std::string::const_iterator> c(text.begin(), text.begin(), text.end()), end(text.end(), text.begin(), text.end()); c != end; ++c) { boost::u8_to_u32_iterator<std::string::const_iterator> next_c_it = boost::next(c); std::string const glyph(c.base(), next_c_it.base()); if (*c == '\n') { y += font->GetSize(glyph).height; next_glyph_pos = 0; continue; } Rect next_glyph_rect(x + next_glyph_pos, y, 0, 0); font->Render(dest, next_glyph_rect.x, next_glyph_rect.y, color, *c); next_glyph_pos += font->GetSize(glyph).width; } }
void Text::Draw(Bitmap& dest, int x, int y, int color, std::string const& text, Text::Alignment align) { if (text.length() == 0) return; FontRef font = dest.GetFont(); Rect dst_rect = Font::Default()->GetSize(text); switch (align) { case Text::AlignCenter: dst_rect.x = x - dst_rect.width / 2; break; case Text::AlignRight: dst_rect.x = x - dst_rect.width; break; case Text::AlignLeft: dst_rect.x = x; break; default: assert(false); } dst_rect.y = y; dst_rect.width += 1; dst_rect.height += 1; // Need place for shadow if (dst_rect.IsOutOfBounds(dest.GetWidth(), dest.GetHeight())) return; BitmapRef text_surface; // Complete text will be on this surface text_surface = Bitmap::Create(dst_rect.width, dst_rect.height, true); text_surface->SetTransparentColor(dest.GetTransparentColor()); text_surface->Clear(); // Load the system file for the shadow and text color BitmapRef system = Cache::System(Data::system.system_name); // Load the exfont-file BitmapRef exfont = Cache::Exfont(); // Get the Shadow color Color shadow_color(Cache::system_info.sh_color); // If shadow is pure black, increase blue channel // so it doesn't become transparent if ((shadow_color.red == 0) && (shadow_color.green == 0) && (shadow_color.blue == 0) ) { if (text_surface->bytes() >= 3) { shadow_color.blue++; } else { shadow_color.blue += 8; } } // Where to draw the next glyph (x pos) int next_glyph_pos = 0; // The current char is an exfont bool is_exfont = false; // This loops always renders a single char, color blends it and then puts // it onto the text_surface (including the drop shadow) for (boost::u8_to_u32_iterator<std::string::const_iterator> c(text.begin(), text.begin(), text.end()), end(text.end(), text.begin(), text.end()); c != end; ++c) { Rect next_glyph_rect(next_glyph_pos, 0, 0, 0); boost::u8_to_u32_iterator<std::string::const_iterator> next_c_it = boost::next(c); uint32_t const next_c = std::distance(c, end) > 1? *next_c_it : 0; // ExFont-Detection: Check for A-Z or a-z behind the $ if (*c == '$' && std::isalpha(next_c)) { int exfont_value = -1; // Calculate which exfont shall be rendered if (islower(next_c)) { exfont_value = 26 + next_c - 'a'; } else if (isupper(next_c)) { exfont_value = next_c - 'A'; } else { assert(false); } is_exfont = true; BitmapRef mask = Bitmap::Create(12, 12, true); // Get exfont from graphic Rect const rect_exfont((exfont_value % 13) * 12, (exfont_value / 13) * 12, 12, 12); // Create a mask mask->Clear(); mask->Blit(0, 0, *exfont, rect_exfont, 255); // Get color region from system graphic Rect clip_system(8+16*(color%10), 4+48+16*(color/10), 6, 12); BitmapRef char_surface = Bitmap::Create(mask->GetWidth(), mask->GetHeight(), true); char_surface->SetTransparentColor(dest.GetTransparentColor()); char_surface->Clear(); // Blit gradient color background (twice because of full glyph) char_surface->Blit(0, 0, *system, clip_system, 255); char_surface->Blit(6, 0, *system, clip_system, 255); // Blit mask onto background char_surface->MaskBlit(0, 0, *mask, mask->GetRect()); BitmapRef char_shadow = Bitmap::Create(mask->GetWidth(), mask->GetHeight(), true); char_shadow->SetTransparentColor(dest.GetTransparentColor()); char_shadow->Clear(); // Blit solid color background char_shadow->Fill(shadow_color); // Blit mask onto background char_shadow->MaskBlit(0, 0, *mask, mask->GetRect()); // Blit first shadow and then text text_surface->Blit(next_glyph_rect.x + 1, next_glyph_rect.y + 1, *char_shadow, char_shadow->GetRect(), 255); text_surface->Blit(next_glyph_rect.x, next_glyph_rect.y, *char_surface, char_surface->GetRect(), 255); } else { // Not ExFont, draw normal text font->Render(*text_surface, next_glyph_rect.x, next_glyph_rect.y, *system, color, *c); } // If it's a full size glyph, add the size of a half-size glypth twice if (is_exfont) { is_exfont = false; next_glyph_pos += 12; // Skip the next character ++c; } else { std::string const glyph(c.base(), next_c_it.base()); next_glyph_pos += Font::Default()->GetSize(glyph).width; } } BitmapRef text_bmp = Bitmap::Create(*text_surface, text_surface->GetRect()); Rect src_rect(0, 0, dst_rect.width, dst_rect.height); int iy = dst_rect.y; if (dst_rect.height > text_bmp->GetHeight()) { iy += ((dst_rect.height - text_bmp->GetHeight()) / 2); } int ix = dst_rect.x; dest.Blit(ix, iy, *text_bmp, src_rect, 255); }