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;
}
示例#2
0
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();
}
示例#3
0
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();
	}
}
示例#4
0
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();
}
示例#6
0
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);
}
示例#7
0
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();
}
示例#8
0
// 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);
}
示例#9
0
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);
				}
			}
		}
	}
}
示例#10
0
文件: sprite.cpp 项目: EasyRPG/Player
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());
	}
}
示例#12
0
文件: window.cpp 项目: cheerjo/Player
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;
}
示例#14
0
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);
	}
}
示例#15
0
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();
	}
}
示例#17
0
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);
}
示例#18
0
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;
		}
	}
}
示例#19
0
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);
}
示例#21
0
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);
}
示例#23
0
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);
				}
			}
		}
	}
}
示例#24
0
/* static */ void
ScreenshotWindow::CleanupIcons()
{
	sNextButtonIcon.Unset();
	sPreviousButtonIcon.Unset();
}
示例#25
0
void Frame::Draw() {
	if (frame_bitmap && Data::system.show_frame) {
		BitmapRef dst = DisplayUi->GetDisplaySurface();
		dst->Blit(0, 0, *frame_bitmap, frame_bitmap->GetRect(), 255);
	}
}
示例#26
0
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);
}
示例#27
0
BitmapRef Bitmap::Create(int width, int height, const Color& color) {
    BitmapRef surface = Bitmap::Create(width, height, false);
	surface->Fill(color);
	return surface;
}