1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-06 06:32:56 +01:00
Files
OpenRCT2/src/openrct2/drawing/Drawing.Sprite.BMP.cpp
2020-06-01 20:46:21 +01:00

134 lines
4.3 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2020 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "Drawing.h"
static void FASTCALL gfx_bmp_sprite_to_buffer_magnify(DrawSpriteArgs& args)
{
auto dpi = args.DPI;
auto zoom_level = dpi->zoom_level;
uint8_t zoom_amount = 1 * 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;
auto 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;
}
}
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(DrawSpriteArgs& args)
{
auto dpi = args.DPI;
auto zoom_level = dpi->zoom_level;
if (zoom_level < 0)
{
gfx_bmp_sprite_to_buffer_magnify(args);
return;
}
auto imageId = args.Image;
// Image uses the palette pointer to remap the colours of the image
if (imageId.HasPrimary())
{
// Copy non-transparent bitmap data but re-colour using the palette map.
gfx_bmp_sprite_to_buffer_x<BLEND_TRANSPARENT | BLEND_SRC>(args);
}
else if (imageId.IsBlended())
{
// 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);
}
}