mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-27 16:54:52 +01:00
implement utf8, part 14
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
<ClCompile Include="..\src\cursors.c" />
|
||||
<ClCompile Include="..\src\diagnostic.c" />
|
||||
<ClCompile Include="..\src\drawing\drawing.c" />
|
||||
<ClCompile Include="..\src\drawing\font.c" />
|
||||
<ClCompile Include="..\src\drawing\line.c" />
|
||||
<ClCompile Include="..\src\drawing\rain.c" />
|
||||
<ClCompile Include="..\src\drawing\rect.c" />
|
||||
@@ -195,6 +196,7 @@
|
||||
<ClInclude Include="..\src\cursors.h" />
|
||||
<ClInclude Include="..\src\diagnostic.h" />
|
||||
<ClInclude Include="..\src\drawing\drawing.h" />
|
||||
<ClInclude Include="..\src\drawing\font.h" />
|
||||
<ClInclude Include="..\src\editor.h" />
|
||||
<ClInclude Include="..\src\game.h" />
|
||||
<ClInclude Include="..\src\hook.h" />
|
||||
|
||||
@@ -501,6 +501,9 @@
|
||||
<ClCompile Include="..\src\drawing\scrolling_text.c">
|
||||
<Filter>Source\Drawing</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\drawing\font.c">
|
||||
<Filter>Source\Drawing</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\src\management\award.h">
|
||||
@@ -731,5 +734,8 @@
|
||||
<ClInclude Include="..\src\cheats.h">
|
||||
<Filter>Source</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\drawing\font.h">
|
||||
<Filter>Source\Drawing</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -22,6 +22,7 @@
|
||||
#define _DRAWING_H_
|
||||
|
||||
#include "../common.h"
|
||||
#include "font.h"
|
||||
|
||||
// Size: 0x10
|
||||
typedef struct {
|
||||
@@ -113,7 +114,6 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32
|
||||
void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer);
|
||||
|
||||
// string
|
||||
void gfx_load_character_widths();
|
||||
int clip_text(char *buffer, int width);
|
||||
int gfx_wrap_string(char* buffer, int width, int* num_lines, int* font_height);
|
||||
int gfx_get_string_width(char *buffer);
|
||||
|
||||
94
src/drawing/font.c
Normal file
94
src/drawing/font.c
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "../addresses.h"
|
||||
#include "../localisation/localisation.h"
|
||||
#include "../sprites.h"
|
||||
#include "drawing.h"
|
||||
#include "font.h"
|
||||
|
||||
static uint8 *_spriteFontCharacterWidths = (uint8*)RCT2_ADDRESS_FONT_CHAR_WIDTH;
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C19AC
|
||||
*/
|
||||
void font_sprite_initialise_characters()
|
||||
{
|
||||
uint8* pCharacterWidth = _spriteFontCharacterWidths;
|
||||
for (int fontSize = 0; fontSize < FONT_SIZE_COUNT; fontSize++) {
|
||||
int glyphOffset = fontSize * FONT_SPRITE_GLYPH_COUNT;
|
||||
for (uint8 glyphIndex = 0; glyphIndex < FONT_SPRITE_GLYPH_COUNT; glyphIndex++) {
|
||||
rct_g1_element g1 = g1Elements[glyphIndex + SPR_CHAR_START + glyphOffset];
|
||||
|
||||
int width = fontSize == FONT_SIZE_BIG ? g1.width + 1 : g1.width - 1;
|
||||
if (glyphIndex >= (FORMAT_ARGUMENT_CODE_START - 32) && glyphIndex < (FORMAT_COLOUR_CODE_END - 32)) {
|
||||
width = 0;
|
||||
}
|
||||
*pCharacterWidth++ = (uint8)width;
|
||||
}
|
||||
}
|
||||
|
||||
scrolling_text_initialise_bitmaps();
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
rct_g1_element* g1 = &g1Elements[0x606 + i];
|
||||
uint8* unknown_pointer = RCT2_ADDRESS(0x009C3852, uint8) + 0xA12 * i;
|
||||
g1->offset = unknown_pointer;
|
||||
g1->width = 64;
|
||||
g1->height = 40;
|
||||
*((uint16*)unknown_pointer) = 0xFFFF;
|
||||
*((uint32*)(unknown_pointer + 0x0E)) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int font_sprite_get_codepoint_offset(int codepoint)
|
||||
{
|
||||
switch (codepoint) {
|
||||
case FORMAT_ENDQUOTES: return 34 - 32;
|
||||
|
||||
case FORMAT_AMINUSCULE: return 159 - 32;
|
||||
case FORMAT_UP: return 160 - 32;
|
||||
case FORMAT_SYMBOL_i: return 160 - 32;
|
||||
case FORMAT_CENT: return 162 - 32;
|
||||
case FORMAT_POUND: return 163 - 32;
|
||||
|
||||
case FORMAT_YEN: return 165 - 32;
|
||||
|
||||
|
||||
|
||||
case FORMAT_COPYRIGHT: return 169 - 32;
|
||||
case FORMAT_DOWN: return 170 - 32;
|
||||
case FORMAT_LEFTGUILLEMET: return 171 - 32;
|
||||
case FORMAT_TICK: return 172 - 32;
|
||||
case FORMAT_CROSS: return 173 - 32;
|
||||
|
||||
case FORMAT_RIGHT: return 175 - 32;
|
||||
case FORMAT_DEGREE: return 176 - 32;
|
||||
case FORMAT_SYMBOL_RAILWAY: return 177 - 32;
|
||||
case FORMAT_SQUARED: return 178 - 32;
|
||||
|
||||
case FORMAT_OPENQUOTES: return 180 - 32;
|
||||
case FORMAT_EURO: return 181 - 32;
|
||||
case FORMAT_SYMBOL_ROAD: return 182 - 32;
|
||||
case FORMAT_SYMBOL_FLAG: return 183 - 32;
|
||||
case FORMAT_APPROX: return 184 - 32;
|
||||
case FORMAT_POWERNEGATIVEONE: return 185 - 32;
|
||||
case FORMAT_BULLET: return 186 - 32;
|
||||
case FORMAT_RIGHTGUILLEMET: return 187 - 32;
|
||||
case FORMAT_SMALLUP: return 188 - 32;
|
||||
case FORMAT_SMALLDOWN: return 189 - 32;
|
||||
case FORMAT_LEFT: return 190 - 32;
|
||||
case FORMAT_INVERTEDQUESTION: return 191 - 32;
|
||||
default:
|
||||
if (codepoint < 32 || codepoint >= 256) codepoint = '?';
|
||||
return codepoint - 32;
|
||||
}
|
||||
}
|
||||
|
||||
int font_sprite_get_codepoint_width(int fontSpriteBase, int codepoint)
|
||||
{
|
||||
return _spriteFontCharacterWidths[fontSpriteBase + font_sprite_get_codepoint_offset(codepoint)];
|
||||
}
|
||||
|
||||
int font_sprite_get_codepoint_sprite(int fontSpriteBase, int codepoint)
|
||||
{
|
||||
return SPR_CHAR_START + ((IMAGE_TYPE_USE_PALETTE << 28) | (fontSpriteBase + font_sprite_get_codepoint_offset(codepoint)));
|
||||
}
|
||||
28
src/drawing/font.h
Normal file
28
src/drawing/font.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _DRAWING_FONT_H_
|
||||
#define _DRAWING_FONT_H_
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
enum {
|
||||
FONT_SIZE_TINY = 2,
|
||||
FONT_SIZE_SMALL = 0,
|
||||
FONT_SIZE_MEDIUM = 1,
|
||||
FONT_SIZE_BIG = 3,
|
||||
FONT_SIZE_COUNT = 4
|
||||
};
|
||||
|
||||
enum {
|
||||
FONT_SPRITE_GLYPH_COUNT = 224,
|
||||
|
||||
FONT_SPRITE_BASE_TINY = 448,
|
||||
FONT_SPRITE_BASE_SMALL = 0,
|
||||
FONT_SPRITE_BASE_MEDIUM = 224,
|
||||
FONT_SPRITE_BASE_BIG = 672
|
||||
};
|
||||
|
||||
void font_sprite_initialise_characters();
|
||||
int font_sprite_get_codepoint_offset(int codepoint);
|
||||
int font_sprite_get_codepoint_width(int fontSpriteBase, int codepoint);
|
||||
int font_sprite_get_codepoint_sprite(int fontSpriteBase, int codepoint);
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <SDL_ttf.h>
|
||||
#include "../addresses.h"
|
||||
#include "../config.h"
|
||||
#include "../localisation/localisation.h"
|
||||
@@ -15,6 +16,10 @@ typedef struct {
|
||||
} rct_draw_scroll_text;
|
||||
|
||||
rct_draw_scroll_text *gDrawScrollTextList = RCT2_ADDRESS(RCT2_ADDRESS_DRAW_SCROLL_LIST, rct_draw_scroll_text);
|
||||
uint8 *gCharacterBitmaps = RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8);
|
||||
|
||||
void scrolling_text_set_bitmap_for_sprite(utf8 *text, int scroll, uint8 *bitmap, sint16 *scrollPositionOffsets);
|
||||
void scrolling_text_set_bitmap_for_ttf(utf8 *text, int scroll, uint8 *bitmap, sint16 *scrollPositionOffsets);
|
||||
|
||||
void scrolling_text_initialise_bitmaps()
|
||||
{
|
||||
@@ -42,27 +47,22 @@ void scrolling_text_initialise_bitmaps()
|
||||
val |= 0x80;
|
||||
}
|
||||
}
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[i * 8 + x] = val;
|
||||
gCharacterBitmaps[i * 8 + x] = val;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C42D9
|
||||
*/
|
||||
int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode)
|
||||
static uint8 *font_sprite_get_codepoint_bitmap(int codepoint)
|
||||
{
|
||||
rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
|
||||
return &gCharacterBitmaps[font_sprite_get_codepoint_offset(codepoint) * 8];
|
||||
}
|
||||
|
||||
if (dpi->zoom_level != 0) return 0x626;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++;
|
||||
|
||||
// Find the oldest scroll for use as the newest
|
||||
static int scrolling_text_get_matching_or_oldest(rct_string_id stringId, uint16 scroll, uint16 scrollingMode)
|
||||
{
|
||||
uint32 oldestId = 0xFFFFFFFF;
|
||||
uint8 scrollIndex = 0xFF;
|
||||
int scrollIndex = -1;
|
||||
rct_draw_scroll_text* oldestScroll = NULL;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
rct_draw_scroll_text *scrollText = &gDrawScrollTextList[i];
|
||||
@@ -84,70 +84,103 @@ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrolling
|
||||
return i + 0x606;
|
||||
}
|
||||
}
|
||||
return scrollIndex;
|
||||
}
|
||||
|
||||
static uint8 scrolling_text_get_colour(uint32 character)
|
||||
{
|
||||
int edi = character & 0x7F;
|
||||
int offset = 0;
|
||||
if (character >= 0x80) offset = 2;
|
||||
return RCT2_ADDRESS(0x0141FC47, uint8)[offset + (edi * 8)];
|
||||
}
|
||||
|
||||
static void scrolling_text_format(utf8 *dst, rct_draw_scroll_text *scrollText)
|
||||
{
|
||||
if (gConfigGeneral.upper_case_banners) {
|
||||
format_string_to_upper(dst, scrollText->string_id, &scrollText->string_args_0);
|
||||
} else {
|
||||
format_string(dst, scrollText->string_id, &scrollText->string_args_0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C42D9
|
||||
*/
|
||||
int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrollingMode)
|
||||
{
|
||||
rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*);
|
||||
|
||||
if (dpi->zoom_level != 0) return 0x626;
|
||||
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32)++;
|
||||
|
||||
int scrollIndex = scrolling_text_get_matching_or_oldest(stringId, scroll, scrollingMode);
|
||||
if (scrollIndex >= 0x606) return scrollIndex;
|
||||
|
||||
// Setup scrolling text
|
||||
rct_draw_scroll_text* scrollText = oldestScroll;
|
||||
rct_draw_scroll_text* scrollText = &gDrawScrollTextList[scrollIndex];
|
||||
scrollText->string_id = stringId;
|
||||
scrollText->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32);
|
||||
scrollText->string_args_1 = RCT2_GLOBAL(0x13CE956, uint32);
|
||||
scrollText->string_args_0 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32);
|
||||
scrollText->string_args_1 = RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32);
|
||||
scrollText->position = scroll;
|
||||
scrollText->mode = scrollingMode;
|
||||
scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32_t);
|
||||
scrollText->id = RCT2_GLOBAL(RCT2_ADDRESS_DRAW_SCROLL_NEXT_ID, uint32);
|
||||
|
||||
uint8* scrollPixelPointer = scrollText->bitmap;
|
||||
memset(scrollPixelPointer, 0, 320 * 8);
|
||||
// Create the string to draw
|
||||
utf8 scrollString[256];
|
||||
scrolling_text_format(scrollString, scrollText);
|
||||
|
||||
// Convert string id back into a string for processing
|
||||
utf8 scrollString[MAX_PATH];
|
||||
if (gConfigGeneral.upper_case_banners)
|
||||
format_string_to_upper(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
|
||||
else
|
||||
format_string(scrollString, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS);
|
||||
sint16* scrollingModePositions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16*)[scrollingMode];
|
||||
|
||||
memset(scrollText->bitmap, 0, 320 * 8);
|
||||
if (gUseTrueTypeFont) {
|
||||
scrolling_text_set_bitmap_for_ttf(scrollString, scroll, scrollText->bitmap, scrollingModePositions);
|
||||
} else {
|
||||
scrolling_text_set_bitmap_for_sprite(scrollString, scroll, scrollText->bitmap, scrollingModePositions);
|
||||
}
|
||||
|
||||
// Setup character colour from ???
|
||||
uint32 character = RCT2_GLOBAL(0x13CE959, uint8);
|
||||
int edi = character & 0x7F;
|
||||
int offs = 0;
|
||||
if (character >= 0x80) offs = 2;
|
||||
uint8 characterColour = RCT2_ADDRESS(0x0141FC47, uint8)[offs + edi * 8];
|
||||
return scrollIndex + 0x606;
|
||||
}
|
||||
|
||||
sint16* scrollingModePositions = RCT2_ADDRESS(RCT2_ADDRESS_SCROLLING_MODE_POSITIONS, uint16_t*)[scrollingMode];
|
||||
uint8* formatResult = scrollString;
|
||||
void scrolling_text_set_bitmap_for_sprite(utf8 *text, int scroll, uint8 *bitmap, sint16 *scrollPositionOffsets)
|
||||
{
|
||||
uint8 characterColour = scrolling_text_get_colour(RCT2_GLOBAL(0x013CE959, uint8));
|
||||
|
||||
utf8 *ch = text;
|
||||
while (true) {
|
||||
character = utf8_get_next(formatResult, &formatResult);
|
||||
uint32 codepoint = utf8_get_next(ch, &ch);
|
||||
|
||||
// If at the end of the string loop back to the start
|
||||
if (character == 0) {
|
||||
formatResult = scrollString;
|
||||
if (codepoint == 0) {
|
||||
ch = text;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set any change in colour
|
||||
if (character <= FORMAT_COLOUR_CODE_END && character >= FORMAT_COLOUR_CODE_START){
|
||||
character -= FORMAT_COLOUR_CODE_START;
|
||||
characterColour = RCT2_GLOBAL(0x009FF048, uint8*)[character * 4];
|
||||
if (codepoint <= FORMAT_COLOUR_CODE_END && codepoint >= FORMAT_COLOUR_CODE_START){
|
||||
codepoint -= FORMAT_COLOUR_CODE_START;
|
||||
characterColour = RCT2_GLOBAL(0x009FF048, uint8*)[codepoint * 4];
|
||||
continue;
|
||||
}
|
||||
|
||||
// If another type of control character ignore
|
||||
if (character < 32) continue;
|
||||
if (codepoint < 32) continue;
|
||||
|
||||
// Convert to an indexable character
|
||||
character = utf8_get_sprite_offset_for_codepoint(character);
|
||||
|
||||
uint8 characterWidth = RCT2_ADDRESS(RCT2_ADDRESS_FONT_CHAR_WIDTH + 448, uint8)[character];
|
||||
uint8* characterBitmap = &(RCT2_ADDRESS(RCT2_ADDRESS_CHARACTER_BITMAP, uint8)[character * 8]);
|
||||
int characterWidth = font_sprite_get_codepoint_width(FONT_SPRITE_BASE_TINY, codepoint);
|
||||
uint8 *characterBitmap = font_sprite_get_codepoint_bitmap(codepoint);
|
||||
for (; characterWidth != 0; characterWidth--, characterBitmap++) {
|
||||
// Skip any none displayed columns
|
||||
if (scroll != 0){
|
||||
if (scroll != 0) {
|
||||
scroll--;
|
||||
continue;
|
||||
}
|
||||
|
||||
sint16 scrollPosition = *scrollingModePositions;
|
||||
if (scrollPosition == -1) return scrollIndex + 0x606;
|
||||
sint16 scrollPosition = *scrollPositionOffsets;
|
||||
if (scrollPosition == -1) return;
|
||||
if (scrollPosition > -1) {
|
||||
uint8* dst = &scrollPixelPointer[scrollPosition];
|
||||
uint8 *dst = &bitmap[scrollPosition];
|
||||
for (uint8 char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1){
|
||||
if (char_bitmap & 1) *dst = characterColour;
|
||||
|
||||
@@ -155,7 +188,83 @@ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrolling
|
||||
dst += 64;
|
||||
}
|
||||
}
|
||||
scrollingModePositions++;
|
||||
scrollPositionOffsets++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TTF_Font *ttf_get_font_from_sprite_base(uint16 spriteBase);
|
||||
SDL_Surface *_ttf_surface_cache_get_or_add(TTF_Font *font, const utf8 *text);
|
||||
|
||||
void scrolling_text_set_bitmap_for_ttf(utf8 *text, int scroll, uint8 *bitmap, sint16 *scrollPositionOffsets)
|
||||
{
|
||||
// Currently only supports one colour
|
||||
uint8 colour = 0;
|
||||
|
||||
utf8 *dstCh = text;
|
||||
utf8 *ch = text;
|
||||
int codepoint;
|
||||
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
|
||||
if (utf8_is_format_code(codepoint)) {
|
||||
if (colour == 0 && codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) {
|
||||
colour = (uint8)codepoint;
|
||||
}
|
||||
} else {
|
||||
dstCh = utf8_write_codepoint(dstCh, codepoint);
|
||||
}
|
||||
}
|
||||
*dstCh = 0;
|
||||
|
||||
if (colour == 0) {
|
||||
colour = scrolling_text_get_colour(RCT2_GLOBAL(0x013CE959, uint8));
|
||||
} else {
|
||||
colour = RCT2_GLOBAL(0x009FF048, uint8*)[(colour - FORMAT_COLOUR_CODE_START) * 4];
|
||||
}
|
||||
|
||||
TTF_Font *font = ttf_get_font_from_sprite_base(FONT_SPRITE_BASE_TINY);
|
||||
SDL_Surface *surface = _ttf_surface_cache_get_or_add(font, text);
|
||||
if (surface == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(surface) && SDL_LockSurface(surface) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pitch = surface->pitch;
|
||||
int width = surface->w;
|
||||
int height = surface->h;
|
||||
uint8 *src = surface->pixels;
|
||||
|
||||
// Offset
|
||||
height -= 3;
|
||||
src += 3 * pitch;
|
||||
height = min(height, 8);
|
||||
|
||||
int x = 0;
|
||||
while (true) {
|
||||
// Skip any none displayed columns
|
||||
if (scroll == 0) {
|
||||
sint16 scrollPosition = *scrollPositionOffsets;
|
||||
if (scrollPosition == -1) return;
|
||||
if (scrollPosition > -1) {
|
||||
uint8 *dst = &bitmap[scrollPosition];
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
if (src[y * pitch + x] != 0) *dst = colour;
|
||||
|
||||
// Jump to next row
|
||||
dst += 64;
|
||||
}
|
||||
}
|
||||
scrollPositionOffsets++;
|
||||
} else {
|
||||
scroll--;
|
||||
}
|
||||
|
||||
x++;
|
||||
if (x >= width) x = 0;
|
||||
}
|
||||
|
||||
if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@ static void ttf_draw_string(rct_drawpixelinfo *dpi, char *buffer, int colour, in
|
||||
|
||||
static bool _ttfInitialised = false;
|
||||
static TTF_Font *_ttfFont[4] = { NULL };
|
||||
static int _ttfFontOffsetX = 0;
|
||||
static int _ttfFontOffsetY = 0;
|
||||
int _ttfFontOffsetX = 0;
|
||||
int _ttfFontOffsetY = 0;
|
||||
|
||||
static const int TTFFontSizes[] = { 7, 9, 11, 13 };
|
||||
static const int TTFFontSizes[] = { 9, 9, 11, 13 };
|
||||
|
||||
#define TTF_SURFACE_CACHE_SIZE 256
|
||||
#define TTF_GETWIDTH_CACHE_SIZE 1024
|
||||
@@ -61,58 +61,6 @@ static int _ttfGetWidthCacheCount = 0;
|
||||
static int _ttfGetWidthCacheHitCount = 0;
|
||||
static int _ttfGetWidthCacheMissCount = 0;
|
||||
|
||||
enum {
|
||||
FONT_SIZE_TINY = 2,
|
||||
FONT_SIZE_SMALL = 0,
|
||||
FONT_SIZE_MEDIUM = 1,
|
||||
FONT_SIZE_BIG = 3,
|
||||
FONT_SIZE_COUNT = 4
|
||||
};
|
||||
|
||||
enum {
|
||||
FONT_SPRITE_GLYPH_COUNT = 224,
|
||||
|
||||
FONT_SPRITE_BASE_TINY = 448,
|
||||
FONT_SPRITE_BASE_SMALL = 0,
|
||||
FONT_SPRITE_BASE_MEDIUM = 224,
|
||||
FONT_SPRITE_BASE_BIG = 672
|
||||
};
|
||||
|
||||
static uint8 *_spriteFontCharacterWidths = (uint8*)RCT2_ADDRESS_FONT_CHAR_WIDTH;
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C19AC
|
||||
*/
|
||||
void gfx_load_character_widths()
|
||||
{
|
||||
uint8* pCharacterWidth = _spriteFontCharacterWidths;
|
||||
for (int fontSize = 0; fontSize < FONT_SIZE_COUNT; fontSize++) {
|
||||
int glyphOffset = fontSize * FONT_SPRITE_GLYPH_COUNT;
|
||||
for (uint8 glyphIndex = 0; glyphIndex < FONT_SPRITE_GLYPH_COUNT; glyphIndex++) {
|
||||
rct_g1_element g1 = g1Elements[glyphIndex + SPR_CHAR_START + glyphOffset];
|
||||
|
||||
int width = fontSize == FONT_SIZE_BIG ? g1.width + 1 : g1.width - 1;
|
||||
if (glyphIndex >= (FORMAT_ARGUMENT_CODE_START - 32) && glyphIndex < (FORMAT_COLOUR_CODE_END - 32)) {
|
||||
width = 0;
|
||||
}
|
||||
*pCharacterWidth++ = (uint8)width;
|
||||
}
|
||||
}
|
||||
|
||||
scrolling_text_initialise_bitmaps();
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
rct_g1_element* g1 = &g1Elements[0x606 + i];
|
||||
uint8* unknown_pointer = RCT2_ADDRESS(0x009C3852, uint8) + 0xA12 * i;
|
||||
g1->offset = unknown_pointer;
|
||||
g1->width = 64;
|
||||
g1->height = 40;
|
||||
*((uint16*)unknown_pointer) = 0xFFFF;
|
||||
*((uint32*)(unknown_pointer + 0x0E)) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006C23B1
|
||||
@@ -802,7 +750,7 @@ static void _ttf_surface_cache_dispose_all()
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Surface *_ttf_surface_cache_get_or_add(TTF_Font *font, const utf8 *text)
|
||||
SDL_Surface *_ttf_surface_cache_get_or_add(TTF_Font *font, const utf8 *text)
|
||||
{
|
||||
ttf_cache_entry *entry;
|
||||
|
||||
@@ -987,16 +935,16 @@ typedef struct {
|
||||
|
||||
static void ttf_draw_character_sprite(rct_drawpixelinfo *dpi, int codepoint, text_draw_info *info)
|
||||
{
|
||||
uint32 charOffset = info->font_sprite_base + utf8_get_sprite_offset_for_codepoint(codepoint);
|
||||
int charWidth = _spriteFontCharacterWidths[charOffset] & 0xFF;
|
||||
int characterWidth = font_sprite_get_codepoint_width(info->font_sprite_base, codepoint);
|
||||
int sprite = font_sprite_get_codepoint_sprite(info->font_sprite_base, codepoint);
|
||||
|
||||
if (!(info->flags & TEXT_DRAW_FLAG_NO_DRAW)) {
|
||||
RCT2_GLOBAL(0x009ABDA4, uint8*) = (uint8*)&info->palette;
|
||||
RCT2_GLOBAL(0x00EDF81C, uint32) = (IMAGE_TYPE_USE_PALETTE << 28);
|
||||
gfx_draw_sprite_palette_set(dpi, SPR_CHAR_START + ((IMAGE_TYPE_USE_PALETTE << 28) | charOffset), info->x, info->y, info->palette, NULL);
|
||||
gfx_draw_sprite_palette_set(dpi, sprite, info->x, info->y, info->palette, NULL);
|
||||
}
|
||||
|
||||
info->x += charWidth;
|
||||
info->x += characterWidth;
|
||||
}
|
||||
|
||||
static void ttf_draw_string_raw_sprite(rct_drawpixelinfo *dpi, const utf8 *text, text_draw_info *info)
|
||||
|
||||
@@ -144,6 +144,32 @@ bool utf8_is_codepoint_start(utf8 *text)
|
||||
return false;
|
||||
}
|
||||
|
||||
void utf8_remove_format_codes(utf8 *text)
|
||||
{
|
||||
utf8 *dstCh = text;
|
||||
utf8 *ch = text;
|
||||
int codepoint;
|
||||
while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
|
||||
if (!utf8_is_format_code(codepoint)) {
|
||||
dstCh = utf8_write_codepoint(dstCh, codepoint);
|
||||
}
|
||||
}
|
||||
*dstCh = 0;
|
||||
}
|
||||
|
||||
int utf8_get_codepoint_length(int codepoint)
|
||||
{
|
||||
if (codepoint <= 0x7F) {
|
||||
return 1;
|
||||
} else if (codepoint <= 0x7FF) {
|
||||
return 2;
|
||||
} else if (codepoint <= 0xFFFF) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
const char *language_get_string(rct_string_id id)
|
||||
{
|
||||
const char *openrctString = NULL;
|
||||
|
||||
@@ -73,5 +73,7 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/
|
||||
uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr);
|
||||
utf8 *utf8_write_codepoint(utf8 *dst, uint32 codepoint);
|
||||
bool utf8_is_codepoint_start(utf8 *text);
|
||||
void utf8_remove_format_codes(utf8 *text);
|
||||
int utf8_get_codepoint_length(int codepoint);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -154,50 +154,6 @@ bool utf8_should_use_sprite_for_codepoint(int codepoint)
|
||||
}
|
||||
}
|
||||
|
||||
int utf8_get_sprite_offset_for_codepoint(int codepoint)
|
||||
{
|
||||
switch (codepoint) {
|
||||
case FORMAT_ENDQUOTES: return 34 - 32;
|
||||
|
||||
case FORMAT_AMINUSCULE: return 159 - 32;
|
||||
case FORMAT_UP: return 160 - 32;
|
||||
case FORMAT_SYMBOL_i: return 160 - 32;
|
||||
case FORMAT_CENT: return 162 - 32;
|
||||
case FORMAT_POUND: return 163 - 32;
|
||||
|
||||
case FORMAT_YEN: return 165 - 32;
|
||||
|
||||
|
||||
|
||||
case FORMAT_COPYRIGHT: return 169 - 32;
|
||||
case FORMAT_DOWN: return 170 - 32;
|
||||
case FORMAT_LEFTGUILLEMET: return 171 - 32;
|
||||
case FORMAT_TICK: return 172 - 32;
|
||||
case FORMAT_CROSS: return 173 - 32;
|
||||
|
||||
case FORMAT_RIGHT: return 175 - 32;
|
||||
case FORMAT_DEGREE: return 176 - 32;
|
||||
case FORMAT_SYMBOL_RAILWAY: return 177 - 32;
|
||||
case FORMAT_SQUARED: return 178 - 32;
|
||||
|
||||
case FORMAT_OPENQUOTES: return 180 - 32;
|
||||
case FORMAT_EURO: return 181 - 32;
|
||||
case FORMAT_SYMBOL_ROAD: return 182 - 32;
|
||||
case FORMAT_SYMBOL_FLAG: return 183 - 32;
|
||||
case FORMAT_APPROX: return 184 - 32;
|
||||
case FORMAT_POWERNEGATIVEONE: return 185 - 32;
|
||||
case FORMAT_BULLET: return 186 - 32;
|
||||
case FORMAT_RIGHTGUILLEMET: return 187 - 32;
|
||||
case FORMAT_SMALLUP: return 188 - 32;
|
||||
case FORMAT_SMALLDOWN: return 189 - 32;
|
||||
case FORMAT_LEFT: return 190 - 32;
|
||||
case FORMAT_INVERTEDQUESTION: return 191 - 32;
|
||||
default:
|
||||
if (codepoint < 32 || codepoint >= 256) codepoint = '?';
|
||||
return codepoint - 32;
|
||||
}
|
||||
}
|
||||
|
||||
int utf8_get_format_code_arg_length(int codepoint)
|
||||
{
|
||||
switch (codepoint) {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
bool utf8_is_format_code(int codepoint);
|
||||
bool utf8_should_use_sprite_for_codepoint(int codepoint);
|
||||
int utf8_get_sprite_offset_for_codepoint(int codepoint);
|
||||
int font_sprite_get_codepoint_offset(int codepoint);
|
||||
int utf8_get_format_code_arg_length(int codepoint);
|
||||
|
||||
void format_string(char *dest, rct_string_id format, void *args);
|
||||
|
||||
@@ -99,7 +99,7 @@ int rct2_init()
|
||||
|
||||
gfx_load_g1();
|
||||
gfx_load_g2();
|
||||
gfx_load_character_widths();
|
||||
font_sprite_initialise_characters();
|
||||
if (!gOpenRCT2Headless) {
|
||||
platform_init();
|
||||
audio_init1();
|
||||
|
||||
@@ -263,21 +263,21 @@ static void window_banner_dropdown(rct_window *w, int widgetIndex, int dropdownI
|
||||
|
||||
banner->text_colour = dropdownIndex + 1;
|
||||
|
||||
int colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;
|
||||
|
||||
// Can be replaced with a buffer 34 chars wide ( 32 character + 1 colour_format + 1 '\0')
|
||||
uint8* text_buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8);
|
||||
uint8* buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8);
|
||||
format_string(buffer, banner->string_idx, 0);
|
||||
|
||||
format_string(text_buffer, banner->string_idx, 0);
|
||||
|
||||
if (text_buffer[0] < FORMAT_COLOUR_CODE_START
|
||||
|| text_buffer[0] > FORMAT_COLOUR_CODE_END){
|
||||
int end_point = strlen(text_buffer) + 1;
|
||||
strncpy(text_buffer + 1, text_buffer, 32);
|
||||
text_buffer[end_point] = '\0';
|
||||
int firstCodepoint = utf8_get_next(buffer, NULL);
|
||||
if (!(firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END)) {
|
||||
utf8 *endPoint = get_string_end(buffer) + utf8_get_codepoint_length(colourCodepoint);
|
||||
memmove(buffer + utf8_get_codepoint_length(colourCodepoint), buffer, endPoint - buffer);
|
||||
*endPoint = 0;
|
||||
}
|
||||
utf8_write_codepoint(buffer, colourCodepoint);
|
||||
|
||||
text_buffer[0] = banner->text_colour + FORMAT_COLOUR_CODE_START;
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, text_buffer);
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId != 0) {
|
||||
rct_string_id prev_string_id = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
@@ -296,12 +296,12 @@ static void window_banner_textinput(rct_window *w, int widgetIndex, char *text)
|
||||
if (widgetIndex == WIDX_BANNER_TEXT && text != NULL) {
|
||||
rct_banner* banner = &gBanners[w->number];
|
||||
|
||||
uint8* text_buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8);
|
||||
utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8);
|
||||
utf8 *dst = buffer;
|
||||
dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour);
|
||||
strncpy(dst, text, 32);
|
||||
|
||||
text_buffer[0] = banner->text_colour + FORMAT_COLOUR_CODE_START;
|
||||
strncpy(text_buffer + 1, text, 32);
|
||||
|
||||
rct_string_id stringId = user_string_allocate(128, text_buffer);
|
||||
rct_string_id stringId = user_string_allocate(128, buffer);
|
||||
if (stringId) {
|
||||
rct_string_id prev_string_id = banner->string_idx;
|
||||
banner->string_idx = stringId;
|
||||
|
||||
@@ -118,6 +118,8 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t
|
||||
// from crashing the game.
|
||||
text_input[maxLength - 1] = '\0';
|
||||
|
||||
utf8_remove_format_codes(text_input);
|
||||
|
||||
// This is the text displayed above the input box
|
||||
input_text_description = description;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user