BitmapRef FTFont::Glyph(char32_t glyph) { if(!check_face()) { return Font::Default()->Glyph(glyph); } if (FT_Load_Char(face_.get(), glyph, FT_LOAD_NO_BITMAP) != FT_Err_Ok) { Output::Error("Couldn't load FreeType character %d", glyph); } if (FT_Render_Glyph(face_->glyph, FT_RENDER_MODE_MONO) != FT_Err_Ok) { Output::Error("Couldn't render FreeType character %d", glyph); } FT_Bitmap const& ft_bitmap = face_->glyph->bitmap; assert(face_->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO); size_t const pitch = std::abs(ft_bitmap.pitch); int const width = ft_bitmap.width; int const height = ft_bitmap.rows; BitmapRef bm = Bitmap::Create(nullptr, width, height, 0, DynamicFormat(8,8,0,8,0,8,0,8,0,PF::Alpha)); uint8_t* data = reinterpret_cast<uint8_t*>(bm->pixels()); int dst_pitch = bm->pitch(); for(int row = 0; row < height; ++row) { for(int col = 0; col < width; ++col) { unsigned c = ft_bitmap.buffer[pitch * row + (col/8)]; unsigned bit = 7 - (col%8); data[row * dst_pitch + col] = (c & (0x01 << bit)) ? 255 : 0; } } return bm; }
static void HandleErrorOutput(const std::string& err) { // Drawing directly on the screen because message_overlay is not visible // when faded out BitmapRef surface = DisplayUi->GetDisplaySurface(); surface->FillRect(surface->GetRect(), Color(255, 0, 0, 128)); std::string error = "Error:\n"; error += err; error += "\n\nEasyRPG Player will close now. Press any key..."; Text::Draw(*surface, 11, 11, Color(0, 0, 0, 255), error); Text::Draw(*surface, 10, 10, Color(255, 255, 255, 255), error); DisplayUi->UpdateDisplay(); if (ignore_pause) { return; } Input::ResetKeys(); while (!Input::IsAnyPressed()) { DisplayUi->Sleep(1); DisplayUi->ProcessEvents(); if (Player::exit_flag) break; Input::Update(); } Input::ResetKeys(); Graphics::FrameReset(); DisplayUi->UpdateDisplay(); }
static void HandleErrorOutput(const std::string& err) { #ifdef EMSCRIPTEN // Do not execute any game logic after an error happened emscripten_cancel_main_loop(); #endif // Drawing directly on the screen because message_overlay is not visible // when faded out BitmapRef surface = DisplayUi->GetDisplaySurface(); surface->FillRect(surface->GetRect(), Color(255, 0, 0, 128)); std::string error = "Error:\n"; error += err; error += "\n\nEasyRPG Player will close now.\nPress [ENTER] key to exit..."; Text::Draw(*surface, 11, 11, Color(0, 0, 0, 255), error); Text::Draw(*surface, 10, 10, Color(255, 255, 255, 255), error); DisplayUi->UpdateDisplay(); if (ignore_pause) { return; } Input::ResetKeys(); while (!Input::IsAnyPressed()) { DisplayUi->Sleep(1); DisplayUi->ProcessEvents(); if (Player::exit_flag) break; Input::Update(); } }
BitmapScreenRef TilemapLayer::GenerateAutotiles(int count, const std::map<uint32_t, TileXY>& map) { int rows = (count + TILES_PER_ROW - 1) / TILES_PER_ROW; BitmapRef tiles = Bitmap::Create(TILES_PER_ROW * TILE_SIZE, rows * TILE_SIZE); tiles->Clear(); Rect rect(0, 0, TILE_SIZE/2, TILE_SIZE/2); std::map<uint32_t, TileXY>::const_iterator it; for (it = map.begin(); it != map.end(); ++it) { uint32_t quarters_hash = it->first; TileXY dst = it->second; // unpack the quarters data for (int j = 0; j < 2; j++) { for (int i = 0; i < 2; i++) { int x = quarters_hash >> 28; quarters_hash <<= 4; int y = quarters_hash >> 28; quarters_hash <<= 4; rect.x = (x * 2 + i) * (TILE_SIZE/2); rect.y = (y * 2 + j) * (TILE_SIZE/2); tiles->Blit((dst.x * 2 + i) * (TILE_SIZE/2), (dst.y * 2 + j) * (TILE_SIZE/2), *chipset, rect, 255); } } } return BitmapScreen::Create(tiles); }
Window_ShopParty::Window_ShopParty(int ix, int iy, int iwidth, int iheight) : Window_Base(ix, iy, iwidth, iheight) { SetContents(Bitmap::Create(width - 16, height - 16)); contents->SetTransparentColor(windowskin->GetTransparentColor()); cycle = 0; item_id = 0; const std::vector<Game_Actor*>& actors = Game_Party::GetActors(); for (size_t i = 0; i < actors.size() && i < 4; i++) { Game_Actor *actor = actors[i]; const std::string& sprite_name = actor->GetCharacterName(); int sprite_id = actor->GetCharacterIndex(); BitmapRef bm = Cache::Charset(sprite_name); int width = bm->GetWidth() / 4 / 3; int height = bm->GetHeight() / 2 / 4; for (int j = 0; j < 3; j++) { int sx = ((sprite_id % 4) * 3 + j) * width; int sy = ((sprite_id / 4) * 4 + 2) * height; Rect src(sx, sy, width, height); for (int k = 0; k < 2; k++) { BitmapRef bm2 = Bitmap::Create(width, height, true); bm2->SetTransparentColor(bm->GetTransparentColor()); bm2->Clear(); bm2->Blit(0, 0, *bm, src, 255); if (k == 0) bm2->ToneBlit(0, 0, *bm2, bm2->GetRect(), Tone(0, 0, 0, 255)); bitmaps[i][j][k] = bm2; } } } Refresh(); }
void TilemapLayer::DrawTile(Bitmap& screen, int x, int y, int row, int col, bool autotile) { if (!autotile && screen.GetTileOpacity(row, col) == Bitmap::Transparent) return; Rect rect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); BitmapRef dst = DisplayUi->GetDisplaySurface(); dst->Blit(x, y, screen, rect, 255); }
ScreenshotWindow::ScreenshotWindow(BWindow* parent, BRect frame) : BWindow(frame, B_TRANSLATE("Screenshot"), B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL, B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), fBarberPoleShown(false), fDownloadPending(false), fWorkerThread(-1) { AddToSubset(parent); atomic_set(&fCurrentScreenshotIndex, 0); fBarberPole = new BarberPole("barber pole"); fBarberPole->SetExplicitMaxSize(BSize(100, B_SIZE_UNLIMITED)); fBarberPole->Hide(); fIndexView = new BStringView("screenshot index", NULL); fToolBar = new BToolBar(); fToolBar->AddAction(MSG_PREVIOUS_SCREENSHOT, this, sNextButtonIcon->Bitmap(SharedBitmap::SIZE_22), NULL, NULL); fToolBar->AddAction(MSG_NEXT_SCREENSHOT, this, sPreviousButtonIcon->Bitmap(SharedBitmap::SIZE_22), NULL, NULL); fToolBar->AddView(fIndexView); fToolBar->AddGlue(); fToolBar->AddView(fBarberPole); fScreenshotView = new BitmapView("screenshot view"); fScreenshotView->SetExplicitMaxSize( BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)); fScreenshotView->SetScaleBitmap(false); BGroupView* groupView = new BGroupView(B_VERTICAL); groupView->SetViewColor(kBackgroundColor); // Build layout BLayoutBuilder::Group<>(this, B_VERTICAL, 0) .SetInsets(0, 3, 0, 0) .Add(fToolBar) .AddStrut(3) .AddGroup(groupView) .Add(fScreenshotView) .SetInsets(B_USE_WINDOW_INSETS) .End() ; fScreenshotView->SetLowColor(kBackgroundColor); // Set after attaching all views to prevent it from being overriden // again by BitmapView::AllAttached() CenterOnScreen(); }
// Waver, Zoom, Split Opacity void Bitmap::EffectsBlit(int x, int y, Bitmap const& src, Rect const& src_rect, int top_opacity, int bottom_opacity, int opacity_split, double zoom_x, double zoom_y, int waver_depth, double waver_phase) { int zoomed_width = (int)(src_rect.width * zoom_x); int zoomed_height = (int)(src_rect.height * zoom_y); BitmapRef draw = src.Resample(zoomed_width, zoomed_height, src_rect); EffectsBlit(x, y, *draw, draw->GetRect(), top_opacity, bottom_opacity, (int) (opacity_split * zoom_y), waver_depth, waver_phase); }
void Window_ShopParty::Refresh() { contents->Clear(); BitmapRef system = Cache::System(); if (item_id <= 0 || item_id > static_cast<int>(Data::items.size())) return; const std::vector<Game_Actor*>& actors = Main_Data::game_party->GetActors(); for (size_t i = 0; i < actors.size() && i < 4; i++) { Game_Actor *actor = actors[i]; int phase = (cycle / anim_rate) % 4; if (phase == 3) { phase = 1; } bool usable = actor->IsEquippable(item_id); BitmapRef bm = bitmaps[i][usable ? phase : 1][usable ? 1 : 0]; if (bm) { contents->Blit(i * 32, 0, *bm, bm->GetRect(), 255); } // (Shop) items are guaranteed to be valid const auto* new_item = ReaderUtil::GetElement(Data::items, item_id); bool equippable = usable && IsEquipment(new_item); if (equippable) { // check if item is equipped by each member bool is_equipped = false; for (int j = 1; j <= 5; ++j) { const RPG::Item* item = actor->GetEquipment(j); if (item) { is_equipped |= (item->ID == item_id); } } if (is_equipped) contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 24, 8, 8), 255); else { int cmp = CmpEquip(actor, new_item); if (cmp > 0) { contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 0, 8, 8), 255); } else if (cmp < 0) { contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 16, 8, 8), 255); } else { contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 8, 8, 8), 255); } } } } }
void Sprite::BlitScreenIntern(Bitmap const& draw_bitmap, Rect const& src_rect, int opacity_split) const { BitmapRef dst = DisplayUi->GetDisplaySurface(); double zoom_x = zoom_x_effect; double zoom_y = zoom_y_effect; dst->EffectsBlit(x, y, ox, oy, draw_bitmap, src_rect, Opacity(opacity_top_effect, opacity_bottom_effect, opacity_split), zoom_x, zoom_y, angle_effect != 0.0 ? angle_effect * 3.14159 / 180 : 0.0, waver_effect_depth, waver_effect_phase); }
void BattleAnimation::OnBattle2SpriteReady(FileRequestResult* result) { if (result->success) { BitmapRef bitmap = Cache::Battle2(result->file); if (bitmap->GetWidth() == 640) { large = true; } SetBitmap(bitmap); SetSrcRect(Rect(0, 0, 0, 0)); } else { Output::Warning("Couldn't find animation: %s", result->file.c_str()); } }
void Window::RefreshBackground() { background_needs_refresh = false; BitmapRef bitmap = Bitmap::Create(width, height, false); if (stretch) { bitmap->StretchBlit(*windowskin, Rect(0, 0, 32, 32), 255); } else { bitmap->TiledBlit(Rect(0, 0, 16, 16), *windowskin, bitmap->GetRect(), 255); } background->SetBitmap(bitmap); }
BitmapRef ShinonomeFont::Glyph(char32_t code) { ShinonomeGlyph const* const glyph = func_(code); assert(glyph); size_t const width = glyph->is_full? FULL_WIDTH : HALF_WIDTH; BitmapRef bm = Bitmap::Create(nullptr, width, HEIGHT, 0, DynamicFormat(8,8,0,8,0,8,0,8,0,PF::Alpha)); uint8_t* data = reinterpret_cast<uint8_t*>(bm->pixels()); int pitch = bm->pitch(); for(size_t y_ = 0; y_ < HEIGHT; ++y_) for(size_t x_ = 0; x_ < width; ++x_) data[y_*pitch+x_] = (glyph->data[y_] & (0x1 << x_)) ? 255 : 0; return bm; }
void TilemapLayer::DrawTile(Bitmap& screen, int x, int y, int row, int col, bool autotile) { Bitmap::TileOpacity op = screen.GetTileOpacity(row, col); if (!fast_blit && op == Bitmap::Transparent) return; Rect rect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); BitmapRef dst = DisplayUi->GetDisplaySurface(); if (fast_blit || op == Bitmap::Opaque) { dst->BlitFast(x, y, screen, rect, 255); } else { dst->Blit(x, y, screen, rect, 255); } }
void BitmapScreen::BlitScreenIntern(Bitmap const& draw_bitmap, int x, int y, Rect const& src_rect, bool need_scale, int bush_y) { if (! &draw_bitmap) return; BitmapRef dst = DisplayUi->GetDisplaySurface(); int opacity_split = bush_y; double zoom_x = need_scale ? zoom_x_effect : 1.0; double zoom_y = need_scale ? zoom_y_effect : 1.0; dst->EffectsBlit(x, y, draw_bitmap, src_rect, opacity_top_effect, opacity_bottom_effect, opacity_split, Tone(), zoom_x, zoom_y, angle_effect * 3.14159 / 180, waver_effect_depth, waver_effect_phase); }
void BattleAnimation::OnBattleSpriteReady(FileRequestResult* result) { if (result->success) { //Normally only battle2 sprites are "large" sprites - but the check doesn't hurt. BitmapRef bitmap = Cache::Battle(result->file); if (bitmap->GetWidth() == 640) { large = true; } SetBitmap(bitmap); SetSrcRect(Rect(0, 0, 0, 0)); } else { // Try battle2 FileRequestAsync* request = AsyncHandler::RequestFile("Battle2", result->file); request_id = request->Bind(&BattleAnimation::OnBattle2SpriteReady, this); request->Start(); } }
void Scene_Battle_Rpg2k3::DrawFloatText(int x, int y, int color, const std::string& text, int _duration) { Rect rect = Font::Default()->GetSize(text); BitmapRef graphic = Bitmap::Create(rect.width, rect.height); graphic->Clear(); graphic->TextDraw(-rect.x, -rect.y, color, text); Sprite* floating_text = new Sprite(); floating_text->SetBitmap(graphic); floating_text->SetOx(rect.width / 2); floating_text->SetOy(rect.height + 5); floating_text->SetX(x); floating_text->SetY(y); floating_text->SetZ(500 + y); FloatText float_text = FloatText(EASYRPG_SHARED_PTR<Sprite>(floating_text), _duration); floating_texts.push_back(float_text); }
void Window_ShopParty::OnCharsetSpriteReady(FileRequestResult* /* result */, int party_index) { Game_Actor *actor = Main_Data::game_party->GetActors()[party_index]; const std::string& sprite_name = actor->GetSpriteName(); int sprite_id = actor->GetSpriteIndex(); BitmapRef bm = Cache::Charset(sprite_name); int width = bm->GetWidth() / 4 / 3; int height = bm->GetHeight() / 2 / 4; for (int j = 0; j < 3; j++) { int sx = ((sprite_id % 4) * 3 + j) * width; int sy = ((sprite_id / 4) * 4 + 2) * height; Rect src(sx, sy, width, height); for (int k = 0; k < 2; k++) { BitmapRef bm2 = Bitmap::Create(width, height, true); bm2->Clear(); bm2->Blit(0, 0, *bm, src, 255); if (k == 0) bm2->ToneBlit(0, 0, *bm2, bm2->GetRect(), Tone(128, 128, 128, 0), Opacity::opaque); bitmaps[party_index][j][k] = bm2; } } }
BitmapScreen::BitmapScreen(BitmapRef const& bitmap) : bitmap(bitmap), bitmap_effects_valid(false), bitmap_scale_valid(false) { ClearEffects(); bitmap_changed = true; current_tone = tone_effect; current_zoom_x = zoom_x_effect; current_zoom_y = zoom_y_effect; current_flip_x = flipx_effect; current_flip_y = flipy_effect; current_flash = flash_effect; bitmap_effects_src_rect = Rect(); bitmap_scale_src_rect = Rect(); if (bitmap != NULL) { src_rect_effect = bitmap->GetRect(); bitmap->AttachBitmapScreen(this); } }
void Font::Render(Bitmap& bmp, int const x, int const y, Bitmap const& sys, int color, char32_t code) { if(color != ColorShadow) { BitmapRef system = Cache::System(); Render(bmp, x + 1, y + 1, system->GetShadowColor(), code); } BitmapRef bm = Glyph(code); unsigned const src_x = color == ColorShadow? 16 : color % 10 * 16 + 2, src_y = color == ColorShadow? 32 : color / 10 * 16 + 48 + 16 - bm->height(); bmp.MaskedBlit(Rect(x, y, bm->width(), bm->height()), *bm, 0, 0, sys, src_x, src_y); }
void Battle::Enemy::CreateSprite() { BitmapRef graphic = Cache::Monster(rpg_enemy->battler_name); bool hue_change = rpg_enemy->battler_hue != 0; if (hue_change) { BitmapRef new_graphic = Bitmap::Create(graphic->GetWidth(), graphic->GetHeight()); new_graphic->HueChangeBlit(0, 0, *graphic, graphic->GetRect(), rpg_enemy->battler_hue); graphic = new_graphic; } sprite.reset(new Sprite()); sprite->SetBitmap(graphic); sprite->SetOx(graphic->GetWidth() / 2); sprite->SetOy(graphic->GetHeight() / 2); sprite->SetX(member->x); sprite->SetY(member->y); sprite->SetZ(member->y); sprite->SetVisible(!game_enemy->IsHidden()); }
void Font::Render(Bitmap& bmp, int x, int y, Color const& color, char32_t code) { BitmapRef bm = Glyph(code); bmp.MaskedBlit(Rect(x, y, bm->width(), bm->height()), *bm, 0, 0, color); }
void Window_ShopParty::Refresh() { contents->Clear(); BitmapRef system = Cache::System(); if (item_id <= 0 || item_id > Data::items.size()) return; const std::vector<Game_Actor*>& actors = Main_Data::game_party->GetActors(); for (size_t i = 0; i < actors.size() && i < 4; i++) { Game_Actor *actor = actors[i]; int phase = (cycle / anim_rate) % 4; if (phase == 3) { phase = 1; } bool equippable = actor->IsEquippable(item_id); BitmapRef bm = bitmaps[i][equippable ? phase : 1][equippable ? 1 : 0]; if (bm) { contents->Blit(i * 32, 0, *bm, bm->GetRect(), 255); } if (equippable) { //check if item is equipped by each member bool is_equipped = false; for (int j = 0; j < 5; ++j) { const RPG::Item* item = actor->GetEquipment(j); if (item) { is_equipped |= (item->ID == item_id); } } if (is_equipped) contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 24, 8, 8), 255); else { RPG::Item* new_item = &Data::items[item_id - 1]; int item_type = new_item->type; RPG::Item* current_item = NULL; switch (item_type) { //get the current equipped item case RPG::Item::Type_weapon: if (actor->GetWeaponId() > 0) current_item = &Data::items[actor->GetWeaponId() - 1]; else current_item = &Data::items[0]; break; case RPG::Item::Type_helmet: if (actor->GetHelmetId() > 0) current_item = &Data::items[actor->GetHelmetId() - 1]; else current_item = &Data::items[0]; break; case RPG::Item::Type_shield: if (actor->GetShieldId() > 0) current_item = &Data::items[actor->GetShieldId() - 1]; else current_item = &Data::items[0]; break; case RPG::Item::Type_armor: if (actor->GetArmorId() > 0) current_item = &Data::items[actor->GetArmorId() - 1]; else current_item = &Data::items[0]; break; case RPG::Item::Type_accessory: if (actor->GetAccessoryId() > 0) current_item = &Data::items[actor->GetAccessoryId() -1]; else current_item = &Data::items[0]; break; } if (current_item != NULL) { int diff_atk = new_item->atk_points1 - current_item->atk_points1; int diff_def = new_item->def_points1 - current_item->def_points1; int diff_spi = new_item->spi_points1 - current_item->spi_points1; int diff_agi = new_item->agi_points1 - current_item->agi_points1; if (diff_atk > 0 || diff_def > 0 || diff_spi > 0 || diff_agi > 0) contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 0, 8, 8), 255); else if (diff_atk < 0 || diff_def < 0 || diff_spi < 0 || diff_agi < 0) contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 16, 8, 8), 255); else contents->Blit(i * 32 + 20, 24, *system, Rect(128 + 8 * phase, 8, 8, 8), 255); } } } } }
/* static */ void ScreenshotWindow::CleanupIcons() { sNextButtonIcon.Unset(); sPreviousButtonIcon.Unset(); }
void Frame::Draw() { if (frame_bitmap && Data::system.show_frame) { BitmapRef dst = DisplayUi->GetDisplaySurface(); dst->Blit(0, 0, *frame_bitmap, frame_bitmap->GetRect(), 255); } }
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); }
BitmapRef Bitmap::Create(int width, int height, const Color& color) { BitmapRef surface = Bitmap::Create(width, height, false); surface->Fill(color); return surface; }