Merge pull request #7797 from Gymnasiast/extra-letters
Add sprite font glyphs for Æ and Ø
After Width: | Height: | Size: 242 B |
After Width: | Height: | Size: 185 B |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 205 B |
After Width: | Height: | Size: 194 B |
After Width: | Height: | Size: 171 B |
After Width: | Height: | Size: 235 B |
After Width: | Height: | Size: 179 B |
After Width: | Height: | Size: 174 B |
After Width: | Height: | Size: 210 B |
After Width: | Height: | Size: 195 B |
After Width: | Height: | Size: 171 B |
|
@ -439,5 +439,80 @@
|
|||
"path": "icons/eyedropper.png",
|
||||
"x_offset": 5,
|
||||
"y_offset": 5
|
||||
},
|
||||
{
|
||||
"path": "font/ae-uc-small.png",
|
||||
"y_offset": 0,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/ae-small.png",
|
||||
"y_offset": 2,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-uc-small.png",
|
||||
"x_offset": -1,
|
||||
"y_offset": 0,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-small.png",
|
||||
"y_offset": 2,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/ae-uc-bold.png",
|
||||
"y_offset": 0,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/ae-bold.png",
|
||||
"y_offset": 2,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-uc-bold.png",
|
||||
"x_offset": -1,
|
||||
"y_offset": -1,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-bold.png",
|
||||
"x_offset": 0,
|
||||
"y_offset": 2,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/ae-uc-tiny.png",
|
||||
"y_offset": 0,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/ae-tiny.png",
|
||||
"y_offset": 1,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-uc-tiny.png",
|
||||
"y_offset": 0,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
},
|
||||
{
|
||||
"path": "font/o-stroke-tiny.png",
|
||||
"y_offset": 1,
|
||||
"palette": "keep",
|
||||
"forceBmp": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -246,12 +246,18 @@ static bool sprite_file_export(int32_t spriteIndex, const char *outPath)
|
|||
}
|
||||
}
|
||||
|
||||
static bool sprite_file_import(const char *path, int16_t x_offset, int16_t y_offset, bool keep_palette, rct_g1_element *outElement, uint8_t **outBuffer, int *outBufferLength, int32_t mode)
|
||||
static bool sprite_file_import(const char *path, int16_t x_offset, int16_t y_offset, bool keep_palette, bool forceBmp, rct_g1_element *outElement, uint8_t **outBuffer, int *outBufferLength, int32_t mode)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto format = IMAGE_FORMAT::PNG_32;
|
||||
auto flags = ImageImporter::IMPORT_FLAGS::RLE;
|
||||
auto flags = ImageImporter::IMPORT_FLAGS::NONE;
|
||||
|
||||
if (!forceBmp)
|
||||
{
|
||||
flags = (ImageImporter::IMPORT_FLAGS)ImageImporter::IMPORT_FLAGS::RLE;
|
||||
}
|
||||
|
||||
if (keep_palette)
|
||||
{
|
||||
format = IMAGE_FORMAT::PNG;
|
||||
|
@ -464,7 +470,7 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc)
|
|||
uint8_t *buffer;
|
||||
|
||||
int32_t bufferLength;
|
||||
if (!sprite_file_import(imagePath, x_offset, y_offset, false, &spriteElement, &buffer, &bufferLength, gSpriteMode))
|
||||
if (!sprite_file_import(imagePath, x_offset, y_offset, false, false, &spriteElement, &buffer, &bufferLength, gSpriteMode))
|
||||
return -1;
|
||||
|
||||
if (!sprite_file_open(spriteFilePath)) {
|
||||
|
@ -558,6 +564,14 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc)
|
|||
}
|
||||
}
|
||||
|
||||
// Get forcebmp option, if present
|
||||
bool forceBmp = false;
|
||||
json_t* forceBmpObject = json_object_get(sprite_description, "forceBmp");
|
||||
if (palette && json_is_boolean(forceBmpObject))
|
||||
{
|
||||
forceBmp = json_boolean_value(forceBmpObject);
|
||||
}
|
||||
|
||||
// Resolve absolute sprite path
|
||||
char *imagePath = platform_get_absolute_path(json_string_value(path), directoryPath);
|
||||
|
||||
|
@ -568,7 +582,7 @@ int32_t cmdline_for_sprite(const char **argv, int32_t argc)
|
|||
if (!sprite_file_import(imagePath,
|
||||
x_offset == nullptr ? 0 : json_integer_value(x_offset),
|
||||
y_offset == nullptr ? 0 : json_integer_value(y_offset),
|
||||
keep_palette, &spriteElement, &buffer, &bufferLength, gSpriteMode))
|
||||
keep_palette, forceBmp, &spriteElement, &buffer, &bufferLength, gSpriteMode))
|
||||
{
|
||||
fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath);
|
||||
json_decref(sprite_list);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
static constexpr const int32_t SpriteFontLineHeight[FONT_SIZE_COUNT] = { 6, 10, 10 };
|
||||
|
||||
static uint8_t _spriteFontCharacterWidths[FONT_SIZE_COUNT][FONT_SPRITE_GLYPH_COUNT];
|
||||
static uint8_t _additionalSpriteFontCharacterWidth[FONT_SIZE_COUNT][SPR_G2_GLYPH_COUNT] = {};
|
||||
|
||||
#ifndef NO_TTF
|
||||
TTFFontSetDescriptor *gCurrentTTFFontSet;
|
||||
|
@ -46,6 +47,22 @@ void font_sprite_initialise_characters()
|
|||
}
|
||||
}
|
||||
|
||||
for (uint8_t fontSize : { FONT_SIZE_SMALL, FONT_SIZE_MEDIUM, FONT_SIZE_TINY })
|
||||
{
|
||||
int32_t glyphOffset = fontSize * SPR_G2_GLYPH_COUNT;
|
||||
for (int32_t glyphIndex = 0; glyphIndex < SPR_G2_GLYPH_COUNT; glyphIndex++)
|
||||
{
|
||||
const rct_g1_element * g1 = gfx_get_g1_element(glyphIndex + SPR_G2_CHAR_BEGIN + glyphOffset);
|
||||
int32_t width = 0;
|
||||
if (g1 != nullptr)
|
||||
{
|
||||
width = g1->width + (2 * g1->x_offset) - 1;
|
||||
}
|
||||
|
||||
_additionalSpriteFontCharacterWidth[fontSize][glyphIndex] = (uint8_t)width;
|
||||
}
|
||||
}
|
||||
|
||||
scrolling_text_initialise_bitmaps();
|
||||
}
|
||||
|
||||
|
@ -107,6 +124,15 @@ int32_t font_sprite_get_codepoint_offset(int32_t codepoint)
|
|||
// Render capital sharp-S (ẞ) with lowercase sprite (ß)
|
||||
case UNICODE_CAPITAL_SHARP_S: return 223 - 32;
|
||||
|
||||
case UNICODE_AE_UC:
|
||||
return SPR_G2_AE_UPPER - SPR_CHAR_START;
|
||||
case UNICODE_O_STROKE_UC:
|
||||
return SPR_G2_O_STROKE_UPPER - SPR_CHAR_START;
|
||||
case UNICODE_AE:
|
||||
return SPR_G2_AE_LOWER - SPR_CHAR_START;
|
||||
case UNICODE_O_STROKE:
|
||||
return SPR_G2_O_STROKE_LOWER - SPR_CHAR_START;
|
||||
|
||||
case UNICODE_DINGBATS_PLUS: return 11;
|
||||
case UNICODE_DINGBATS_MINUS: return 13;
|
||||
|
||||
|
@ -126,7 +152,18 @@ int32_t font_sprite_get_codepoint_width(uint16_t fontSpriteBase, int32_t codepoi
|
|||
|
||||
int32_t glyphIndex = font_sprite_get_codepoint_offset(codepoint);
|
||||
int32_t baseFontIndex = font_get_font_index_from_sprite_base(fontSpriteBase);
|
||||
if (glyphIndex < 0 || glyphIndex >= (int32_t)FONT_SPRITE_GLYPH_COUNT)
|
||||
if (glyphIndex >= FONT_SPRITE_GLYPH_COUNT)
|
||||
{
|
||||
glyphIndex = (SPR_CHAR_START + glyphIndex) - SPR_G2_CHAR_BEGIN;
|
||||
|
||||
if (glyphIndex >= (int32_t)Util::CountOf(_additionalSpriteFontCharacterWidth[baseFontIndex]))
|
||||
{
|
||||
log_warning("Invalid glyph index %u", glyphIndex);
|
||||
glyphIndex = 0;
|
||||
}
|
||||
return _additionalSpriteFontCharacterWidth[baseFontIndex][glyphIndex];
|
||||
}
|
||||
else if (glyphIndex < 0 || glyphIndex >= (int32_t)FONT_SPRITE_GLYPH_COUNT)
|
||||
{
|
||||
log_warning("Invalid glyph index %u", glyphIndex);
|
||||
glyphIndex = 0;
|
||||
|
@ -136,7 +173,13 @@ int32_t font_sprite_get_codepoint_width(uint16_t fontSpriteBase, int32_t codepoi
|
|||
|
||||
int32_t font_sprite_get_codepoint_sprite(int32_t fontSpriteBase, int32_t codepoint)
|
||||
{
|
||||
return SPR_CHAR_START + (IMAGE_TYPE_REMAP | (fontSpriteBase + font_sprite_get_codepoint_offset(codepoint)));
|
||||
auto codePointOffset = font_sprite_get_codepoint_offset(codepoint);
|
||||
if (codePointOffset > FONT_SPRITE_GLYPH_COUNT)
|
||||
{
|
||||
fontSpriteBase = font_get_font_index_from_sprite_base(fontSpriteBase) * SPR_G2_GLYPH_COUNT;
|
||||
}
|
||||
|
||||
return SPR_CHAR_START + (IMAGE_TYPE_REMAP | (fontSpriteBase + codePointOffset));
|
||||
}
|
||||
|
||||
int32_t font_get_font_index_from_sprite_base(uint16_t spriteBase)
|
||||
|
|
|
@ -34,7 +34,7 @@ assert_struct_size(rct_draw_scroll_text, 0xA12);
|
|||
#define MAX_SCROLLING_TEXT_ENTRIES 32
|
||||
|
||||
static rct_draw_scroll_text _drawScrollTextList[MAX_SCROLLING_TEXT_ENTRIES];
|
||||
static uint8_t _characterBitmaps[FONT_SPRITE_GLYPH_COUNT][8];
|
||||
static uint8_t _characterBitmaps[FONT_SPRITE_GLYPH_COUNT + SPR_G2_GLYPH_COUNT][8];
|
||||
static uint32_t _drawSCrollNextIndex = 0;
|
||||
|
||||
static void scrolling_text_set_bitmap_for_sprite(utf8 *text, int32_t scroll, uint8_t *bitmap, const int16_t *scrollPositionOffsets);
|
||||
|
@ -71,6 +71,23 @@ void scrolling_text_initialise_bitmaps()
|
|||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < SPR_G2_GLYPH_COUNT; i++) {
|
||||
memset(drawingSurface, 0, sizeof(drawingSurface));
|
||||
gfx_draw_sprite_software(&dpi, SPR_G2_CHAR_BEGIN + (FONT_SIZE_TINY * SPR_G2_GLYPH_COUNT) + i, -1, 0, 0);
|
||||
|
||||
for (int32_t x = 0; x < 8; x++) {
|
||||
uint8_t val = 0;
|
||||
for (int32_t y = 0; y < 8; y++) {
|
||||
val >>= 1;
|
||||
uint8_t pixel = dpi.bits[x + y * 8];
|
||||
if (pixel == 1 || (gTinyFontAntiAliased && pixel == 2)) {
|
||||
val |= 0x80;
|
||||
}
|
||||
}
|
||||
_characterBitmaps[FONT_SPRITE_GLYPH_COUNT + i][x] = val;
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < MAX_SCROLLING_TEXT_ENTRIES; i++)
|
||||
{
|
||||
int32_t imageId = SPR_SCROLLING_TEXT_START + i;
|
||||
|
@ -94,7 +111,15 @@ void scrolling_text_initialise_bitmaps()
|
|||
|
||||
static uint8_t *font_sprite_get_codepoint_bitmap(int32_t codepoint)
|
||||
{
|
||||
return _characterBitmaps[font_sprite_get_codepoint_offset(codepoint)];
|
||||
auto offset = font_sprite_get_codepoint_offset(codepoint);
|
||||
if (offset >= FONT_SPRITE_GLYPH_COUNT)
|
||||
{
|
||||
return _characterBitmaps[offset - (SPR_G2_CHAR_BEGIN - SPR_CHAR_START) + FONT_SPRITE_GLYPH_COUNT];
|
||||
}
|
||||
else
|
||||
{
|
||||
return _characterBitmaps[offset];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -179,6 +179,14 @@ enum UnicodeGerman
|
|||
UNICODE_CAPITAL_SHARP_S = 0x1E9E,
|
||||
};
|
||||
|
||||
enum UnicodeNorwegianDanish
|
||||
{
|
||||
UNICODE_AE_UC = 198,
|
||||
UNICODE_O_STROKE_UC = 216,
|
||||
UNICODE_AE = 230,
|
||||
UNICODE_O_STROKE = 248,
|
||||
};
|
||||
|
||||
enum UnicodeDingbats
|
||||
{
|
||||
UNICODE_DINGBATS_PLUS = 0x2795,
|
||||
|
|
|
@ -840,6 +840,16 @@ enum {
|
|||
|
||||
SPR_G2_EYEDROPPER = SPR_G2_BEGIN + 123,
|
||||
|
||||
SPR_G2_CHAR_BEGIN = SPR_G2_BEGIN + 124,
|
||||
|
||||
SPR_G2_AE_UPPER = SPR_G2_CHAR_BEGIN,
|
||||
SPR_G2_AE_LOWER = SPR_G2_CHAR_BEGIN + 1,
|
||||
SPR_G2_O_STROKE_UPPER = SPR_G2_CHAR_BEGIN + 2,
|
||||
SPR_G2_O_STROKE_LOWER = SPR_G2_CHAR_BEGIN + 3,
|
||||
|
||||
SPR_G2_CHAR_END = SPR_G2_O_STROKE_LOWER,
|
||||
SPR_G2_GLYPH_COUNT = (SPR_G2_CHAR_END - SPR_G2_CHAR_BEGIN) + 1,
|
||||
|
||||
// 0x60000, chosen because it's a round hex number
|
||||
// of the last possible range of image ID values that is large enough to fit all csg1 sprites.
|
||||
SPR_CSG_BEGIN = 393216,
|
||||
|
|