2014-04-02 22:50:16 +02:00
|
|
|
/*****************************************************************************
|
2024-01-01 12:52:28 +01:00
|
|
|
* Copyright (c) 2014-2024 OpenRCT2 developers
|
2014-04-03 04:08:06 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
2014-04-03 04:08:06 +02:00
|
|
|
*
|
2018-06-15 14:07:34 +02:00
|
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
2014-04-03 04:08:06 +02:00
|
|
|
*****************************************************************************/
|
2014-04-02 22:50:16 +02:00
|
|
|
|
2021-08-21 12:55:28 +02:00
|
|
|
#pragma once
|
2014-04-02 22:50:16 +02:00
|
|
|
|
2014-10-06 18:36:58 +02:00
|
|
|
#include "../common.h"
|
2022-01-25 16:41:45 +01:00
|
|
|
#include "../core/String.hpp"
|
2018-01-06 00:08:58 +01:00
|
|
|
#include "../interface/Colour.h"
|
2020-11-07 13:42:04 +01:00
|
|
|
#include "../interface/ZoomLevel.h"
|
2020-08-26 01:59:11 +02:00
|
|
|
#include "../world/Location.hpp"
|
2021-02-27 12:40:20 +01:00
|
|
|
#include "Font.h"
|
2021-12-03 19:59:33 +01:00
|
|
|
#include "ImageId.hpp"
|
2020-08-26 14:44:30 +02:00
|
|
|
#include "Text.h"
|
2014-04-04 20:59:32 +02:00
|
|
|
|
2021-02-12 18:30:53 +01:00
|
|
|
#include <memory>
|
2020-05-27 21:12:01 +02:00
|
|
|
#include <optional>
|
2020-04-25 15:36:44 +02:00
|
|
|
#include <vector>
|
|
|
|
|
2020-05-10 06:00:26 +02:00
|
|
|
struct ScreenCoordsXY;
|
2020-07-03 23:05:18 +02:00
|
|
|
struct ScreenLine;
|
2020-07-04 20:16:09 +02:00
|
|
|
struct ScreenRect;
|
2018-04-20 20:58:59 +02:00
|
|
|
namespace OpenRCT2
|
|
|
|
{
|
2020-07-30 23:19:53 +02:00
|
|
|
struct IPlatformEnvironment;
|
2022-03-19 19:02:02 +01:00
|
|
|
struct IStream;
|
|
|
|
} // namespace OpenRCT2
|
2018-04-20 20:58:59 +02:00
|
|
|
|
2019-05-01 22:51:55 +02:00
|
|
|
namespace OpenRCT2::Drawing
|
|
|
|
{
|
2020-07-30 23:19:53 +02:00
|
|
|
struct IDrawingEngine;
|
2019-05-01 22:51:55 +02:00
|
|
|
}
|
|
|
|
|
2020-05-27 21:12:01 +02:00
|
|
|
struct PaletteBGRA
|
|
|
|
{
|
|
|
|
uint8_t Blue{};
|
|
|
|
uint8_t Green{};
|
|
|
|
uint8_t Red{};
|
|
|
|
uint8_t Alpha{};
|
|
|
|
};
|
|
|
|
|
2024-03-04 22:34:08 +01:00
|
|
|
constexpr auto PALETTE_SIZE = 256U;
|
2020-05-27 21:12:01 +02:00
|
|
|
|
|
|
|
struct GamePalette
|
|
|
|
{
|
|
|
|
PaletteBGRA Colour[PALETTE_SIZE]{};
|
|
|
|
|
2024-03-04 22:34:08 +01:00
|
|
|
PaletteBGRA& operator[](size_t idx)
|
2020-05-27 21:12:01 +02:00
|
|
|
{
|
|
|
|
assert(idx < PALETTE_SIZE);
|
|
|
|
if (idx >= PALETTE_SIZE)
|
|
|
|
{
|
|
|
|
static PaletteBGRA dummy;
|
|
|
|
return dummy;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Colour[idx];
|
|
|
|
}
|
|
|
|
|
2024-03-04 22:34:08 +01:00
|
|
|
const PaletteBGRA operator[](size_t idx) const
|
2020-05-27 21:12:01 +02:00
|
|
|
{
|
|
|
|
assert(idx < PALETTE_SIZE);
|
|
|
|
if (idx >= PALETTE_SIZE)
|
|
|
|
return {};
|
|
|
|
|
|
|
|
return Colour[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit operator uint8_t*()
|
|
|
|
{
|
|
|
|
return reinterpret_cast<uint8_t*>(Colour);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
struct G1Element
|
2018-06-22 22:59:03 +02:00
|
|
|
{
|
2022-07-05 02:42:51 +02:00
|
|
|
uint8_t* offset = nullptr; // 0x00
|
|
|
|
int16_t width = 0; // 0x04
|
|
|
|
int16_t height = 0; // 0x06
|
|
|
|
int16_t x_offset = 0; // 0x08
|
|
|
|
int16_t y_offset = 0; // 0x0A
|
|
|
|
uint16_t flags = 0; // 0x0C
|
|
|
|
int32_t zoomed_offset = 0; // 0x0E
|
2018-02-14 09:42:26 +01:00
|
|
|
};
|
2016-04-27 14:09:15 +02:00
|
|
|
|
2020-04-25 15:36:44 +02:00
|
|
|
#pragma pack(push, 1)
|
2023-01-19 09:16:44 +01:00
|
|
|
struct RCTG1Header
|
2020-04-25 15:36:44 +02:00
|
|
|
{
|
2022-07-05 02:42:51 +02:00
|
|
|
uint32_t num_entries = 0;
|
|
|
|
uint32_t total_size = 0;
|
2020-04-25 15:36:44 +02:00
|
|
|
};
|
2023-01-19 09:16:44 +01:00
|
|
|
assert_struct_size(RCTG1Header, 8);
|
2020-04-25 15:36:44 +02:00
|
|
|
#pragma pack(pop)
|
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
struct Gx
|
2020-04-25 15:36:44 +02:00
|
|
|
{
|
2023-01-19 09:16:44 +01:00
|
|
|
RCTG1Header header;
|
|
|
|
std::vector<G1Element> elements;
|
2021-02-12 18:30:53 +01:00
|
|
|
std::unique_ptr<uint8_t[]> data;
|
2020-04-25 15:36:44 +02:00
|
|
|
};
|
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
struct DrawPixelInfo
|
2018-06-22 22:59:03 +02:00
|
|
|
{
|
2019-05-01 22:51:55 +02:00
|
|
|
uint8_t* bits{};
|
2021-08-16 21:51:16 +02:00
|
|
|
int32_t x{};
|
|
|
|
int32_t y{};
|
|
|
|
int32_t width{};
|
|
|
|
int32_t height{};
|
|
|
|
int32_t pitch{}; // note: this is actually (pitch - width)
|
2020-02-20 01:18:05 +01:00
|
|
|
ZoomLevel zoom_level{};
|
2019-05-01 22:51:55 +02:00
|
|
|
|
2020-08-26 19:56:58 +02:00
|
|
|
/**
|
|
|
|
* As x and y are based on 1:1 units, zooming in will cause a reduction in precision when mapping zoomed-in
|
|
|
|
* pixels to 1:1 pixels. When x, y are not a multiple of the zoom level, the remainder will be non-zero.
|
|
|
|
* The drawing of sprites will need to be offset by this amount.
|
|
|
|
*/
|
2020-08-22 14:01:11 +02:00
|
|
|
uint8_t remX{};
|
|
|
|
uint8_t remY{};
|
|
|
|
|
2021-06-04 03:10:09 +02:00
|
|
|
// Last position of drawn text.
|
|
|
|
ScreenCoordsXY lastStringPos{};
|
|
|
|
|
2019-05-01 22:51:55 +02:00
|
|
|
OpenRCT2::Drawing::IDrawingEngine* DrawingEngine{};
|
2020-08-22 14:00:15 +02:00
|
|
|
|
2020-08-26 01:59:11 +02:00
|
|
|
size_t GetBytesPerRow() const;
|
|
|
|
uint8_t* GetBitsOffset(const ScreenCoordsXY& pos) const;
|
2023-01-19 09:16:44 +01:00
|
|
|
DrawPixelInfo Crop(const ScreenCoordsXY& pos, const ScreenSize& size) const;
|
2018-02-14 09:42:26 +01:00
|
|
|
};
|
2014-04-04 20:59:32 +02:00
|
|
|
|
2023-12-03 03:15:46 +01:00
|
|
|
struct TextDrawInfo
|
|
|
|
{
|
|
|
|
int32_t startX;
|
|
|
|
int32_t startY;
|
|
|
|
int32_t x;
|
|
|
|
int32_t y;
|
|
|
|
int32_t maxX;
|
|
|
|
int32_t maxY;
|
|
|
|
int32_t flags;
|
|
|
|
uint8_t palette[8];
|
|
|
|
::FontStyle FontStyle;
|
|
|
|
const int8_t* y_offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum : uint32_t
|
|
|
|
{
|
|
|
|
TEXT_DRAW_FLAG_INSET = 1 << 0,
|
|
|
|
TEXT_DRAW_FLAG_OUTLINE = 1 << 1,
|
|
|
|
TEXT_DRAW_FLAG_DARK = 1 << 2,
|
|
|
|
TEXT_DRAW_FLAG_EXTRA_DARK = 1 << 3,
|
|
|
|
TEXT_DRAW_FLAG_NO_FORMATTING = 1 << 28,
|
|
|
|
TEXT_DRAW_FLAG_Y_OFFSET_EFFECT = 1 << 29,
|
|
|
|
TEXT_DRAW_FLAG_TTF = 1 << 30,
|
|
|
|
TEXT_DRAW_FLAG_NO_DRAW = 1u << 31
|
|
|
|
};
|
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
struct RCTG1Element
|
2018-06-22 22:59:03 +02:00
|
|
|
{
|
|
|
|
uint32_t offset; // 0x00 note: uint32_t always!
|
|
|
|
int16_t width; // 0x04
|
|
|
|
int16_t height; // 0x06
|
|
|
|
int16_t x_offset; // 0x08
|
|
|
|
int16_t y_offset; // 0x0A
|
|
|
|
uint16_t flags; // 0x0C
|
|
|
|
uint16_t zoomed_offset; // 0x0E
|
2018-02-14 09:42:26 +01:00
|
|
|
};
|
2023-01-19 09:16:44 +01:00
|
|
|
assert_struct_size(RCTG1Element, 0x10);
|
2016-06-24 22:52:28 +02:00
|
|
|
|
2018-06-22 22:59:03 +02:00
|
|
|
enum
|
|
|
|
{
|
2022-06-25 08:04:40 +02:00
|
|
|
G1_FLAG_HAS_TRANSPARENCY = (1 << 0), // Image data contains transparent pixels (0XFF) which will not be rendered
|
2018-06-22 22:59:03 +02:00
|
|
|
G1_FLAG_1 = (1 << 1),
|
2017-06-06 23:24:18 +02:00
|
|
|
G1_FLAG_RLE_COMPRESSION = (1 << 2), // Image data is encoded using RCT2's form of run length encoding
|
2018-06-22 22:59:03 +02:00
|
|
|
G1_FLAG_PALETTE = (1 << 3), // Image data is a sequence of palette entries R8G8B8
|
2017-06-06 23:24:18 +02:00
|
|
|
G1_FLAG_HAS_ZOOM_SPRITE = (1 << 4), // Use a different sprite for higher zoom levels
|
2018-06-22 22:59:03 +02:00
|
|
|
G1_FLAG_NO_ZOOM_DRAW = (1 << 5), // Does not get drawn at higher zoom levels (only zoom 0)
|
2014-05-23 13:08:20 +02:00
|
|
|
};
|
|
|
|
|
2020-05-31 14:55:47 +02:00
|
|
|
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;
|
|
|
|
|
2018-06-22 22:59:03 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
INSET_RECT_FLAG_FILL_GREY = (1 << 2), // 0x04
|
|
|
|
INSET_RECT_FLAG_BORDER_NONE = (1 << 3), // 0x08
|
|
|
|
INSET_RECT_FLAG_FILL_NONE = (1 << 4), // 0x10
|
|
|
|
INSET_RECT_FLAG_BORDER_INSET = (1 << 5), // 0x20
|
2017-06-06 23:24:18 +02:00
|
|
|
INSET_RECT_FLAG_FILL_DONT_LIGHTEN = (1 << 6), // 0x40
|
2018-06-22 22:59:03 +02:00
|
|
|
INSET_RECT_FLAG_FILL_MID_LIGHT = (1 << 7), // 0x80
|
2016-11-10 18:54:33 +01:00
|
|
|
};
|
|
|
|
|
2020-12-05 19:13:59 +01:00
|
|
|
enum class FilterPaletteID : int32_t
|
2018-06-22 22:59:03 +02:00
|
|
|
{
|
2020-12-05 19:13:59 +01:00
|
|
|
PaletteNull = 0,
|
|
|
|
|
2023-04-06 09:36:07 +02:00
|
|
|
PaletteWater = COLOUR_COUNT,
|
|
|
|
|
2023-04-09 22:29:35 +02:00
|
|
|
PaletteLandMarker0, // North (corner/edge)
|
|
|
|
PaletteLandMarker1, // East (corner/edge)
|
|
|
|
PaletteLandMarker2, // South (corner/edge)
|
|
|
|
PaletteLandMarker3, // West (corner/edge)
|
|
|
|
PaletteSceneryGroundMarker,
|
2023-04-08 10:50:46 +02:00
|
|
|
PaletteWaterMarker,
|
2023-04-09 22:29:35 +02:00
|
|
|
PaletteQuarterMarker0, // North (not sure why it couldn't just use PaletteLandMarker0)
|
|
|
|
PaletteQuarterMarker1, // East
|
|
|
|
PaletteQuarterMarker2, // South
|
|
|
|
PaletteQuarterMarker3, // West
|
|
|
|
PaletteRideGroundMarker,
|
|
|
|
PaletteGhost, // Construction marker
|
|
|
|
Palette45, // Decolourise + lighten
|
2023-04-06 09:36:07 +02:00
|
|
|
Palette46,
|
|
|
|
|
|
|
|
PaletteDarken3,
|
|
|
|
|
|
|
|
PaletteDarken1 = PaletteDarken3 + 2,
|
|
|
|
PaletteDarken2,
|
|
|
|
Palette51, // Decolourise + darken
|
|
|
|
PaletteTranslucentGrey,
|
|
|
|
PaletteTranslucentGreyHighlight,
|
|
|
|
PaletteTranslucentGreyShadow,
|
|
|
|
PaletteTranslucentLightBlue,
|
|
|
|
PaletteTranslucentLightBlueHighlight,
|
|
|
|
PaletteTranslucentLightBlueShadow,
|
|
|
|
PaletteTranslucentBordeauxRed,
|
|
|
|
PaletteTranslucentBordeauxRedHighlight,
|
|
|
|
PaletteTranslucentBordeauxRedShadow,
|
|
|
|
PaletteTranslucentDarkGreen,
|
|
|
|
PaletteTranslucentDarkGreenHighlight,
|
|
|
|
PaletteTranslucentDarkGreenShadow,
|
|
|
|
PaletteTranslucentLightPurple,
|
|
|
|
PaletteTranslucentLightPurpleHighlight,
|
|
|
|
PaletteTranslucentLightPurpleShadow,
|
|
|
|
PaletteTranslucentDarkOliveGreen,
|
|
|
|
PaletteTranslucentDarkOliveGreenHighlight,
|
|
|
|
PaletteTranslucentDarkOliveGreenShadow,
|
|
|
|
PaletteTranslucentLightBrown,
|
|
|
|
PaletteTranslucentLightBrownHighlight,
|
|
|
|
PaletteTranslucentLightBrownShadow,
|
|
|
|
PaletteTranslucentYellow,
|
|
|
|
PaletteTranslucentYellowHighlight,
|
|
|
|
PaletteTranslucentYellowShadow,
|
|
|
|
PaletteTranslucentMossGreen,
|
|
|
|
PaletteTranslucentMossGreenHighlight,
|
|
|
|
PaletteTranslucentMossGreenShadow,
|
|
|
|
PaletteTranslucentOliveGreen,
|
|
|
|
PaletteTranslucentOliveGreenHighlight,
|
|
|
|
PaletteTranslucentOliveGreenShadow,
|
|
|
|
PaletteTranslucentBrightGreen,
|
|
|
|
PaletteTranslucentBrightGreenHighlight,
|
|
|
|
PaletteTranslucentBrightGreenShadow,
|
|
|
|
PaletteTranslucentSalmonPink,
|
|
|
|
PaletteTranslucentSalmonPinkHighlight,
|
|
|
|
PaletteTranslucentSalmonPinkShadow,
|
|
|
|
PaletteTranslucentBrightPurple,
|
|
|
|
PaletteTranslucentBrightPurpleHighlight,
|
|
|
|
PaletteTranslucentBrightPurpleShadow,
|
|
|
|
PaletteTranslucentBrightRed,
|
|
|
|
PaletteTranslucentBrightRedHighlight,
|
|
|
|
PaletteTranslucentBrightRedShadow,
|
|
|
|
PaletteTranslucentLightOrange,
|
|
|
|
PaletteTranslucentLightOrangeHighlight,
|
|
|
|
PaletteTranslucentLightOrangeShadow,
|
|
|
|
PaletteTranslucentTeal,
|
|
|
|
PaletteTranslucentTealHighlight,
|
|
|
|
PaletteTranslucentTealShadow,
|
|
|
|
PaletteTranslucentBrightPink,
|
|
|
|
PaletteTranslucentBrightPinkHighlight,
|
|
|
|
PaletteTranslucentBrightPinkShadow,
|
|
|
|
PaletteTranslucentDarkBrown,
|
|
|
|
PaletteTranslucentDarkBrownHighlight,
|
|
|
|
PaletteTranslucentDarkBrownShadow,
|
|
|
|
PaletteTranslucentLightPink,
|
|
|
|
PaletteTranslucentLightPinkHighlight,
|
|
|
|
PaletteTranslucentLightPinkShadow,
|
|
|
|
PaletteTranslucentWhite,
|
|
|
|
PaletteTranslucentWhiteHighlight,
|
|
|
|
PaletteTranslucentWhiteShadow,
|
|
|
|
PaletteGlass,
|
2020-12-05 19:13:59 +01:00
|
|
|
PaletteGlassBlack = PaletteGlass + COLOUR_BLACK,
|
|
|
|
PaletteGlassGrey = PaletteGlass + COLOUR_GREY,
|
|
|
|
PaletteGlassWhite = PaletteGlass + COLOUR_WHITE,
|
|
|
|
PaletteGlassDarkPurple = PaletteGlass + COLOUR_DARK_PURPLE,
|
|
|
|
PaletteGlassLightPurple = PaletteGlass + COLOUR_LIGHT_PURPLE,
|
|
|
|
PaletteGlassBrightPurple = PaletteGlass + COLOUR_BRIGHT_PURPLE,
|
|
|
|
PaletteGlassDarkBlue = PaletteGlass + COLOUR_DARK_BLUE,
|
|
|
|
PaletteGlassLightBlue = PaletteGlass + COLOUR_LIGHT_BLUE,
|
|
|
|
PaletteGlassIcyBlue = PaletteGlass + COLOUR_ICY_BLUE,
|
|
|
|
PaletteGlassTeal = PaletteGlass + COLOUR_TEAL,
|
|
|
|
PaletteGlassAquamarine = PaletteGlass + COLOUR_AQUAMARINE,
|
|
|
|
PaletteGlassSaturatedGreen = PaletteGlass + COLOUR_SATURATED_GREEN,
|
|
|
|
PaletteGlassDarkGreen = PaletteGlass + COLOUR_DARK_GREEN,
|
|
|
|
PaletteGlassMossGreen = PaletteGlass + COLOUR_MOSS_GREEN,
|
|
|
|
PaletteGlassBrightGreen = PaletteGlass + COLOUR_BRIGHT_GREEN,
|
|
|
|
PaletteGlassOliveGreen = PaletteGlass + COLOUR_OLIVE_GREEN,
|
|
|
|
PaletteGlassDarkOliveGreen = PaletteGlass + COLOUR_DARK_OLIVE_GREEN,
|
|
|
|
PaletteGlassBrightYellow = PaletteGlass + COLOUR_BRIGHT_YELLOW,
|
|
|
|
PaletteGlassYellow = PaletteGlass + COLOUR_YELLOW,
|
|
|
|
PaletteGlassDarkYellow = PaletteGlass + COLOUR_DARK_YELLOW,
|
|
|
|
PaletteGlassLightOrange = PaletteGlass + COLOUR_LIGHT_ORANGE,
|
|
|
|
PaletteGlassDarkOrange = PaletteGlass + COLOUR_DARK_ORANGE,
|
|
|
|
PaletteGlassLightBrown = PaletteGlass + COLOUR_LIGHT_BROWN,
|
|
|
|
PaletteGlassSaturatedBrown = PaletteGlass + COLOUR_SATURATED_BROWN,
|
|
|
|
PaletteGlassDarkBrown = PaletteGlass + COLOUR_DARK_BROWN,
|
|
|
|
PaletteGlassSalmonPink = PaletteGlass + COLOUR_SALMON_PINK,
|
|
|
|
PaletteGlassBordeauxRed = PaletteGlass + COLOUR_BORDEAUX_RED,
|
|
|
|
PaletteGlassSaturatedRed = PaletteGlass + COLOUR_SATURATED_RED,
|
|
|
|
PaletteGlassBrightRed = PaletteGlass + COLOUR_BRIGHT_RED,
|
|
|
|
PaletteGlassDarkPink = PaletteGlass + COLOUR_DARK_PINK,
|
|
|
|
PaletteGlassBrightPink = PaletteGlass + COLOUR_BRIGHT_PINK,
|
|
|
|
PaletteGlassLightPink = PaletteGlass + COLOUR_LIGHT_PINK,
|
2023-04-06 09:36:07 +02:00
|
|
|
PaletteGlassDarkOliveDark = PaletteGlass + COLOUR_DARK_OLIVE_DARK,
|
|
|
|
PaletteGlassDarkOliveLight = PaletteGlass + COLOUR_DARK_OLIVE_LIGHT,
|
|
|
|
PaletteGlassSaturatedBrownLight = PaletteGlass + COLOUR_SATURATED_BROWN_LIGHT,
|
|
|
|
PaletteGlassBordeauxRedDark = PaletteGlass + COLOUR_BORDEAUX_RED_DARK,
|
|
|
|
PaletteGlassBordeauxRedLight = PaletteGlass + COLOUR_BORDEAUX_RED_LIGHT,
|
|
|
|
PaletteGlassGrassGreenDark = PaletteGlass + COLOUR_GRASS_GREEN_DARK,
|
|
|
|
PaletteGlassGrassGreenLight = PaletteGlass + COLOUR_GRASS_GREEN_LIGHT,
|
|
|
|
PaletteGlassOliveDark = PaletteGlass + COLOUR_OLIVE_DARK,
|
|
|
|
PaletteGlassOliveLight = PaletteGlass + COLOUR_OLIVE_LIGHT,
|
|
|
|
PaletteGlassSaturatedGreenLight = PaletteGlass + COLOUR_SATURATED_GREEN_LIGHT,
|
|
|
|
PaletteGlassTanDark = PaletteGlass + COLOUR_TAN_DARK,
|
|
|
|
PaletteGlassTanLight = PaletteGlass + COLOUR_TAN_LIGHT,
|
|
|
|
PaletteGlassDullPurpleLight = PaletteGlass + COLOUR_DULL_PURPLE_LIGHT,
|
|
|
|
PaletteGlassDullGreenDark = PaletteGlass + COLOUR_DULL_GREEN_DARK,
|
|
|
|
PaletteGlassDullGreenLight = PaletteGlass + COLOUR_DULL_GREEN_LIGHT,
|
|
|
|
PaletteGlassSaturatedPurpleDark = PaletteGlass + COLOUR_SATURATED_PURPLE_DARK,
|
|
|
|
PaletteGlassSaturatedPurpleLight = PaletteGlass + COLOUR_SATURATED_PURPLE_LIGHT,
|
|
|
|
PaletteGlassOrangeLight = PaletteGlass + COLOUR_ORANGE_LIGHT,
|
|
|
|
PaletteGlassAquaDark = PaletteGlass + COLOUR_AQUA_DARK,
|
|
|
|
PaletteGlassMagentaLight = PaletteGlass + COLOUR_MAGENTA_LIGHT,
|
|
|
|
PaletteGlassDullBrownDark = PaletteGlass + COLOUR_DULL_BROWN_DARK,
|
|
|
|
PaletteGlassDullBrownLight = PaletteGlass + COLOUR_DULL_BROWN_LIGHT,
|
|
|
|
PaletteGlassInvisible = PaletteGlass + COLOUR_INVISIBLE,
|
|
|
|
PaletteGlassVoid = PaletteGlass + COLOUR_VOID,
|
2018-02-14 09:42:26 +01:00
|
|
|
};
|
2016-11-09 21:44:25 +01:00
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
struct TranslucentWindowPalette
|
2018-06-22 22:59:03 +02:00
|
|
|
{
|
2020-12-05 19:13:59 +01:00
|
|
|
FilterPaletteID base;
|
|
|
|
FilterPaletteID highlight;
|
|
|
|
FilterPaletteID shadow;
|
2018-02-14 09:42:26 +01:00
|
|
|
};
|
2016-11-10 13:20:47 +01:00
|
|
|
|
2020-05-28 20:52:20 +02:00
|
|
|
/**
|
|
|
|
* Represents an 8-bit indexed map that maps from one palette index to another.
|
|
|
|
*/
|
|
|
|
struct PaletteMap
|
|
|
|
{
|
|
|
|
private:
|
2020-05-28 22:44:24 +02:00
|
|
|
uint8_t* _data{};
|
|
|
|
uint32_t _dataLength{};
|
2020-05-30 15:23:48 +02:00
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
2020-05-28 22:44:24 +02:00
|
|
|
uint16_t _numMaps;
|
2020-05-30 15:23:48 +02:00
|
|
|
#pragma clang diagnostic pop
|
2020-05-28 22:44:24 +02:00
|
|
|
uint16_t _mapLength;
|
2020-05-28 20:52:20 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
static const PaletteMap& GetDefault();
|
|
|
|
|
|
|
|
PaletteMap() = default;
|
|
|
|
|
2020-05-28 22:44:24 +02:00
|
|
|
PaletteMap(uint8_t* data, uint16_t numMaps, uint16_t mapLength)
|
|
|
|
: _data(data)
|
|
|
|
, _dataLength(numMaps * mapLength)
|
|
|
|
, _numMaps(numMaps)
|
2020-05-28 20:52:20 +02:00
|
|
|
, _mapLength(mapLength)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template<std::size_t TSize>
|
|
|
|
PaletteMap(uint8_t (&map)[TSize])
|
2020-05-28 22:44:24 +02:00
|
|
|
: _data(map)
|
|
|
|
, _dataLength(static_cast<uint32_t>(std::size(map)))
|
|
|
|
, _numMaps(1)
|
|
|
|
, _mapLength(static_cast<uint16_t>(std::size(map)))
|
2020-05-28 20:52:20 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t& operator[](size_t index);
|
|
|
|
uint8_t operator[](size_t index) const;
|
2020-05-28 22:44:24 +02:00
|
|
|
uint8_t Blend(uint8_t src, uint8_t dst) const;
|
2020-05-28 20:52:20 +02:00
|
|
|
void Copy(size_t dstIndex, const PaletteMap& src, size_t srcIndex, size_t length);
|
|
|
|
};
|
|
|
|
|
2020-05-31 14:55:47 +02:00
|
|
|
struct DrawSpriteArgs
|
|
|
|
{
|
|
|
|
ImageId Image;
|
|
|
|
const PaletteMap& PalMap;
|
2023-01-19 09:16:44 +01:00
|
|
|
const G1Element& SourceImage;
|
2020-05-31 15:46:23 +02:00
|
|
|
int32_t SrcX;
|
|
|
|
int32_t SrcY;
|
2020-05-31 14:55:47 +02:00
|
|
|
int32_t Width;
|
|
|
|
int32_t Height;
|
|
|
|
uint8_t* DestinationBits;
|
|
|
|
|
|
|
|
DrawSpriteArgs(
|
2023-01-19 09:16:44 +01:00
|
|
|
ImageId image, const PaletteMap& palMap, const G1Element& sourceImage, int32_t srcX, int32_t srcY, int32_t width,
|
2021-08-25 14:37:44 +02:00
|
|
|
int32_t height, uint8_t* destinationBits)
|
|
|
|
: Image(image)
|
2020-05-31 14:55:47 +02:00
|
|
|
, PalMap(palMap)
|
|
|
|
, SourceImage(sourceImage)
|
2020-05-31 15:46:23 +02:00
|
|
|
, SrcX(srcX)
|
|
|
|
, SrcY(srcY)
|
2020-05-31 14:55:47 +02:00
|
|
|
, Width(width)
|
|
|
|
, Height(height)
|
|
|
|
, DestinationBits(destinationBits)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-06-03 02:49:42 +02:00
|
|
|
template<DrawBlendOp TBlendOp> bool FASTCALL BlitPixel(const uint8_t* src, uint8_t* dst, const PaletteMap& paletteMap)
|
|
|
|
{
|
|
|
|
if constexpr (TBlendOp & BLEND_TRANSPARENT)
|
|
|
|
{
|
|
|
|
// Ignore transparent pixels
|
|
|
|
if (*src == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if constexpr (((TBlendOp & BLEND_SRC) != 0) && ((TBlendOp & BLEND_DST) != 0))
|
|
|
|
{
|
|
|
|
auto pixel = paletteMap.Blend(*src, *dst);
|
|
|
|
if constexpr (TBlendOp & BLEND_TRANSPARENT)
|
|
|
|
{
|
|
|
|
if (pixel == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dst = pixel;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if constexpr ((TBlendOp & BLEND_SRC) != 0)
|
|
|
|
{
|
|
|
|
auto pixel = paletteMap[*src];
|
|
|
|
if constexpr (TBlendOp & BLEND_TRANSPARENT)
|
|
|
|
{
|
|
|
|
if (pixel == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dst = pixel;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if constexpr ((TBlendOp & BLEND_DST) != 0)
|
|
|
|
{
|
|
|
|
auto pixel = paletteMap[*dst];
|
|
|
|
if constexpr (TBlendOp & BLEND_TRANSPARENT)
|
|
|
|
{
|
|
|
|
if (pixel == 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*dst = pixel;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*dst = *src;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template<DrawBlendOp TBlendOp>
|
|
|
|
void FASTCALL BlitPixels(const uint8_t* src, uint8_t* dst, const PaletteMap& paletteMap, uint8_t zoom, size_t dstPitch)
|
|
|
|
{
|
|
|
|
auto yDstSkip = dstPitch - zoom;
|
|
|
|
for (uint8_t yy = 0; yy < zoom; yy++)
|
|
|
|
{
|
|
|
|
for (uint8_t xx = 0; xx < zoom; xx++)
|
|
|
|
{
|
|
|
|
BlitPixel<TBlendOp>(src, dst, paletteMap);
|
|
|
|
dst++;
|
|
|
|
}
|
|
|
|
dst += yDstSkip;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-26 18:03:53 +02:00
|
|
|
constexpr uint8_t kPaletteTotalOffsets = 192;
|
2016-04-26 00:00:58 +02:00
|
|
|
|
2016-11-10 18:54:33 +01:00
|
|
|
#define INSET_RECT_F_30 (INSET_RECT_FLAG_BORDER_INSET | INSET_RECT_FLAG_FILL_NONE)
|
|
|
|
#define INSET_RECT_F_60 (INSET_RECT_FLAG_BORDER_INSET | INSET_RECT_FLAG_FILL_DONT_LIGHTEN)
|
|
|
|
#define INSET_RECT_F_E0 (INSET_RECT_FLAG_BORDER_INSET | INSET_RECT_FLAG_FILL_DONT_LIGHTEN | INSET_RECT_FLAG_FILL_MID_LIGHT)
|
|
|
|
|
2016-10-01 18:33:30 +02:00
|
|
|
#define MAX_SCROLLING_TEXT_MODES 38
|
|
|
|
|
2020-05-27 21:12:01 +02:00
|
|
|
extern GamePalette gPalette;
|
2018-06-20 17:28:51 +02:00
|
|
|
extern uint8_t gGamePalette[256 * 4];
|
|
|
|
extern uint32_t gPaletteEffectFrame;
|
2020-12-05 19:13:59 +01:00
|
|
|
extern const FilterPaletteID GlassPaletteIds[COLOUR_COUNT];
|
2021-10-06 16:28:37 +02:00
|
|
|
extern thread_local uint8_t gPeepPalette[256];
|
|
|
|
extern thread_local uint8_t gOtherPalette[256];
|
2022-07-30 23:21:34 +02:00
|
|
|
extern uint8_t gTextPalette[];
|
2023-01-19 09:16:44 +01:00
|
|
|
extern const TranslucentWindowPalette TranslucentWindowPalettes[COLOUR_COUNT];
|
2014-10-06 18:36:58 +02:00
|
|
|
|
2021-11-30 01:13:45 +01:00
|
|
|
extern ImageId gPickupPeepImage;
|
2018-06-20 17:28:51 +02:00
|
|
|
extern int32_t gPickupPeepX;
|
|
|
|
extern int32_t gPickupPeepY;
|
2016-04-24 11:28:08 +02:00
|
|
|
|
2017-10-01 02:18:31 +02:00
|
|
|
extern bool gTinyFontAntiAliased;
|
2015-05-28 01:16:51 +02:00
|
|
|
|
2023-04-03 23:29:06 +02:00
|
|
|
bool ClipDrawPixelInfo(DrawPixelInfo& dst, DrawPixelInfo& src, const ScreenCoordsXY& coords, int32_t width, int32_t height);
|
2023-01-16 14:50:43 +01:00
|
|
|
void GfxSetDirtyBlocks(const ScreenRect& rect);
|
|
|
|
void GfxInvalidateScreen();
|
2014-04-04 20:59:32 +02:00
|
|
|
|
2014-10-06 18:36:58 +02:00
|
|
|
// palette
|
2023-01-16 14:50:43 +01:00
|
|
|
void GfxTransposePalette(int32_t pal, uint8_t product);
|
|
|
|
void LoadPalette();
|
2014-10-06 18:36:58 +02:00
|
|
|
|
|
|
|
// other
|
2024-03-10 16:00:08 +01:00
|
|
|
void GfxClear(DrawPixelInfo& dpi, uint8_t paletteIndex);
|
2023-04-03 23:29:06 +02:00
|
|
|
void GfxFilterPixel(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, FilterPaletteID palette);
|
2023-01-16 14:50:43 +01:00
|
|
|
void GfxInvalidatePickedUpPeep();
|
2023-04-03 23:29:06 +02:00
|
|
|
void GfxDrawPickedUpPeep(DrawPixelInfo& dpi);
|
2014-10-06 18:36:58 +02:00
|
|
|
|
|
|
|
// line
|
2023-04-03 23:16:34 +02:00
|
|
|
void GfxDrawLine(DrawPixelInfo& dpi, const ScreenLine& line, int32_t colour);
|
2023-04-03 22:55:11 +02:00
|
|
|
void GfxDrawLineSoftware(DrawPixelInfo& dpi, const ScreenLine& line, int32_t colour);
|
2023-01-16 14:50:43 +01:00
|
|
|
void GfxDrawDashedLine(
|
2023-04-03 23:16:34 +02:00
|
|
|
DrawPixelInfo& dpi, const ScreenLine& screenLine, const int32_t dashedLineSegmentLength, const int32_t color);
|
2014-10-06 18:36:58 +02:00
|
|
|
|
|
|
|
// rect
|
2023-04-03 23:16:34 +02:00
|
|
|
void GfxFillRect(DrawPixelInfo& dpi, const ScreenRect& rect, int32_t colour);
|
|
|
|
void GfxFillRectInset(DrawPixelInfo& dpi, const ScreenRect& rect, int32_t colour, uint8_t flags);
|
|
|
|
void GfxFilterRect(DrawPixelInfo& dpi, const ScreenRect& rect, FilterPaletteID palette);
|
2014-10-06 18:36:58 +02:00
|
|
|
|
|
|
|
// sprite
|
2023-01-16 19:52:17 +01:00
|
|
|
bool GfxLoadG1(const OpenRCT2::IPlatformEnvironment& env);
|
|
|
|
bool GfxLoadG2();
|
|
|
|
bool GfxLoadCsg();
|
|
|
|
void GfxUnloadG1();
|
|
|
|
void GfxUnloadG2();
|
|
|
|
void GfxUnloadCsg();
|
2023-01-19 09:16:44 +01:00
|
|
|
const G1Element* GfxGetG1Element(const ImageId imageId);
|
|
|
|
const G1Element* GfxGetG1Element(ImageIndex image_id);
|
|
|
|
void GfxSetG1Element(ImageIndex imageId, const G1Element* g1);
|
|
|
|
std::optional<Gx> GfxLoadGx(const std::vector<uint8_t>& buffer);
|
2023-01-16 19:52:17 +01:00
|
|
|
bool IsCsgLoaded();
|
2023-01-19 09:16:44 +01:00
|
|
|
void FASTCALL GfxSpriteToBuffer(DrawPixelInfo& dpi, const DrawSpriteArgs& args);
|
|
|
|
void FASTCALL GfxBmpSpriteToBuffer(DrawPixelInfo& dpi, const DrawSpriteArgs& args);
|
|
|
|
void FASTCALL GfxRleSpriteToBuffer(DrawPixelInfo& dpi, const DrawSpriteArgs& args);
|
2023-04-03 20:38:28 +02:00
|
|
|
void FASTCALL GfxDrawSprite(DrawPixelInfo& dpi, const ImageId image_id, const ScreenCoordsXY& coords);
|
2024-03-10 16:00:08 +01:00
|
|
|
void FASTCALL GfxDrawGlyph(DrawPixelInfo& dpi, const ImageId image, const ScreenCoordsXY& coords, const PaletteMap& paletteMap);
|
|
|
|
void FASTCALL GfxDrawSpriteSolid(DrawPixelInfo& dpi, const ImageId image, const ScreenCoordsXY& coords, uint8_t colour);
|
2023-01-16 19:52:17 +01:00
|
|
|
void FASTCALL GfxDrawSpriteRawMasked(
|
2024-03-10 16:00:08 +01:00
|
|
|
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, const ImageId maskImage, const ImageId colourImage);
|
2023-04-03 22:55:11 +02:00
|
|
|
void FASTCALL GfxDrawSpriteSoftware(DrawPixelInfo& dpi, const ImageId imageId, const ScreenCoordsXY& spriteCoords);
|
2023-01-16 19:52:17 +01:00
|
|
|
void FASTCALL GfxDrawSpritePaletteSetSoftware(
|
2023-04-03 22:55:11 +02:00
|
|
|
DrawPixelInfo& dpi, const ImageId imageId, const ScreenCoordsXY& coords, const PaletteMap& paletteMap);
|
2023-01-16 19:52:17 +01:00
|
|
|
void FASTCALL GfxDrawSpriteRawMaskedSoftware(
|
2023-04-03 22:55:11 +02:00
|
|
|
DrawPixelInfo& dpi, const ScreenCoordsXY& scrCoords, const ImageId maskImage, const ImageId colourImage);
|
2016-06-04 12:31:51 +02:00
|
|
|
|
2014-10-06 18:36:58 +02:00
|
|
|
// string
|
2023-02-24 22:05:07 +01:00
|
|
|
void GfxDrawString(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, const_utf8string buffer, TextPaint textPaint = {});
|
2023-01-19 09:16:44 +01:00
|
|
|
|
2023-02-24 22:05:07 +01:00
|
|
|
void GfxDrawStringLeftCentred(DrawPixelInfo& dpi, StringId format, void* args, colour_t colour, const ScreenCoordsXY& coords);
|
2023-02-13 22:02:40 +01:00
|
|
|
void DrawStringCentredRaw(
|
2023-02-24 22:05:07 +01:00
|
|
|
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t numLines, const utf8* text, FontStyle fontStyle);
|
2021-03-02 22:48:33 +01:00
|
|
|
void DrawNewsTicker(
|
2023-02-24 22:05:07 +01:00
|
|
|
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t width, colour_t colour, StringId format, u8string_view args,
|
2018-06-22 22:59:03 +02:00
|
|
|
int32_t ticks);
|
2023-01-16 19:52:17 +01:00
|
|
|
void GfxDrawStringWithYOffsets(
|
2023-02-24 22:05:07 +01:00
|
|
|
DrawPixelInfo& dpi, const utf8* text, int32_t colour, const ScreenCoordsXY& coords, const int8_t* yOffsets,
|
2022-10-12 22:40:59 +02:00
|
|
|
bool forceSpriteFont, FontStyle fontStyle);
|
|
|
|
|
2023-02-13 22:02:40 +01:00
|
|
|
int32_t GfxWrapString(u8string_view text, int32_t width, FontStyle fontStyle, u8string* outWrappedText, int32_t* outNumLines);
|
2023-01-16 19:52:17 +01:00
|
|
|
int32_t GfxGetStringWidth(std::string_view text, FontStyle fontStyle);
|
|
|
|
int32_t GfxGetStringWidthNewLined(std::string_view text, FontStyle fontStyle);
|
|
|
|
int32_t GfxGetStringWidthNoFormatting(std::string_view text, FontStyle fontStyle);
|
|
|
|
int32_t StringGetHeightRaw(std::string_view text, FontStyle fontStyle);
|
|
|
|
int32_t GfxClipString(char* buffer, int32_t width, FontStyle fontStyle);
|
2023-08-10 13:39:38 +02:00
|
|
|
u8string ShortenPath(const u8string& path, int32_t availableWidth, FontStyle fontStyle);
|
2023-01-16 23:31:34 +01:00
|
|
|
void TTFDrawString(
|
2023-02-24 22:05:07 +01:00
|
|
|
DrawPixelInfo& dpi, const_utf8string text, int32_t colour, const ScreenCoordsXY& coords, bool noFormatting,
|
2022-10-12 22:40:59 +02:00
|
|
|
FontStyle fontStyle, TextDarkness darkness);
|
2015-07-26 01:55:17 +02:00
|
|
|
|
2015-07-29 03:03:34 +02:00
|
|
|
// scrolling text
|
2023-01-16 19:52:17 +01:00
|
|
|
void ScrollingTextInitialiseBitmaps();
|
|
|
|
void ScrollingTextInvalidate();
|
2020-07-31 12:31:26 +02:00
|
|
|
|
|
|
|
class Formatter;
|
|
|
|
|
2023-01-16 19:52:17 +01:00
|
|
|
ImageId ScrollingTextSetup(
|
2022-10-14 20:26:36 +02:00
|
|
|
struct PaintSession& session, StringId stringId, Formatter& ft, uint16_t scroll, uint16_t scrollingMode, colour_t colour);
|
2015-07-29 03:03:34 +02:00
|
|
|
|
2023-01-19 09:16:44 +01:00
|
|
|
size_t G1CalculateDataSize(const G1Element* g1);
|
2018-06-22 22:59:03 +02:00
|
|
|
|
2023-01-16 14:50:43 +01:00
|
|
|
void MaskScalar(
|
2018-07-21 13:51:54 +02:00
|
|
|
int32_t width, int32_t height, const uint8_t* RESTRICT maskSrc, const uint8_t* RESTRICT colourSrc, uint8_t* RESTRICT dst,
|
|
|
|
int32_t maskWrap, int32_t colourWrap, int32_t dstWrap);
|
2023-01-16 14:50:43 +01:00
|
|
|
void MaskSse4_1(
|
2018-07-21 13:51:54 +02:00
|
|
|
int32_t width, int32_t height, const uint8_t* RESTRICT maskSrc, const uint8_t* RESTRICT colourSrc, uint8_t* RESTRICT dst,
|
|
|
|
int32_t maskWrap, int32_t colourWrap, int32_t dstWrap);
|
2023-01-16 14:50:43 +01:00
|
|
|
void MaskAvx2(
|
2018-07-21 13:51:54 +02:00
|
|
|
int32_t width, int32_t height, const uint8_t* RESTRICT maskSrc, const uint8_t* RESTRICT colourSrc, uint8_t* RESTRICT dst,
|
|
|
|
int32_t maskWrap, int32_t colourWrap, int32_t dstWrap);
|
2017-12-19 22:15:48 +01:00
|
|
|
|
2023-06-27 22:02:31 +02:00
|
|
|
void MaskFn(
|
2018-07-21 13:51:54 +02:00
|
|
|
int32_t width, int32_t height, const uint8_t* RESTRICT maskSrc, const uint8_t* RESTRICT colourSrc, uint8_t* RESTRICT dst,
|
|
|
|
int32_t maskWrap, int32_t colourWrap, int32_t dstWrap);
|
2017-12-19 22:15:48 +01:00
|
|
|
|
2020-05-28 20:52:20 +02:00
|
|
|
std::optional<uint32_t> GetPaletteG1Index(colour_t paletteId);
|
|
|
|
std::optional<PaletteMap> GetPaletteMapForColour(colour_t paletteId);
|
2022-01-10 13:10:56 +01:00
|
|
|
void UpdatePalette(const uint8_t* colours, int32_t start_index, int32_t num_colours);
|
2020-05-28 20:52:20 +02:00
|
|
|
|
2022-02-18 21:57:00 +01:00
|
|
|
void RefreshVideo(bool recreateWindow);
|
|
|
|
void ToggleWindowedMode();
|
|
|
|
|
2016-06-03 00:53:38 +02:00
|
|
|
#include "NewDrawing.h"
|