mirror of https://github.com/OpenRCT2/OpenRCT2.git
Fix scrolling text
This commit is contained in:
parent
1e5d998338
commit
c6152efa4e
|
@ -784,3 +784,8 @@ namespace String
|
|||
return false;
|
||||
}
|
||||
} // namespace String
|
||||
|
||||
char32_t CodepointView::iterator::GetNextCodepoint(const char* ch, const char** next)
|
||||
{
|
||||
return utf8_get_next(ch, next);
|
||||
}
|
||||
|
|
|
@ -118,3 +118,80 @@ namespace String
|
|||
bool ContainsColourCode(const std::string& string);
|
||||
|
||||
} // namespace String
|
||||
|
||||
class CodepointView
|
||||
{
|
||||
private:
|
||||
std::string_view _str;
|
||||
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
private:
|
||||
std::string_view _str;
|
||||
size_t _index;
|
||||
|
||||
public:
|
||||
iterator(std::string_view str, size_t index)
|
||||
: _str(str)
|
||||
, _index(index)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const iterator& rhs) const
|
||||
{
|
||||
return _index == rhs._index;
|
||||
}
|
||||
bool operator!=(const iterator& rhs) const
|
||||
{
|
||||
return _index != rhs._index;
|
||||
}
|
||||
const char32_t operator*() const
|
||||
{
|
||||
return GetNextCodepoint(&_str[_index], nullptr);
|
||||
}
|
||||
iterator& operator++()
|
||||
{
|
||||
if (_index < _str.size())
|
||||
{
|
||||
const utf8* nextch;
|
||||
GetNextCodepoint(&_str[_index], &nextch);
|
||||
_index = nextch - _str.data();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int)
|
||||
{
|
||||
auto result = *this;
|
||||
if (_index < _str.size())
|
||||
{
|
||||
const utf8* nextch;
|
||||
GetNextCodepoint(&_str[_index], &nextch);
|
||||
_index = nextch - _str.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t GetIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
static char32_t GetNextCodepoint(const char* ch, const char** next);
|
||||
};
|
||||
|
||||
CodepointView(std::string_view str)
|
||||
: _str(str)
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(_str, 0);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(_str, _str.size());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "../common.h"
|
||||
#include "../config/Config.h"
|
||||
#include "../core/String.hpp"
|
||||
#include "../drawing/Drawing.h"
|
||||
#include "../interface/Viewport.h"
|
||||
#include "../localisation/Formatting.h"
|
||||
|
@ -23,81 +24,6 @@
|
|||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
class CodepointView
|
||||
{
|
||||
private:
|
||||
std::string_view _str;
|
||||
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
private:
|
||||
std::string_view _str;
|
||||
size_t _index;
|
||||
|
||||
public:
|
||||
iterator(std::string_view str, size_t index)
|
||||
: _str(str)
|
||||
, _index(index)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const iterator& rhs) const
|
||||
{
|
||||
return _index == rhs._index;
|
||||
}
|
||||
bool operator!=(const iterator& rhs) const
|
||||
{
|
||||
return _index != rhs._index;
|
||||
}
|
||||
const char32_t operator*() const
|
||||
{
|
||||
return utf8_get_next(&_str[_index], nullptr);
|
||||
}
|
||||
iterator& operator++()
|
||||
{
|
||||
if (_index < _str.size())
|
||||
{
|
||||
const utf8* nextch;
|
||||
utf8_get_next(&_str[_index], &nextch);
|
||||
_index = nextch - _str.data();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
iterator operator++(int)
|
||||
{
|
||||
auto result = *this;
|
||||
if (_index < _str.size())
|
||||
{
|
||||
const utf8* nextch;
|
||||
utf8_get_next(&_str[_index], &nextch);
|
||||
_index = nextch - _str.data();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t GetIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
};
|
||||
|
||||
CodepointView(std::string_view str)
|
||||
: _str(str)
|
||||
{
|
||||
}
|
||||
|
||||
iterator begin() const
|
||||
{
|
||||
return iterator(_str, 0);
|
||||
}
|
||||
|
||||
iterator end() const
|
||||
{
|
||||
return iterator(_str, _str.size());
|
||||
}
|
||||
};
|
||||
|
||||
enum : uint32_t
|
||||
{
|
||||
TEXT_DRAW_FLAG_INSET = 1 << 0,
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#include "../config/Config.h"
|
||||
#include "../core/String.hpp"
|
||||
#include "../interface/Colour.h"
|
||||
#include "../localisation/Formatting.h"
|
||||
#include "../localisation/Localisation.h"
|
||||
#include "../localisation/LocalisationService.h"
|
||||
#include "../paint/Paint.h"
|
||||
|
@ -19,6 +21,8 @@
|
|||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
using namespace OpenRCT2;
|
||||
|
||||
struct rct_draw_scroll_text
|
||||
{
|
||||
rct_string_id string_id;
|
||||
|
@ -38,9 +42,9 @@ static uint32_t _drawSCrollNextIndex = 0;
|
|||
static std::mutex _scrollingTextMutex;
|
||||
|
||||
static void scrolling_text_set_bitmap_for_sprite(
|
||||
utf8* text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour);
|
||||
std::string_view text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour);
|
||||
static void scrolling_text_set_bitmap_for_ttf(
|
||||
utf8* text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour);
|
||||
std::string_view text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour);
|
||||
|
||||
void scrolling_text_initialise_bitmaps()
|
||||
{
|
||||
|
@ -1490,105 +1494,98 @@ int32_t scrolling_text_setup(
|
|||
}
|
||||
|
||||
static void scrolling_text_set_bitmap_for_sprite(
|
||||
utf8* text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour)
|
||||
std::string_view text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour)
|
||||
{
|
||||
auto characterColour = colour;
|
||||
auto fmt = FmtString(text);
|
||||
|
||||
utf8* ch = text;
|
||||
while (true)
|
||||
// Repeat string a maximum of four times (eliminates possibility of infinite loop)
|
||||
for (auto i = 0; i < 4; i++)
|
||||
{
|
||||
uint32_t codepoint = utf8_get_next(ch, const_cast<const utf8**>(&ch));
|
||||
|
||||
// If at the end of the string loop back to the start
|
||||
if (codepoint == 0)
|
||||
for (const auto& token : fmt)
|
||||
{
|
||||
ch = text;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set any change in colour
|
||||
if (codepoint <= FORMAT_COLOUR_CODE_END && codepoint >= FORMAT_COLOUR_CODE_START)
|
||||
{
|
||||
codepoint -= FORMAT_COLOUR_CODE_START;
|
||||
const rct_g1_element* g1 = gfx_get_g1_element(SPR_TEXT_PALETTE);
|
||||
if (g1 != nullptr)
|
||||
if (token.IsLiteral())
|
||||
{
|
||||
characterColour = g1->offset[codepoint * 4];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If another type of control character ignore
|
||||
if (codepoint < 32)
|
||||
continue;
|
||||
|
||||
int32_t characterWidth = font_sprite_get_codepoint_width(FONT_SPRITE_BASE_TINY, codepoint);
|
||||
uint8_t* characterBitmap = font_sprite_get_codepoint_bitmap(codepoint);
|
||||
for (; characterWidth != 0; characterWidth--, characterBitmap++)
|
||||
{
|
||||
// Skip any non-displayed columns
|
||||
if (scroll != 0)
|
||||
{
|
||||
scroll--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int16_t scrollPosition = *scrollPositionOffsets;
|
||||
if (scrollPosition == -1)
|
||||
return;
|
||||
if (scrollPosition > -1)
|
||||
{
|
||||
uint8_t* dst = &bitmap[scrollPosition];
|
||||
for (uint8_t char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1)
|
||||
CodepointView codepoints(token.text);
|
||||
for (auto codepoint : codepoints)
|
||||
{
|
||||
if (char_bitmap & 1)
|
||||
*dst = characterColour;
|
||||
auto characterWidth = font_sprite_get_codepoint_width(FONT_SPRITE_BASE_TINY, codepoint);
|
||||
auto characterBitmap = font_sprite_get_codepoint_bitmap(codepoint);
|
||||
for (; characterWidth != 0; characterWidth--, characterBitmap++)
|
||||
{
|
||||
// Skip any non-displayed columns
|
||||
if (scroll != 0)
|
||||
{
|
||||
scroll--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Jump to next row
|
||||
dst += 64;
|
||||
int16_t scrollPosition = *scrollPositionOffsets;
|
||||
if (scrollPosition == -1)
|
||||
return;
|
||||
|
||||
if (scrollPosition > -1)
|
||||
{
|
||||
auto dst = &bitmap[scrollPosition];
|
||||
for (uint8_t char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1)
|
||||
{
|
||||
if (char_bitmap & 1)
|
||||
*dst = characterColour;
|
||||
|
||||
// Jump to next row
|
||||
dst += 64;
|
||||
}
|
||||
}
|
||||
scrollPositionOffsets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (token.kind <= FORMAT_COLOUR_CODE_END && token.kind >= FORMAT_COLOUR_CODE_START)
|
||||
{
|
||||
auto g1 = gfx_get_g1_element(SPR_TEXT_PALETTE);
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
auto colourIndex = token.kind - FORMAT_COLOUR_CODE_START;
|
||||
characterColour = g1->offset[colourIndex * 4];
|
||||
}
|
||||
}
|
||||
scrollPositionOffsets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void scrolling_text_set_bitmap_for_ttf(
|
||||
utf8* text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour)
|
||||
std::string_view text, int32_t scroll, uint8_t* bitmap, const int16_t* scrollPositionOffsets, colour_t colour)
|
||||
{
|
||||
#ifndef NO_TTF
|
||||
TTFFontDescriptor* fontDesc = ttf_get_font_from_sprite_base(FONT_SPRITE_BASE_TINY);
|
||||
auto fontDesc = ttf_get_font_from_sprite_base(FONT_SPRITE_BASE_TINY);
|
||||
if (fontDesc->font == nullptr)
|
||||
{
|
||||
scrolling_text_set_bitmap_for_sprite(text, scroll, bitmap, scrollPositionOffsets, colour);
|
||||
return;
|
||||
}
|
||||
|
||||
utf8* dstCh = text;
|
||||
utf8* ch = text;
|
||||
int32_t codepoint;
|
||||
while ((codepoint = utf8_get_next(ch, const_cast<const utf8**>(&ch))) != 0)
|
||||
thread_local std::string ttfBuffer;
|
||||
ttfBuffer.clear();
|
||||
|
||||
auto fmt = FmtString(text);
|
||||
for (const auto& token : fmt)
|
||||
{
|
||||
if (utf8_is_format_code(codepoint))
|
||||
if (token.IsLiteral())
|
||||
{
|
||||
if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END)
|
||||
ttfBuffer.append(token.text);
|
||||
}
|
||||
else if (token.kind >= FORMAT_COLOUR_CODE_START && token.kind <= FORMAT_COLOUR_CODE_END)
|
||||
{
|
||||
auto g1 = gfx_get_g1_element(SPR_TEXT_PALETTE);
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
codepoint -= FORMAT_COLOUR_CODE_START;
|
||||
auto g1 = gfx_get_g1_element(SPR_TEXT_PALETTE);
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
colour = g1->offset[codepoint * 4];
|
||||
}
|
||||
auto colourIndex = token.kind - FORMAT_COLOUR_CODE_START;
|
||||
colour = g1->offset[colourIndex * 4];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dstCh = utf8_write_codepoint(dstCh, codepoint);
|
||||
}
|
||||
}
|
||||
*dstCh = 0;
|
||||
|
||||
TTFSurface* surface = ttf_surface_cache_get_or_add(fontDesc->font, text);
|
||||
auto surface = ttf_surface_cache_get_or_add(fontDesc->font, ttfBuffer.c_str());
|
||||
if (surface == nullptr)
|
||||
{
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue