예제 #1
0
/**
 * Configure a ViewPort for rendering (a part of) the map into a screenshot.
 * @param t Screenshot type
 * @param [out] vp Result viewport
 */
void SetupScreenshotViewport(ScreenshotType t, ViewPort *vp)
{
	/* Determine world coordinates of screenshot */
	if (t == SC_WORLD) {
		vp->zoom = ZOOM_LVL_WORLD_SCREENSHOT;

		TileIndex north_tile = _settings_game.construction.freeform_edges ? TileXY(1, 1) : TileXY(0, 0);
		TileIndex south_tile = MapSize() - 1;

		/* We need to account for a hill or high building at tile 0,0. */
		int extra_height_top = TilePixelHeight(north_tile) + 150;
		/* If there is a hill at the bottom don't create a large black area. */
		int reclaim_height_bottom = TilePixelHeight(south_tile);

		vp->virtual_left   = RemapCoords(TileX(south_tile) * TILE_SIZE, TileY(north_tile) * TILE_SIZE, 0).x;
		vp->virtual_top    = RemapCoords(TileX(north_tile) * TILE_SIZE, TileY(north_tile) * TILE_SIZE, extra_height_top).y;
		vp->virtual_width  = RemapCoords(TileX(north_tile) * TILE_SIZE, TileY(south_tile) * TILE_SIZE, 0).x                     - vp->virtual_left + 1;
		vp->virtual_height = RemapCoords(TileX(south_tile) * TILE_SIZE, TileY(south_tile) * TILE_SIZE, reclaim_height_bottom).y - vp->virtual_top  + 1;
	} else {
		vp->zoom = (t == SC_ZOOMEDIN) ? _settings_client.gui.zoom_min : ZOOM_LVL_VIEWPORT;

		Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
		vp->virtual_left   = w->viewport->virtual_left;
		vp->virtual_top    = w->viewport->virtual_top;
		vp->virtual_width  = w->viewport->virtual_width;
		vp->virtual_height = w->viewport->virtual_height;
	}

	/* Compute pixel coordinates */
	vp->left = 0;
	vp->top = 0;
	vp->width  = UnScaleByZoom(vp->virtual_width,  vp->zoom);
	vp->height = UnScaleByZoom(vp->virtual_height, vp->zoom);
	vp->overlay = NULL;
}
예제 #2
0
/** Make a zoomed-in screenshot of the currently visible area. */
static bool MakeZoomedInScreenshot()
{
	Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
	ViewPort vp;

	vp.zoom = _settings_client.gui.zoom_min;
	vp.left = w->viewport->left;
	vp.top = w->viewport->top;
	vp.virtual_left = w->viewport->virtual_left;
	vp.virtual_top = w->viewport->virtual_top;
	vp.virtual_width = w->viewport->virtual_width;
	vp.width = UnScaleByZoom(vp.virtual_width, vp.zoom);
	vp.virtual_height = w->viewport->virtual_height;
	vp.height = UnScaleByZoom(vp.virtual_height, vp.zoom);

	const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format;
	return sf->proc(MakeScreenshotName(SCREENSHOT_NAME, sf->extension), LargeWorldCallback, &vp, vp.width, vp.height,
			BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette.palette);
}
예제 #3
0
파일: ship_gui.cpp 프로젝트: Ayutac/OpenTTD
/**
 * Draws an image of a ship
 * @param v         Front vehicle
 * @param left      The minimum horizontal position
 * @param right     The maximum horizontal position
 * @param y         Vertical position to draw at
 * @param selection Selected vehicle to draw a frame around
 */
void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type)
{
	bool rtl = _current_text_dir == TD_RTL;

	SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
	const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);

	int width = UnScaleByZoom(real_sprite->width, ZOOM_LVL_GUI);
	int x_offs = UnScaleByZoom(real_sprite->x_offs, ZOOM_LVL_GUI);
	int x = rtl ? right - width - x_offs : left - x_offs;

	DrawSprite(sprite, GetVehiclePalette(v), x, y + 10);

	if (v->index == selection) {
		x += x_offs;
		y += UnScaleByZoom(real_sprite->y_offs, ZOOM_LVL_GUI) + 10;
		DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleByZoom(real_sprite->height, ZOOM_LVL_GUI) + 1, COLOUR_WHITE, FR_BORDERONLY);
	}
}
예제 #4
0
/**
 * Resizes the sprite in a very simple way, takes every n-th pixel and every n-th row
 *
 * @param sprite_src sprite to resize
 * @param zoom resizing scale
 * @return resized sprite
 */
