mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-20 05:23:04 +01:00
281 lines
8.5 KiB
C++
281 lines
8.5 KiB
C++
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
|
|
/*****************************************************************************
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
*
|
|
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
|
|
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
|
|
*
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* A full copy of the GNU General Public License can be found in licence.txt
|
|
*****************************************************************************/
|
|
#pragma endregion
|
|
|
|
#include "../core/Util.hpp"
|
|
#include "../localisation/FormatCodes.h"
|
|
#include "../localisation/Language.h"
|
|
#include "../localisation/LocalisationService.h"
|
|
#include "../sprites.h"
|
|
#include "Drawing.h"
|
|
#include "Font.h"
|
|
#include "TTF.h"
|
|
|
|
static constexpr const sint32 SpriteFontLineHeight[] = { 6, 10, 10, 18 };
|
|
|
|
static uint8 _spriteFontCharacterWidths[896];
|
|
|
|
#ifndef NO_TTF
|
|
TTFFontSetDescriptor *gCurrentTTFFontSet;
|
|
#endif // NO_TTF
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006C19AC
|
|
*/
|
|
void font_sprite_initialise_characters()
|
|
{
|
|
uint8* pCharacterWidth = _spriteFontCharacterWidths;
|
|
for (sint32 fontSize = 0; fontSize < FONT_SIZE_COUNT; fontSize++) {
|
|
sint32 glyphOffset = fontSize * FONT_SPRITE_GLYPH_COUNT;
|
|
for (uint8 glyphIndex = 0; glyphIndex < FONT_SPRITE_GLYPH_COUNT; glyphIndex++) {
|
|
const rct_g1_element * g1 = gfx_get_g1_element(glyphIndex + SPR_CHAR_START + glyphOffset);
|
|
if (g1 != nullptr)
|
|
{
|
|
sint32 width = g1->width + 2 * g1->x_offset;
|
|
width += fontSize == FONT_SIZE_BIG ? 1 : -1;
|
|
if (glyphIndex >= (FORMAT_ARGUMENT_CODE_START - 32) && glyphIndex < (FORMAT_COLOUR_CODE_END - 32)) {
|
|
width = 0;
|
|
}
|
|
*pCharacterWidth++ = (uint8)width;
|
|
}
|
|
}
|
|
}
|
|
|
|
scrolling_text_initialise_bitmaps();
|
|
}
|
|
|
|
sint32 font_sprite_get_codepoint_offset(sint32 codepoint)
|
|
{
|
|
switch (codepoint) {
|
|
case FORMAT_ENDQUOTES: return 34 - 32;
|
|
|
|
case FORMAT_UP: return 160 - 32;
|
|
case FORMAT_INVERTEDEXCLAMATION: return 161 - 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;
|
|
|
|
case UNICODE_A_OGONEK_UC: return RCT2_A_OGONEK_UC - 32;
|
|
case UNICODE_C_ACUTE_UC: return RCT2_C_ACUTE_UC - 32;
|
|
case UNICODE_E_OGONEK_UC: return RCT2_E_OGONEK_UC - 32;
|
|
case UNICODE_N_ACUTE_UC: return RCT2_N_ACUTE_UC - 32;
|
|
case UNICODE_L_STROKE_UC: return RCT2_L_STROKE_UC - 32;
|
|
case UNICODE_S_ACUTE_UC: return RCT2_S_ACUTE_UC - 32;
|
|
case UNICODE_Z_DOT_UC: return RCT2_Z_DOT_UC - 32;
|
|
case UNICODE_Z_ACUTE_UC: return RCT2_Z_ACUTE_UC - 32;
|
|
|
|
case UNICODE_A_OGONEK: return RCT2_A_OGONEK - 32;
|
|
case UNICODE_C_ACUTE: return RCT2_C_ACUTE - 32;
|
|
case UNICODE_E_OGONEK: return RCT2_E_OGONEK - 32;
|
|
case UNICODE_N_ACUTE: return RCT2_N_ACUTE - 32;
|
|
case UNICODE_L_STROKE: return RCT2_L_STROKE - 32;
|
|
case UNICODE_S_ACUTE: return RCT2_S_ACUTE - 32;
|
|
case UNICODE_Z_DOT: return RCT2_Z_DOT - 32;
|
|
case UNICODE_Z_ACUTE: return RCT2_Z_ACUTE - 32;
|
|
|
|
// Render capital sharp-S (ẞ) with lowercase sprite (ß)
|
|
case UNICODE_CAPITAL_SHARP_S: return 223 - 32;
|
|
|
|
case UNICODE_DINGBATS_PLUS: return 11;
|
|
case UNICODE_DINGBATS_MINUS: return 13;
|
|
|
|
default:
|
|
if (codepoint < 32 || codepoint >= 256) codepoint = '?';
|
|
return codepoint - 32;
|
|
}
|
|
}
|
|
|
|
sint32 font_sprite_get_codepoint_width(uint16 fontSpriteBase, sint32 codepoint)
|
|
{
|
|
if (fontSpriteBase == (uint16)FONT_SPRITE_BASE_MEDIUM_DARK ||
|
|
fontSpriteBase == (uint16)FONT_SPRITE_BASE_MEDIUM_EXTRA_DARK)
|
|
{
|
|
fontSpriteBase = (uint16)FONT_SPRITE_BASE_MEDIUM;
|
|
}
|
|
|
|
sint32 spriteFontIdx = fontSpriteBase + font_sprite_get_codepoint_offset(codepoint);
|
|
if (spriteFontIdx < 0 || spriteFontIdx >= (sint32)Util::CountOf(_spriteFontCharacterWidths))
|
|
{
|
|
log_warning("Invalid font index %u", spriteFontIdx);
|
|
spriteFontIdx = 0;
|
|
}
|
|
return _spriteFontCharacterWidths[spriteFontIdx];
|
|
}
|
|
|
|
sint32 font_sprite_get_codepoint_sprite(sint32 fontSpriteBase, sint32 codepoint)
|
|
{
|
|
return SPR_CHAR_START + (IMAGE_TYPE_REMAP | (fontSpriteBase + font_sprite_get_codepoint_offset(codepoint)));
|
|
}
|
|
|
|
sint32 font_get_size_from_sprite_base(uint16 spriteBase)
|
|
{
|
|
switch (spriteBase) {
|
|
case FONT_SPRITE_BASE_TINY:
|
|
return 0;
|
|
case FONT_SPRITE_BASE_SMALL:
|
|
return 1;
|
|
default:
|
|
case FONT_SPRITE_BASE_MEDIUM:
|
|
return 2;
|
|
case FONT_SPRITE_BASE_BIG:
|
|
return 3;
|
|
}
|
|
}
|
|
|
|
sint32 font_get_line_height(sint32 fontSpriteBase)
|
|
{
|
|
sint32 fontSize = font_get_size_from_sprite_base(fontSpriteBase);
|
|
#ifndef NO_TTF
|
|
if (LocalisationService_UseTrueTypeFont()) {
|
|
return gCurrentTTFFontSet->size[fontSize].line_height;
|
|
} else {
|
|
#endif // NO_TTF
|
|
return SpriteFontLineHeight[fontSize];
|
|
#ifndef NO_TTF
|
|
}
|
|
#endif // NO_TTF
|
|
}
|
|
|
|
sint32 font_get_line_height_small(sint32 fontSpriteBase)
|
|
{
|
|
return font_get_line_height(fontSpriteBase) / 2;
|
|
}
|
|
|
|
bool font_supports_string_sprite(const utf8 *text)
|
|
{
|
|
const utf8 *src = text;
|
|
|
|
uint32 codepoint;
|
|
while ((codepoint = utf8_get_next(src, &src)) != 0) {
|
|
bool supported = false;
|
|
switch (codepoint) {
|
|
case FORMAT_ENDQUOTES:
|
|
case FORMAT_UP:
|
|
case FORMAT_INVERTEDEXCLAMATION:
|
|
case FORMAT_POUND:
|
|
case FORMAT_YEN:
|
|
case FORMAT_COPYRIGHT:
|
|
case FORMAT_DOWN:
|
|
case FORMAT_LEFTGUILLEMET:
|
|
case FORMAT_TICK:
|
|
case FORMAT_CROSS:
|
|
case FORMAT_RIGHT:
|
|
case FORMAT_DEGREE:
|
|
case FORMAT_SYMBOL_RAILWAY:
|
|
case FORMAT_SQUARED:
|
|
case FORMAT_OPENQUOTES:
|
|
case FORMAT_EURO:
|
|
case FORMAT_SYMBOL_ROAD:
|
|
case FORMAT_SYMBOL_FLAG:
|
|
case FORMAT_APPROX:
|
|
case FORMAT_POWERNEGATIVEONE:
|
|
case FORMAT_BULLET:
|
|
case FORMAT_RIGHTGUILLEMET:
|
|
case FORMAT_SMALLUP:
|
|
case FORMAT_SMALLDOWN:
|
|
case FORMAT_LEFT:
|
|
case FORMAT_INVERTEDQUESTION:
|
|
|
|
case UNICODE_A_OGONEK_UC:
|
|
case UNICODE_C_ACUTE_UC:
|
|
case UNICODE_E_OGONEK_UC:
|
|
case UNICODE_N_ACUTE_UC:
|
|
case UNICODE_L_STROKE_UC:
|
|
case UNICODE_S_ACUTE_UC:
|
|
case UNICODE_Z_DOT_UC:
|
|
case UNICODE_Z_ACUTE_UC:
|
|
|
|
case UNICODE_A_OGONEK:
|
|
case UNICODE_C_ACUTE:
|
|
case UNICODE_E_OGONEK:
|
|
case UNICODE_N_ACUTE:
|
|
case UNICODE_L_STROKE:
|
|
case UNICODE_S_ACUTE:
|
|
case UNICODE_Z_DOT:
|
|
case UNICODE_Z_ACUTE:
|
|
|
|
supported = true;
|
|
break;
|
|
default:
|
|
if (codepoint >= 32 && codepoint < 256) {
|
|
supported = true;
|
|
}
|
|
break;
|
|
}
|
|
if (!supported) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool font_supports_string_ttf(const utf8 *text, sint32 fontSize)
|
|
{
|
|
#ifndef NO_TTF
|
|
const utf8 *src = text;
|
|
const TTF_Font *font = gCurrentTTFFontSet->size[fontSize].font;
|
|
if (font == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
uint32 codepoint;
|
|
while ((codepoint = utf8_get_next(src, &src)) != 0) {
|
|
bool supported = ttf_provides_glyph(font, codepoint);
|
|
if (!supported) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif // NO_TTF
|
|
}
|
|
|
|
bool font_supports_string(const utf8 *text, sint32 fontSize)
|
|
{
|
|
if (LocalisationService_UseTrueTypeFont()) {
|
|
return font_supports_string_ttf(text, fontSize);
|
|
} else {
|
|
return font_supports_string_sprite(text);
|
|
}
|
|
}
|