48std::atomic<bool> _exit_game;
75static const uint8_t *_colour_remap_ptr;
78static const uint DIRTY_BLOCK_HEIGHT = 8;
79static const uint DIRTY_BLOCK_WIDTH = 64;
81static size_t _dirty_blocks_per_row = 0;
82static size_t _dirty_blocks_per_column = 0;
83static std::vector<uint8_t> _dirty_blocks;
84extern uint _dirty_block_colour;
86void GfxScroll(
int left,
int top,
int width,
int height,
int xo,
int yo)
90 if (xo == 0 && yo == 0)
return;
92 if (_cursor.visible) UndrawMouseCursor();
96 blitter->
ScrollBuffer(_screen.dst_ptr, left, top, width, height, xo, yo);
116void GfxFillRect(
int left,
int top,
int right,
int bottom,
const std::variant<PixelColour, PaletteID> &colour,
FillRectMode mode)
121 const int otop = top;
122 const int oleft = left;
125 if (left > right || top > bottom)
return;
126 if (right < dpi->left || left >= dpi->left + dpi->width)
return;
127 if (bottom < dpi->top || top >= dpi->top + dpi->height)
return;
129 if ( (left -= dpi->left) < 0) left = 0;
130 right = right - dpi->left + 1;
131 if (right > dpi->width) right = dpi->width;
135 if ( (top -= dpi->top) < 0) top = 0;
136 bottom = bottom - dpi->top + 1;
137 if (bottom > dpi->height) bottom = dpi->height;
141 dst = blitter->
MoveTo(dpi->dst_ptr, left, top);
145 blitter->
DrawRect(dst, right, bottom, std::get<PixelColour>(colour));
153 uint8_t bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
156 for (
int i = (bo ^= 1); i < right; i += 2) blitter->
SetPixel(dst, i, 0, pc);
157 dst = blitter->
MoveTo(dst, 0, 1);
158 }
while (--bottom > 0);
164typedef std::pair<Point, Point> LineSegment;
176 std::vector<LineSegment> segments;
177 if (shape.size() < 3)
return segments;
178 segments.reserve(shape.size());
181 Point prev = shape.back();
184 for (
Point pt : shape) {
190 segments.emplace_back(pt, prev);
191 }
else if (prev.
y < pt.y) {
192 segments.emplace_back(prev, pt);
222 segments.erase(std::remove_if(segments.begin(), segments.end(), [dpi](
const LineSegment &s) { return s.second.y <= 0 || s.first.y >= dpi->height; }), segments.end());
225 if (segments.empty())
return;
228 std::sort(segments.begin(), segments.end(), [](
const LineSegment &a,
const LineSegment &b) { return a.first.y < b.first.y; });
231 std::vector<LineSegment> active;
234 std::vector<int> intersections;
237 intersections.reserve(4);
240 int y = segments.front().first.y;
241 std::vector<LineSegment>::iterator nextseg = segments.begin();
242 while (!active.empty() || nextseg != segments.end()) {
244 active.erase(std::remove_if(active.begin(), active.end(), [y](
const LineSegment &s) { return s.second.y == y; }), active.end());
247 while (nextseg != segments.end() && nextseg->first.y == y) {
248 active.push_back(*nextseg);
257 if (y >= dpi->height)
return;
260 intersections.clear();
261 for (
const LineSegment &s : active) {
262 const int sdx = s.second.x - s.first.x;
263 const int sdy = s.second.y - s.first.y;
264 const int ldy = y - s.first.y;
265 const int x = s.first.x + sdx * ldy / sdy;
266 intersections.push_back(x);
270 std::sort(intersections.begin(), intersections.end());
271 for (
size_t i = 1; i < intersections.size(); i += 2) {
273 const int x1 = std::max(0, intersections[i - 1]);
274 const int x2 = std::min(intersections[i], dpi->width);
275 if (x2 < 0)
continue;
276 if (x1 >= dpi->width)
continue;
279 void *dst = blitter->
MoveTo(dpi->dst_ptr, x1, y);
282 blitter->
DrawRect(dst, x2 - x1, 1, std::get<PixelColour>(colour));
291 for (
int x = (x1 + y) & 1; x < x2 - x1; x += 2) {
318static inline void GfxDoDrawLine(
void *video,
int x,
int y,
int x2,
int y2,
int screen_width,
int screen_height,
PixelColour colour,
int width,
int dash = 0)
324 if (y2 == y || x2 == x) {
326 blitter->
DrawLine(video, x, y, x2, y2, screen_width, screen_height, colour, width, dash);
330 int grade_y = y2 - y;
331 int grade_x = x2 - x;
334 int extra = (int)
CeilDiv(3 * width, 4);
335 Rect clip = { -extra, -extra, screen_width - 1 + extra, screen_height - 1 + extra };
339 while (INT_MAX /
abs(grade_y) < std::max(
abs(clip.left - x),
abs(clip.right - x))) {
346 if (grade_x == 0) grade_x = 1;
352 int left_isec_y = y + (clip.left - x) * grade_y / grade_x;
353 int right_isec_y = y + (clip.right - x) * grade_y / grade_x;
354 if ((left_isec_y > clip.bottom + margin && right_isec_y > clip.bottom + margin) ||
355 (left_isec_y < clip.top - margin && right_isec_y < clip.top - margin)) {
365 blitter->
DrawLine(video, x, y, x2, y2, screen_width, screen_height, colour, width, dash);
387 if (x + width / 2 < 0 && x2 + width / 2 < 0 )
return false;
388 if (y + width / 2 < 0 && y2 + width / 2 < 0 )
return false;
389 if (x - width / 2 > dpi->width && x2 - width / 2 > dpi->width )
return false;
390 if (y - width / 2 > dpi->height && y2 - width / 2 > dpi->height)
return false;
394void GfxDrawLine(
int x,
int y,
int x2,
int y2,
PixelColour colour,
int width,
int dash)
398 GfxDoDrawLine(dpi->dst_ptr, x, y, x2, y2, dpi->width, dpi->height, colour, width, dash);
402void GfxDrawLineUnscaled(
int x,
int y,
int x2,
int y2,
PixelColour colour)
426void DrawBox(
int x,
int y,
int dx1,
int dy1,
int dx2,
int dy2,
int dx3,
int dy3)
445 GfxDrawLineUnscaled(x, y, x + dx1, y + dy1, colour);
446 GfxDrawLineUnscaled(x, y, x + dx2, y + dy2, colour);
447 GfxDrawLineUnscaled(x, y, x + dx3, y + dy3, colour);
449 GfxDrawLineUnscaled(x + dx1, y + dy1, x + dx1 + dx2, y + dy1 + dy2, colour);
450 GfxDrawLineUnscaled(x + dx1, y + dy1, x + dx1 + dx3, y + dy1 + dy3, colour);
451 GfxDrawLineUnscaled(x + dx2, y + dy2, x + dx2 + dx1, y + dy2 + dy1, colour);
452 GfxDrawLineUnscaled(x + dx2, y + dy2, x + dx2 + dx3, y + dy2 + dy3, colour);
453 GfxDrawLineUnscaled(x + dx3, y + dy3, x + dx3 + dx1, y + dy3 + dy1, colour);
454 GfxDrawLineUnscaled(x + dx3, y + dy3, x + dx3 + dx2, y + dy3 + dy2, colour);
466 GfxDrawLine(r.left, r.top, r.right, r.top, colour, width, dash);
467 GfxDrawLine(r.left, r.top, r.left, r.bottom, colour, width, dash);
468 GfxDrawLine(r.right, r.top, r.right, r.bottom, colour, width, dash);
469 GfxDrawLine(r.left, r.bottom, r.right, r.bottom, colour, width, dash);
525 int max_w = right - left + 1;
531 truncation &= max_w < w;
532 int truncation_width = 0;
534 std::optional<Layouter> truncation_layout;
543 truncation_width = truncation_layout->GetBounds().width;
549 min_x += truncation_width;
550 offset_x = w - max_w;
552 max_x -= truncation_width;
569 right = left + w - 1;
575 right = left + w - 1;
579 left = right + 1 - w;
590 int dpi_left = dpi->left;
591 int dpi_right = dpi->left + dpi->width - 1;
594 for (
size_t run_index = 0; run_index < line.
CountRuns(); run_index++) {
605 last_colour = colour;
610 GlyphID glyph = glyphs[i];
613 if (glyph == 0xFFFF)
continue;
615 int begin_x = positions[i].left + left;
616 int end_x = positions[i].right + left;
617 int top = positions[i].top + y;
620 if (truncation && (begin_x < min_x || end_x > max_x))
continue;
624 if (begin_x + sprite->
x_offs > dpi_right || begin_x + sprite->
x_offs + sprite->
width < dpi_left)
continue;
626 if (do_shadow && (glyph & SPRITE_GLYPH) != 0)
continue;
628 GfxMainBlitter(sprite, begin_x + (do_shadow ? shadow_offset : 0), top + (do_shadow ? shadow_offset : 0),
BlitterMode::ColourRemap);
635 for (
bool do_shadow : {
true,
false}) {
636 ExtendedTextColour colour = draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation, default_colour);
640 draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX,
false, colour);
674 int extra = max_height / 2;
676 if (_cur_dpi->top + _cur_dpi->height + extra < top || _cur_dpi->top > top + max_height + extra ||
677 _cur_dpi->left + _cur_dpi->width + extra < left || _cur_dpi->left > right + extra) {
681 Layouter layout(str, INT32_MAX, fontsize);
682 if (layout.empty())
return 0;
684 return DrawLayoutLine(*layout.front(), top, left, right, align, underline,
true, colour);
719 Layouter layout(str, maxw, fontsize);
743 return (uint)layout.size();
789 int maxw = right - left + 1;
790 int maxh = bottom - top + 1;
794 if (maxh <= 0)
return top;
796 Layouter layout(str, maxw, fontsize);
797 int total_height = layout.
GetBounds().height;
805 y =
RoundDivSU(bottom + top - total_height, 2);
809 y = bottom - total_height;
812 default: NOT_REACHED();
816 int first_line = bottom;
818 for (
const auto &line : layout) {
820 int line_height = line->GetLeading();
821 if (y >= top && y + line_height - 1 <= bottom) {
822 last_line = y + line_height;
823 if (first_line > y) first_line = y;
825 DrawLayoutLine(*line, y, left, right, align, underline,
false, colour);
878 int extra = max_height / 2;
880 if (_cur_dpi->top + _cur_dpi->height + extra < top || _cur_dpi->top > bottom + extra ||
881 _cur_dpi->left + _cur_dpi->width + extra < left || _cur_dpi->left > right + extra) {
901 Layouter layout(str, INT32_MAX, start_fontsize);
926 for (
auto str : list) {
941 for (
auto str : list) {
975 if (offset !=
nullptr) {
1016 }
else if (pal != PAL_NONE) {
1044 }
else if (pal != PAL_NONE) {
1069template <
int ZOOM_BASE,
bool SCALED_XY>
1072 const DrawPixelInfo *dpi = (dst !=
nullptr) ? dst : _cur_dpi;
1085 if (sub ==
nullptr) {
1093 int clip_left = std::max(0, -sprite->
x_offs + sub->left * ZOOM_BASE );
1094 int clip_top = std::max(0, -sprite->
y_offs + sub->top * ZOOM_BASE );
1095 int clip_right = std::max(0, sprite->
width - (-sprite->
x_offs + (sub->right + 1) * ZOOM_BASE));
1096 int clip_bottom = std::max(0, sprite->
height - (-sprite->
y_offs + (sub->bottom + 1) * ZOOM_BASE));
1098 if (clip_left + clip_right >= sprite->
width)
return;
1099 if (clip_top + clip_bottom >= sprite->
height)
return;
1117 bp.
dst = dpi->dst_ptr;
1118 bp.
pitch = dpi->pitch;
1119 bp.
remap = _colour_remap_ptr;
1121 assert(sprite->
width > 0);
1122 assert(sprite->
height > 0);
1124 if (bp.
width <= 0)
return;
1125 if (bp.
height <= 0)
return;
1127 y -= SCALED_XY ?
ScaleByZoom(dpi->top, zoom) : dpi->top;
1131 bp.
height -= -y_unscaled;
1132 if (bp.
height <= 0)
return;
1136 bp.
top = y_unscaled;
1143 if (bp.
height <= 0)
return;
1146 x -= SCALED_XY ?
ScaleByZoom(dpi->left, zoom) : dpi->left;
1150 bp.
width -= -x_unscaled;
1151 if (bp.
width <= 0)
return;
1155 bp.
left = x_unscaled;
1162 if (bp.
width <= 0)
return;
1176 if (topleft <= clicked && clicked <= bottomright) {
1177 uint offset = (((size_t)clicked - (size_t)topleft) / (blitter->
GetScreenDepth() / 8)) % bp.
pitch;
1178 if (offset < (uint)bp.
width) {
1197 if (zoom < _settings_client.gui.zoom_min || zoom >
_settings_client.gui.zoom_max)
return nullptr;
1206 size_t dim_size =
static_cast<size_t>(dim.width) * dim.height;
1207 std::unique_ptr<uint32_t[]> result = std::make_unique<uint32_t[]>(dim_size);
1212 dpi.dst_ptr = result.get();
1213 dpi.pitch = dim.width;
1216 dpi.width = dim.width;
1217 dpi.height = dim.height;
1220 dim_size =
static_cast<size_t>(dim.width) * dim.height;
1223 std::unique_ptr<uint8_t[]> pal_buffer{};
1225 pal_buffer = std::make_unique<uint8_t[]>(dim_size);
1226 dpi.dst_ptr = pal_buffer.get();
1236 uint32_t *dst = result.get();
1237 const uint8_t *src = pal_buffer.get();
1238 for (
size_t i = 0; i < dim_size; ++i) {
1265 for (uint i = 0; i != 224; i++) {
1293 for (
char c =
'0'; c <=
'9'; c++) {
1311 for (
char c =
'9'; c >=
'0'; c--) {
1313 if (w <= width)
continue;
1317 if (c !=
'0') front = c -
'0';
1319 return {front, next};
1322void ScreenSizeChanged()
1324 _dirty_blocks_per_row =
CeilDiv(_screen.width, DIRTY_BLOCK_WIDTH);
1325 _dirty_blocks_per_column =
CeilDiv(_screen.height, DIRTY_BLOCK_HEIGHT);
1326 _dirty_blocks.resize(_dirty_blocks_per_column * _dirty_blocks_per_row);
1333 _cursor.visible =
false;
1340void UndrawMouseCursor()
1346 if (_screen.dst_ptr ==
nullptr)
return;
1348 if (_cursor.visible) {
1350 _cursor.visible =
false;
1351 blitter->
CopyFromBuffer(blitter->
MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup.GetBuffer(), _cursor.draw_size.x, _cursor.draw_size.y);
1356void DrawMouseCursor()
1362 if (_screen.dst_ptr ==
nullptr)
return;
1367 if (!_cursor.in_window)
return;
1370 if (_cursor.visible) {
1371 if (!_cursor.dirty)
return;
1372 UndrawMouseCursor();
1376 int left = _cursor.pos.x + _cursor.total_offs.x;
1377 int width = _cursor.total_size.x;
1382 if (left + width > _screen.width) {
1383 width = _screen.width - left;
1385 if (width <= 0)
return;
1387 int top = _cursor.pos.y + _cursor.total_offs.y;
1388 int height = _cursor.total_size.y;
1393 if (top + height > _screen.height) {
1394 height = _screen.height - top;
1396 if (height <= 0)
return;
1398 _cursor.draw_pos.x = left;
1399 _cursor.draw_pos.y = top;
1400 _cursor.draw_size.x = width;
1401 _cursor.draw_size.y = height;
1403 uint8_t *buffer = _cursor_backup.Allocate(blitter->
BufferSize(_cursor.draw_size.x, _cursor.draw_size.y));
1406 blitter->
CopyToBuffer(blitter->
MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), buffer, _cursor.draw_size.x, _cursor.draw_size.y);
1409 _cur_dpi = &_screen;
1410 for (
const auto &cs : _cursor.sprites) {
1411 DrawSprite(cs.image.sprite, cs.image.pal, _cursor.pos.x + cs.pos.x, _cursor.pos.y + cs.pos.y);
1416 _cursor.visible =
true;
1417 _cursor.dirty =
false;
1432 assert(right <= _screen.width && bottom <= _screen.height);
1433 if (_cursor.visible) {
1434 if (right > _cursor.draw_pos.x &&
1435 left < _cursor.draw_pos.x + _cursor.draw_size.x &&
1436 bottom > _cursor.draw_pos.y &&
1437 top < _cursor.draw_pos.y + _cursor.draw_size.y) {
1438 UndrawMouseCursor();
1458 auto is_dirty = [](
auto block) ->
bool {
return block != 0; };
1459 auto block = _dirty_blocks.begin();
1461 for (
size_t x = 0; x < _dirty_blocks_per_row; ++x) {
1462 auto last_of_column = block + _dirty_blocks_per_column;
1463 for (
size_t y = 0; y < _dirty_blocks_per_column; ++y, ++block) {
1464 if (!is_dirty(*block))
continue;
1467 size_t height = std::find_if_not(block + 1, last_of_column, is_dirty) - block;
1471 std::fill_n(block, height, 0);
1474 auto block_right = block;
1475 for (
size_t x_right = x + 1; x_right < _dirty_blocks_per_row; ++x_right, ++width) {
1476 block_right += _dirty_blocks_per_column;
1477 auto last_right = block_right + height;
1479 if (std::find_if_not(block_right, last_right, is_dirty) != last_right)
break;
1482 std::fill_n(block_right, height, 0);
1485 int left =
static_cast<int>(x * DIRTY_BLOCK_WIDTH);
1486 int top =
static_cast<int>(y * DIRTY_BLOCK_HEIGHT);
1487 int right = left +
static_cast<int>(width * DIRTY_BLOCK_WIDTH);
1488 int bottom = top +
static_cast<int>(height * DIRTY_BLOCK_HEIGHT);
1495 if (left < right && top < bottom) {
1501 ++_dirty_block_colour;
1522 if (left < 0) left = 0;
1523 if (top < 0) top = 0;
1524 if (right > _screen.width) right = _screen.width;
1525 if (bottom > _screen.height) bottom = _screen.height;
1527 if (left >= right || top >= bottom)
return;
1534 left /= DIRTY_BLOCK_WIDTH;
1535 top /= DIRTY_BLOCK_HEIGHT;
1536 right =
CeilDiv(right, DIRTY_BLOCK_WIDTH);
1537 int height =
CeilDiv(bottom, DIRTY_BLOCK_HEIGHT) - top;
1539 assert(left < right && height > 0);
1541 for (; left < right; ++left) {
1542 size_t offset = _dirty_blocks_per_column * left + top;
1543 std::fill_n(_dirty_blocks.begin() + offset, height, 0xFF);
1582 if ((left -= o->left) < 0) {
1584 if (width <= 0)
return false;
1591 if (width > o->width - left) {
1592 width = o->width - left;
1593 if (width <= 0)
return false;
1597 if ((top -= o->top) < 0) {
1599 if (height <= 0)
return false;
1606 n->dst_ptr = blitter->
MoveTo(o->dst_ptr, left, top);
1607 n->pitch = o->pitch;
1609 if (height > o->height - top) {
1610 height = o->height - top;
1611 if (height <= 0)
return false;
1628 for (
const auto &cs : _cursor.sprites) {
1638 _cursor.total_offs = offs;
1639 _cursor.total_size = size;
1643 int right = std::max(_cursor.total_offs.x + _cursor.total_size.x, offs.
x + size.
x);
1644 int bottom = std::max(_cursor.total_offs.y + _cursor.total_size.y, offs.
y + size.
y);
1645 if (offs.
x < _cursor.total_offs.x) _cursor.total_offs.x = offs.
x;
1646 if (offs.
y < _cursor.total_offs.y) _cursor.total_offs.y = offs.
y;
1647 _cursor.total_size.x = right - _cursor.total_offs.x;
1648 _cursor.total_size.y = bottom - _cursor.total_offs.y;
1652 _cursor.dirty =
true;
1662 if (_cursor.sprites.size() == 1 && _cursor.sprites[0].image.sprite == cursor && _cursor.sprites[0].image.pal == pal)
return;
1664 _cursor.sprites.clear();
1665 _cursor.sprites.emplace_back(cursor, pal, 0, 0);
1670static void SwitchAnimatedCursor()
1672 if (_cursor.animate_cur == std::end(_cursor.animate_list)) {
1673 _cursor.animate_cur = std::begin(_cursor.animate_list);
1676 assert(!_cursor.sprites.empty());
1677 SetCursorSprite(_cursor.animate_cur->sprite, _cursor.sprites[0].image.pal);
1679 _cursor.animate_timeout = _cursor.animate_cur->display_time;
1680 ++_cursor.animate_cur;
1685 if (_cursor.animate_timeout != 0 && --_cursor.animate_timeout == 0) {
1686 SwitchAnimatedCursor();
1696 assert(!_cursor.sprites.empty());
1713 _cursor.animate_timeout = 0;
1725 assert(!_cursor.sprites.empty());
1726 _cursor.animate_list = table;
1727 _cursor.animate_cur = std::end(table);
1728 _cursor.sprites[0].image.pal = PAL_NONE;
1729 SwitchAnimatedCursor();
1756 this->
delta.x = delta_x;
1757 this->
delta.y = delta_y;
1772 return this->
delta.x != 0 || this->
delta.y != 0;
1773 }
else if (this->
pos.x != x || this->pos.y != y) {
1782bool ChangeResInGame(
int width,
int height)
1787bool ToggleFullScreen(
bool fs)
1791 Debug(driver, 0,
"Could not find a suitable fullscreen resolution");
1796void SortResolutions()
1813 float xs = _screen.width / 640.f;
1814 float ys = _screen.height / 480.f;
1815 int scale = std::min(xs, ys) * 100;
1817 _gui_scale =
Clamp((scale / 25) * 25, MIN_INTERFACE_SCALE, MAX_INTERFACE_SCALE);
1862 auto zoom_shift = old_gui_zoom -
_gui_zoom;
1865 w->left = (w->left *
_gui_scale) / old_scale;
1868 if (w->viewport !=
nullptr) {
1876void ChangeGameSpeed(
bool enable_fast_forward)
1878 if (enable_fast_forward) {
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
This file defines all the the animated cursors.
static constexpr std::span< const AnimCursor > _animcursors[]
This is an array of pointers to all the animated cursor definitions we have above.
Class for backupping variables and making sure they are restored later.
BlitterMode
The modes of blitting we can do.
@ Transparent
Perform transparency darkening remapping.
@ CrashRemap
Perform a crash remapping.
@ BlackRemap
Perform remapping to a completely blackened sprite.
@ Normal
Perform the simple blitting.
@ TransparentRemap
Perform transparency colour remapping.
@ ColourRemap
Perform a colour remapping.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
How all blitters should look like.
virtual void * MoveTo(void *video, int x, int y)=0
Move the destination pointer the requested amount x and y, keeping in mind any pitch and bpp of the r...
virtual uint8_t GetScreenDepth()=0
Get the screen depth this blitter works for.
virtual size_t BufferSize(uint width, uint height)=0
Calculate how much memory there is needed for an image of this size in the video-buffer.
virtual void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash=0)=0
Draw a line with a given colour.
virtual void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)=0
Draw a colourtable to the screen.
virtual void SetPixel(void *video, int x, int y, PixelColour colour)=0
Draw a pixel with a given colour on the video-buffer.
virtual void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)=0
Draw an image to the screen, given an amount of params defined above.
virtual void CopyToBuffer(const void *video, void *dst, int width, int height)=0
Copy from the screen to a buffer.
virtual void DrawRect(void *video, int width, int height, PixelColour colour)=0
Make a single horizontal line in a single colour on the video-buffer.
virtual void CopyFromBuffer(void *video, const void *src, int width, int height)=0
Copy from a buffer to the screen.
virtual void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)=0
Scroll the videobuffer some 'x' and 'y' value.
Font cache for basic fonts.
virtual const Sprite * GetGlyph(GlyphID key)=0
Get the glyph (sprite) of the given key.
static void ClearFontCaches(FontSizes fontsizes)
Clear cached information for the specified font caches.
FontSize GetSize() const
Get the FontSize of the font.
virtual bool GetDrawGlyphShadow()=0
Do we need to draw a glyph shadow?
Container with information about a font.
ExtendedTextColour colour
The colour this font has to be.
FontCache * fc
The font we are using.
The layouter performs all the layout work.
Dimension GetBounds()
Get the boundaries of this paragraph.
A single line worth of VisualRuns.
virtual int GetLeading() const =0
Get the font leading, or distance between the baselines of consecutive lines.
virtual const VisualRun & GetVisualRun(size_t run) const =0
Get a reference to the given run.
virtual int GetWidth() const =0
Get the width of this line.
virtual size_t CountRuns() const =0
Get the number of runs in this line.
Visual run contains data about the bit of text with the same font.
virtual std::span< const GlyphID > GetGlyphs() const =0
Get the glyphs to draw.
virtual std::span< const Position > GetPositions() const =0
Get the positions for each of the glyphs.
virtual const Font * GetFont() const =0
Get the font.
virtual size_t GetGlyphCount() const =0
Get the number of glyphs.
A reusable buffer that can be used for places that temporary allocate a bit of memory and do that ver...
virtual bool ToggleFullscreen(bool fullscreen)=0
Change the full screen setting.
virtual void ClearSystemSprites()
Clear all cached sprites.
virtual void MakeDirty(int left, int top, int width, int height)=0
Mark a particular area dirty.
virtual bool ChangeResolution(int w, int h)=0
Change the resolution of the window.
static VideoDriver * GetInstance()
Get the currently active instance of the video driver.
Control codes that are embedded in the translation strings.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
std::vector< Dimension > _resolutions
List of resolutions.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
Factory to 'query' all available blitters.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
const Sprite * GetGlyph(FontSize size, char32_t key)
Get the Sprite for a glyph.
uint GetGlyphWidth(FontSize size, char32_t key)
Get the width of a glyph.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
int CentreBounds(int min, int max, int size)
Determine where to position a centred object.
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
void SetMouseCursor(CursorID sprite, PaletteID pal)
Assign a single non-animated sprite to the cursor.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
void UpdateCursorSize()
Update cursor dimension.
static void SetCursorSprite(CursorID cursor, PaletteID pal)
Switch cursor to different sprite.
std::pair< uint8_t, uint8_t > GetBroadestDigit(FontSize size)
Determine the broadest digits for guessing the maximum width of a n-digit number.
bool _shift_pressed
Is Shift pressed?
static void GfxBlitter(const Sprite *const sprite, int x, int y, BlitterMode mode, const SubSprite *const sub, SpriteID sprite_id, ZoomLevel zoom, const DrawPixelInfo *dst=nullptr)
The code for setting up the blitter mode and sprite information before finally drawing the sprite.
int GetStringLineCount(std::string_view str, int maxw)
Calculates number of lines of string.
void LoadStringWidthTable(FontSizes fontsizes)
Initialize _stringwidth_table cache for the specified font sizes.
bool _left_button_down
Is left mouse button pressed?
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
Return the string dimension in pixels.
static std::vector< LineSegment > MakePolygonSegments(std::span< const Point > shape, Point offset)
Make line segments from a polygon defined by points, translated by an offset.
Dimension GetStringListBoundingBox(std::span< const StringID > list, FontSize fontsize)
Get maximum dimension of a list of strings.
bool _ctrl_pressed
Is Ctrl pressed?
bool _screen_disable_anim
Disable palette animation (important for 32bpp-anim blitter during giant screenshot).
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, ExtendedTextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
ZoomLevel _font_zoom
Sprite font Zoom level (not clamped).
bool _left_button_clicked
Is left mouse button clicked?
uint GetStringListWidth(std::span< const StringID > list, FontSize fontsize)
Get maximum width of a list of strings.
uint16_t _game_speed
Current game-speed; 100 is 1x, 0 is infinite.
int DrawString(int left, int right, int top, std::string_view str, ExtendedTextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
static BlitterMode GetBlitterMode(PaletteID pal)
Helper function to get the blitter mode for different types of palettes.
static void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, PixelColour colour, int width, int dash=0)
Check line clipping by using a linear equation and draw the visible part of the line given by x/y and...
void SetMouseCursorBusy(bool busy)
Set or unset the ZZZ cursor.
void SetCursor(CursorID icon, PaletteID pal)
Assign an animation or a non-animated sprite to the cursor.
GameSessionStats _game_session_stats
Statistics about the current session.
void DrawRectOutline(const Rect &r, PixelColour colour, int width, int dash)
Draw the outline of a Rect.
void UpdateGUIZoom()
Resolve GUI zoom level, if auto-suggestion is requested.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
bool _right_button_clicked
Is right mouse button clicked?
void SetAnimatedMouseCursor(std::span< const AnimCursor > table)
Assign an animation to the cursor.
uint8_t GetDigitWidth(FontSize size)
Return the maximum width of single digit.
int _gui_scale_cfg
GUI scale in config.
Support8bpp _support8bpp
State of the support for 8bpp graphics.
uint8_t GetCharacterWidth(FontSize size, char32_t key)
Return width of character glyph.
DirectionKeys _dirkeys
Pressed direction keys.
void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub)
Draw a sprite in a viewport.
bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, std::string_view str, ExtendedTextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw a multiline string, possibly over multiple lines, if the region is within the current display cl...
PauseModes _pause_mode
The current pause mode.
void GfxFillPolygon(std::span< const Point > shape, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Fill a polygon with colour.
static bool GfxPreprocessLine(DrawPixelInfo *dpi, int &x, int &y, int &x2, int &y2, int width)
Align parameters of a line to the given DPI and check simple clipping.
Dimension GetStringMultiLineBoundingBox(StringID str, const Dimension &suggestion)
Calculate string bounding box for multi-line strings.
std::unique_ptr< uint32_t[]> DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zoom)
Draws a sprite to a new RGBA buffer (see Colour union) instead of drawing to the screen.
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
static EnumIndexArray< std::array< uint8_t, 244 >, FontSize, FontSize::End > _stringwidth_table
Cache containing width of often used characters.
SwitchMode _switch_mode
The next mainloop command.
static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation, ExtendedTextColour default_colour)
Drawing routine for drawing a laid out line of text.
void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
Draws the projection of a parallelepiped.
ZoomLevel _gui_zoom
GUI Zoom level.
static void SetColourRemap(ExtendedTextColour colour)
Set the colour remap to be for the given colour.
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
bool _right_button_down
Is right mouse button pressed?
static uint8_t _string_colourremap[3]
Recoloursprite for stringdrawing. The grf loader ensures that SpriteType::Font sprites only use colou...
bool AdjustGUIZoom(bool automatic)
Resolve GUI zoom level and adjust GUI to new zoom, if auto-suggestion is requested.
void DrawCharCentered(char32_t c, const Rect &r, TextColour colour)
Draw single character horizontally centered around (x,y).
int _gui_scale
GUI scale, 100 is 100%.
Functions related to the gfx engine.
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom)
From a rectangle that needs redrawing, find the windows that intersect with the rectangle.
Palette _cur_palette
Current palette.
Functions related to laying out the texts.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Support8bpp
Modes for 8bpp support.
@ Recolour
Recolour sprite.
@ Normal
The most basic (normal) sprite.
FontSize
Available font sizes.
@ Small
Index of the small font in the font tables.
@ Large
Index of the large font in the font tables.
@ End
Marker for the end of the enumerations.
@ Normal
Index of the normal font in the font tables.
@ Monospace
Index of the monospaced font in the font tables.
uint32_t CursorID
The number of the cursor (sprite).
StringAlignment
How to align the to-be drawn text.
@ SA_TOP
Top align the text.
@ SA_LEFT
Left align the text.
@ SA_HOR_MASK
Mask for horizontal alignment.
@ SA_RIGHT
Right align the text (must be a single bit).
@ SA_HOR_CENTER
Horizontally center the text.
@ SA_VERT_MASK
Mask for vertical alignment.
@ SA_FORCE
Force the alignment, i.e. don't swap for RTL languages.
@ SA_BOTTOM
Bottom align the text.
@ SA_VERT_CENTER
Vertically center the text.
constexpr FontSizes FONTSIZES_ALL
Mask of all possible font sizes.
uint32_t PaletteID
The number of the palette.
EnumBitSet< DirectionKey, uint8_t > DirectionKeys
Bitset of the direction keys.
@ NoShade
Do not add shading to this text colour.
@ IsPaletteColour
Colour value is already a real palette colour index, not an index of a StringColour.
@ Forced
Ignore colour changes from strings.
TextColour
Colour of the strings, see _string_colourmap in table/string_colours.h or docs/ottd-colourtext-palett...
FillRectMode
Define the operation GfxFillRect performs.
@ Recolour
Apply a recolour sprite to the screen content.
@ Checker
Draw only every second pixel, used for greying-out.
static Rect _invalid_rect
The rect for repaint.
void AddDirtyBlock(int left, int top, int right, int bottom)
Extend the internal _invalid_rect rectangle to contain the rectangle defined by the given parameters.
void DrawDirtyBlocks()
Repaints the rectangle blocks which are marked as 'dirty'.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
void RedrawScreenRect(int left, int top, int right, int bottom)
Repaints a specific rectangle of the screen.
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr int RoundDivSU(int a, uint b)
Computes round(a / b) for signed a and unsigned b.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
bool _networking
are we in networking mode?
Basic functions/variables used all over the place.
void NetworkUndrawChatMessage()
Hide the chatbox.
Network functions used by other parts of OpenTTD.
Functions/types related to NewGRF debugging.
NewGrfDebugSpritePicker _newgrf_debug_sprite_picker
The sprite picker.
GameMode
Mode which defines the state of the game.
SwitchMode
Mode which defines what mode we're switching to.
static constexpr PixelColour PC_WHITE
White palette colour.
Functions related to modal progress.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Types related to global configuration settings.
void GfxClearFontSpriteCache()
Remove all encoded font sprites from the sprite cache without discarding sprite location information.
SpriteID GetMaxSpriteID()
Get a reasonable (upper bound) estimate of the maximum SpriteID used in OpenTTD; there will be no spr...
This file contains all sprite-related enums and defines.
static const CursorID ANIMCURSOR_FLAG
Flag for saying a cursor sprite is an animated cursor.
static const PaletteID PALETTE_ALL_BLACK
Exchange any colour by black, needed for painting fictive tiles outside map.
static constexpr uint8_t PALETTE_WIDTH
number of bits of the sprite containing the recolour palette
static constexpr uint8_t PALETTE_MODIFIER_TRANSPARENT
when a sprite is to be displayed transparently, this bit needs to be set.
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
static const CursorID SPR_CURSOR_MOUSE
Cursor sprite numbers.
static constexpr uint8_t PALETTE_TEXT_RECOLOUR
Set if palette is actually a magic text recolour.
static constexpr uint8_t SPRITE_WIDTH
number of bits for the sprite number
static const PaletteID PALETTE_TO_TRANSPARENT
This sets the sprite to transparent.
Definition of base types and functions in a cross-platform compatible way.
The colour translation of GRF's strings.
static constexpr PixelColour _string_colourmap[17]
Colour mapping for TextColour.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
TextDirection _current_text_dir
Text direction of the currently selected language.
std::string_view GetEllipsis()
Get the ellipsis string for the current language.
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
Class to backup a specific variable and restore it later.
void Restore()
Restore the variable.
Parameters related to blitting.
int skip_top
How much pixels of the source to skip on the top (based on zoom of dst).
int sprite_height
Real height of the sprite.
void * dst
Destination buffer.
int left
The left offset in the 'dst' in pixels to start drawing.
int pitch
The pitch of the destination buffer.
int sprite_width
Real width of the sprite.
int skip_left
How much pixels of the source to skip on the left (based on zoom of dst).
int height
The height in pixels that needs to be drawn to dst.
const uint8_t * remap
XXX – Temporary storage for remap array.
int width
The width in pixels that needs to be drawn to dst.
const void * sprite
Pointer to the sprite how ever the encoder stored it.
int top
The top offset in the 'dst' in pixels to start drawing.
Collection of variables for cursor-display and -animation.
bool UpdateCursorPosition(int x, int y)
Update cursor position on mouse movement.
bool fix_at
mouse is moving, but cursor is not (used for scrolling)
Point pos
logical mouse position
void UpdateCursorPositionRelative(int delta_x, int delta_y)
Update cursor position based on a relative change.
bool dirty
the rect occupied by the mouse is dirty (redraw)
Point delta
relative mouse movement in this tick
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Container for the text colour and some text colour related flags for drawing.
ExtendedTextColourFlags flags
The flags.
TextColour colour
The colour.
Colour for pixel/line drawing.
Data structure describing a sprite.
uint16_t width
Width of the sprite.
uint16_t height
Height of the sprite.
int16_t y_offs
Number of pixels to shift the sprite downwards.
std::byte data[]
Sprite data.
int16_t x_offs
Number of pixels to shift the sprite to the right.
Used to only draw a part of the sprite.
Data structure for an opened window.
AllWindows< false > Iterate
Iterate all windows in whatever order is easiest.
Base of all video drivers.
Functions related to (drawing on) viewports.
void ReInitAllWindows(bool zoom_changed)
Re-initialize all windows.
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
Functions related to zooming.
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZoomLevel::Min) When shifting right,...
int UnScaleByZoomLower(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZoomLevel::Min).
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
int UnScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift right (when zoom > ZoomLevel::Min) When shifting right,...
ZoomLevel
All zoom levels we know.
@ Normal
The normal zoom level.