static const SpriteLoader::Sprite *ResizeSprite(const SpriteLoader::Sprite *sprite_src, ZoomLevel zoom)
{
	SpriteLoader::Sprite *sprite = MallocT<SpriteLoader::Sprite>(1);

	if (zoom == ZOOM_LVL_NORMAL) {
		memcpy(sprite, sprite_src, sizeof(*sprite));
		uint size = sprite_src->height * sprite_src->width;
		sprite->data = MallocT<SpriteLoader::CommonPixel>(size);
		memcpy(sprite->data, sprite_src->data, size * sizeof(SpriteLoader::CommonPixel));
		return sprite;
	}

	sprite->height = UnScaleByZoom(sprite_src->height, zoom);
	sprite->width  = UnScaleByZoom(sprite_src->width,  zoom);
	sprite->x_offs = UnScaleByZoom(sprite_src->x_offs, zoom);
	sprite->y_offs = UnScaleByZoom(sprite_src->y_offs, zoom);

	uint size = sprite->height * sprite->width;
	SpriteLoader::CommonPixel *dst = sprite->data = CallocT<SpriteLoader::CommonPixel>(size);

	const SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite_src->data;
	const SpriteLoader::CommonPixel *src_end = src + sprite_src->height * sprite_src->width;

	uint scaled_1 = ScaleByZoom(1, zoom);

	for (uint y = 0; y < sprite->height; y++) {
		if (src >= src_end) src = src_end - sprite_src->width;

		const SpriteLoader::CommonPixel *src_ln = src + sprite_src->width * scaled_1;
		for (uint x = 0; x < sprite->width; x++) {
			if (src >= src_ln) src = src_ln - 1;
			*dst = *src;
			dst++;
			src += scaled_1;
		}

		src = src_ln;
	}

	return sprite;
}
예제 #5
0
Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
{
	/* Make memory for all zoom-levels */
	uint memory = sizeof(SpriteData);

	for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
		memory += UnScaleByZoom(sprite->height, i) * UnScaleByZoom(sprite->width, i);
	}

	/* We have no idea how much memory we really need, so just guess something */
	memory *= 5;

	/* Don't allocate memory each time, but just keep some
	 * memory around as this function is called quite often
	 * and the memory usage is quite low. */
	static ReusableBuffer<byte> temp_buffer;
	SpriteData *temp_dst = (SpriteData *)temp_buffer.Allocate(memory);
	byte *dst = temp_dst->data;

	/* Make the sprites per zoom-level */
	for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
		/* Store the index table */
		uint offset = dst - temp_dst->data;
		temp_dst->offset[i] = offset;

		/* cache values, because compiler can't cache it */
		int scaled_height = UnScaleByZoom(sprite->height, i);
		int scaled_width  = UnScaleByZoom(sprite->width,  i);
		int scaled_1      =   ScaleByZoom(1,              i);

		for (int y = 0; y < scaled_height; y++) {
			uint trans = 0;
			uint pixels = 0;
			uint last_colour = 0;
			byte *count_dst = NULL;

			/* Store the scaled image */
			const SpriteLoader::CommonPixel *src = &sprite->data[ScaleByZoom(y, i) * sprite->width];
			const SpriteLoader::CommonPixel *src_end = &src[sprite->width];

			for (int x = 0; x < scaled_width; x++) {
				uint colour = 0;

				/* Get the colour keeping in mind the zoom-level */
				for (int j = 0; j < scaled_1; j++) {
					if (src->m != 0) colour = src->m;
					/* Because of the scaling it might happen we read outside the buffer. Avoid that. */
					if (++src == src_end) break;
				}

				if (last_colour == 0 || colour == 0 || pixels == 255) {
					if (count_dst != NULL) {
						/* Write how many non-transparent bytes we get */
						*count_dst = pixels;
						pixels = 0;
						count_dst = NULL;
					}
					/* As long as we find transparency bytes, keep counting */
					if (colour == 0) {
						last_colour = 0;
						trans++;
						continue;
					}
					/* No longer transparency, so write the amount of transparent bytes */
					*dst = trans;
					dst++;
					trans = 0;
					/* Reserve a byte for the pixel counter */
					count_dst = dst;
					dst++;
				}
				last_colour = colour;
				pixels++;
				*dst = colour;
				dst++;
			}

			if (count_dst != NULL) *count_dst = pixels;

			/* Write line-ending */
			*dst = 0; dst++;
			*dst = 0; dst++;
		}
	}

	uint size = dst - (byte *)temp_dst;

	/* Safety check, to make sure we guessed the size correctly */
	assert(size < memory);

	/* Allocate the exact amount of memory we need */
	Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + size);

	dest_sprite->height = sprite->height;
	dest_sprite->width  = sprite->width;
	dest_sprite->x_offs = sprite->x_offs;
	dest_sprite->y_offs = sprite->y_offs;
	memcpy(dest_sprite->data, temp_dst, size);

	return dest_sprite;
}