mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-29 17:54:50 +01:00
Refactor bitmap drawing, one arg struct
This commit is contained in:
@@ -227,9 +227,10 @@ static bool sprite_file_export(rct_g1_element* spriteHeader, const char* outPath
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx_bmp_sprite_to_buffer(
|
||||
PaletteMap::GetDefault(), spriteHeader->offset, pixels, spriteHeader, &dpi, spriteHeader->height,
|
||||
spriteHeader->width, ImageId());
|
||||
DrawSpriteArgs args(
|
||||
&dpi, ImageId(), PaletteMap::GetDefault(), *spriteHeader, spriteHeader->width, spriteHeader->height,
|
||||
spriteHeader->offset, pixels);
|
||||
gfx_bmp_sprite_to_buffer(args);
|
||||
}
|
||||
|
||||
auto const pixels8 = dpi.bits;
|
||||
|
||||
@@ -9,16 +9,19 @@
|
||||
|
||||
#include "Drawing.h"
|
||||
|
||||
static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(
|
||||
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
|
||||
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId)
|
||||
static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(DrawSpriteArgs& args)
|
||||
{
|
||||
auto zoom_level = dest_dpi->zoom_level;
|
||||
auto dpi = args.DPI;
|
||||
auto zoom_level = dpi->zoom_level;
|
||||
uint8_t zoom_amount = 1 * zoom_level;
|
||||
uint32_t dest_line_width = (dest_dpi->width / zoom_level) + dest_dpi->pitch;
|
||||
uint32_t source_line_width = source_image->width * zoom_level;
|
||||
uint32_t dest_line_width = (dpi->width / zoom_level) + dpi->pitch;
|
||||
uint32_t source_line_width = args.SourceImage.width * zoom_level;
|
||||
|
||||
// Basic bitmap with no draw pixels
|
||||
auto source_pointer = args.SourceBits;
|
||||
auto dest_pointer = args.DestinationBits;
|
||||
auto width = args.Width;
|
||||
auto height = args.Height;
|
||||
for (; height > 0; height -= zoom_amount)
|
||||
{
|
||||
auto next_source_pointer = source_pointer + source_line_width;
|
||||
@@ -37,116 +40,94 @@ static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(
|
||||
}
|
||||
}
|
||||
|
||||
template<DrawBlendOp TBlendOp> static void FASTCALL gfx_bmp_sprite_to_buffer_x(DrawSpriteArgs& args)
|
||||
{
|
||||
auto src = args.SourceBits;
|
||||
auto dst = args.DestinationBits;
|
||||
auto& paletteMap = args.PalMap;
|
||||
auto width = args.Width;
|
||||
auto height = args.Height;
|
||||
auto dpi = args.DPI;
|
||||
auto zoomLevel = dpi->zoom_level;
|
||||
size_t srcLineWidth = args.SourceImage.width * zoomLevel;
|
||||
size_t dstLineWidth = (static_cast<size_t>(dpi->width) / zoomLevel) + dpi->pitch;
|
||||
uint8_t zoom = 1 * zoomLevel;
|
||||
for (; height > 0; height -= zoom)
|
||||
{
|
||||
auto nextSrc = src + srcLineWidth;
|
||||
auto nextDst = dst + dstLineWidth;
|
||||
for (int32_t widthRemaining = width; widthRemaining > 0; widthRemaining -= zoom, src += zoom, dst++)
|
||||
{
|
||||
if constexpr (TBlendOp & BLEND_TRANSPARENT)
|
||||
{
|
||||
// Ignore transparent pixels
|
||||
if (*src == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (((TBlendOp & BLEND_SRC) != 0) && ((TBlendOp & BLEND_DST) != 0))
|
||||
{
|
||||
*dst = paletteMap.Blend(*src, *dst);
|
||||
}
|
||||
else if constexpr ((TBlendOp & BLEND_SRC) != 0)
|
||||
{
|
||||
*dst = paletteMap[*src];
|
||||
}
|
||||
else if constexpr ((TBlendOp & BLEND_DST) != 0)
|
||||
{
|
||||
*dst = paletteMap[*dst];
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
src = nextSrc;
|
||||
dst = nextDst;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a sprite onto the buffer. There is no compression used on the sprite
|
||||
* image.
|
||||
* rct2: 0x0067A690
|
||||
* @param imageId Only flags are used.
|
||||
*/
|
||||
void FASTCALL gfx_bmp_sprite_to_buffer(
|
||||
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
|
||||
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId)
|
||||
void FASTCALL gfx_bmp_sprite_to_buffer(DrawSpriteArgs& args)
|
||||
{
|
||||
auto zoom_level = dest_dpi->zoom_level;
|
||||
auto dpi = args.DPI;
|
||||
auto zoom_level = dpi->zoom_level;
|
||||
if (zoom_level < 0)
|
||||
{
|
||||
gfx_bmp_sprite_to_buffer_magnify(
|
||||
paletteMap, source_pointer, dest_pointer, source_image, dest_dpi, height, width, imageId);
|
||||
gfx_bmp_sprite_to_buffer_magnify(args);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t zoom_amount = 1 * zoom_level;
|
||||
uint32_t dest_line_width = (dest_dpi->width / zoom_level) + dest_dpi->pitch;
|
||||
uint32_t source_line_width = source_image->width * zoom_level;
|
||||
auto imageId = args.Image;
|
||||
|
||||
// Image uses the palette pointer to remap the colours of the image
|
||||
if (imageId.HasPrimary())
|
||||
{
|
||||
// Image with remaps
|
||||
for (; height > 0; height -= zoom_amount)
|
||||
{
|
||||
uint8_t* next_source_pointer = source_pointer + source_line_width;
|
||||
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
|
||||
for (int32_t no_pixels = width; no_pixels > 0;
|
||||
no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++)
|
||||
{
|
||||
uint8_t pixel = *source_pointer;
|
||||
pixel = paletteMap[pixel];
|
||||
if (pixel)
|
||||
{
|
||||
*dest_pointer = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
source_pointer = next_source_pointer;
|
||||
dest_pointer = next_dest_pointer;
|
||||
}
|
||||
return;
|
||||
// Copy non-transparent bitmap data but re-colour using the palette map.
|
||||
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT | BLEND_SRC>(args);
|
||||
}
|
||||
|
||||
// Image is transparent. It only uses source pointer for
|
||||
// telling if it needs to be drawn not for colour. Colour provided
|
||||
// by the palette pointer.
|
||||
if (imageId.IsBlended())
|
||||
{ // Not tested
|
||||
for (; height > 0; height -= zoom_amount)
|
||||
{
|
||||
uint8_t* next_source_pointer = source_pointer + source_line_width;
|
||||
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
|
||||
|
||||
for (int32_t no_pixels = width; no_pixels > 0;
|
||||
no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++)
|
||||
{
|
||||
uint8_t pixel = *source_pointer;
|
||||
if (pixel)
|
||||
{
|
||||
pixel = *dest_pointer;
|
||||
pixel = paletteMap[pixel];
|
||||
*dest_pointer = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
source_pointer = next_source_pointer;
|
||||
dest_pointer = next_dest_pointer;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic bitmap no fancy stuff
|
||||
if (!(source_image->flags & G1_FLAG_BMP))
|
||||
{ // Not tested
|
||||
for (; height > 0; height -= zoom_amount)
|
||||
{
|
||||
uint8_t* next_source_pointer = source_pointer + source_line_width;
|
||||
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
|
||||
|
||||
for (int32_t no_pixels = width; no_pixels > 0;
|
||||
no_pixels -= zoom_amount, dest_pointer++, source_pointer += zoom_amount)
|
||||
{
|
||||
*dest_pointer = *source_pointer;
|
||||
}
|
||||
|
||||
dest_pointer = next_dest_pointer;
|
||||
source_pointer = next_source_pointer;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic bitmap with no draw pixels
|
||||
for (; height > 0; height -= zoom_amount)
|
||||
else if (imageId.IsBlended())
|
||||
{
|
||||
uint8_t* next_source_pointer = source_pointer + source_line_width;
|
||||
uint8_t* next_dest_pointer = dest_pointer + dest_line_width;
|
||||
|
||||
for (int32_t no_pixels = width; no_pixels > 0; no_pixels -= zoom_amount, dest_pointer++, source_pointer += zoom_amount)
|
||||
{
|
||||
uint8_t pixel = *source_pointer;
|
||||
if (pixel)
|
||||
{
|
||||
*dest_pointer = pixel;
|
||||
}
|
||||
}
|
||||
dest_pointer = next_dest_pointer;
|
||||
source_pointer = next_source_pointer;
|
||||
// Image is only a transparency mask. Just colour the pixels using the palette map.
|
||||
// Used for glass.
|
||||
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT | BLEND_DST>(args);
|
||||
return;
|
||||
}
|
||||
else if (!(args.SourceImage.flags & G1_FLAG_BMP))
|
||||
{
|
||||
// Copy raw bitmap data to target
|
||||
gfx_bmp_sprite_to_buffer_x<BLEND_NONE>(args);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy raw bitmap data to target but exclude transparent pixels
|
||||
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT>(args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,7 +580,9 @@ void FASTCALL gfx_draw_sprite_palette_set_software(
|
||||
{
|
||||
// Move the pointer to the start point of the source
|
||||
auto source_pointer = g1->offset + ((static_cast<size_t>(g1->width) * source_start_y) + source_start_x);
|
||||
gfx_bmp_sprite_to_buffer(paletteMap, source_pointer, dest_pointer, g1, dpi, height, width, imageId);
|
||||
|
||||
DrawSpriteArgs args(dpi, imageId, paletteMap, *g1, width, height, source_pointer, dest_pointer);
|
||||
gfx_bmp_sprite_to_buffer(args);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,28 @@ enum : uint32_t
|
||||
// REMAP_2_PLUS = REMAP 3
|
||||
};
|
||||
|
||||
using DrawBlendOp = uint8_t;
|
||||
|
||||
constexpr DrawBlendOp BLEND_NONE = 0;
|
||||
|
||||
/**
|
||||
* Only supported by BITMAP. RLE images always encode transparency via the encoding.
|
||||
* Pixel value of 0 represents transparent.
|
||||
*/
|
||||
constexpr DrawBlendOp BLEND_TRANSPARENT = 1 << 0;
|
||||
|
||||
/**
|
||||
* Whether to use the pixel value from the source image.
|
||||
* This is usually only unset for glass images where there the src is only a transparency mask.
|
||||
*/
|
||||
constexpr DrawBlendOp BLEND_SRC = 1 << 1;
|
||||
|
||||
/**
|
||||
* Whether to use the pixel value of the destination image for blending.
|
||||
* This is used for any image that filters the target image, e.g. glass or water.
|
||||
*/
|
||||
constexpr DrawBlendOp BLEND_DST = 2 << 2;
|
||||
|
||||
enum
|
||||
{
|
||||
INSET_RECT_FLAG_FILL_GREY = (1 << 2), // 0x04
|
||||
@@ -492,6 +514,32 @@ public:
|
||||
void Copy(size_t dstIndex, const PaletteMap& src, size_t srcIndex, size_t length);
|
||||
};
|
||||
|
||||
struct DrawSpriteArgs
|
||||
{
|
||||
rct_drawpixelinfo* DPI;
|
||||
ImageId Image;
|
||||
const PaletteMap& PalMap;
|
||||
const rct_g1_element& SourceImage;
|
||||
int32_t Width;
|
||||
int32_t Height;
|
||||
const uint8_t* SourceBits;
|
||||
uint8_t* DestinationBits;
|
||||
|
||||
DrawSpriteArgs(
|
||||
rct_drawpixelinfo* dpi, ImageId image, const PaletteMap& palMap, const rct_g1_element& sourceImage, int32_t width,
|
||||
int32_t height, const uint8_t* sourceBits, uint8_t* destinationBits)
|
||||
: DPI(dpi)
|
||||
, Image(image)
|
||||
, PalMap(palMap)
|
||||
, SourceImage(sourceImage)
|
||||
, Width(width)
|
||||
, Height(height)
|
||||
, SourceBits(sourceBits)
|
||||
, DestinationBits(destinationBits)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#define SPRITE_ID_PALETTE_COLOUR_1(colourId) (IMAGE_TYPE_REMAP | ((colourId) << 19))
|
||||
#define SPRITE_ID_PALETTE_COLOUR_2(primaryId, secondaryId) \
|
||||
(IMAGE_TYPE_REMAP_2_PLUS | IMAGE_TYPE_REMAP | (((primaryId) << 19) | ((secondaryId) << 24)))
|
||||
@@ -576,9 +624,7 @@ void gfx_object_free_images(uint32_t baseImageId, uint32_t count);
|
||||
void gfx_object_check_all_images_freed();
|
||||
size_t ImageListGetUsedCount();
|
||||
size_t ImageListGetMaximum();
|
||||
void FASTCALL gfx_bmp_sprite_to_buffer(
|
||||
const PaletteMap& paletteMap, uint8_t* source_pointer, uint8_t* dest_pointer, const rct_g1_element* source_image,
|
||||
rct_drawpixelinfo* dest_dpi, int32_t height, int32_t width, ImageId imageId);
|
||||
void FASTCALL gfx_bmp_sprite_to_buffer(DrawSpriteArgs& args);
|
||||
void FASTCALL gfx_rle_sprite_to_buffer(
|
||||
const uint8_t* RESTRICT source_bits_pointer, uint8_t* RESTRICT dest_bits_pointer, const PaletteMap& RESTRICT paletteMap,
|
||||
const rct_drawpixelinfo* RESTRICT dpi, ImageId imageId, int32_t source_y_start, int32_t height, int32_t source_x_start,
|
||||
|
||||
Reference in New Issue
Block a user