Load plain font.png beyond U+007F

VVVVVV 2.2 only supported displaying characters 00-7F with its font
system. VVVVVV 2.3 added support for unicode, by supplying a font.txt
with all the characters that are in the font image. But 2.3 made
another change that I didn't immediately realize, even after reading
the code: if font.txt is not present, then the font is not assumed to
have _only_ 00-7F, but _all_ of unicode, as far as the image dimensions
allow.

However, an inconsistency I _did_ notice is how unknown characters
would be rendered in 2.3. If a font had a font.txt, then any unknown
characters would be shown as a '?'. If a font had no font.txt however,
then suddenly any unknown characters would just come out as a space.
I fixed this behavior with the new font system; but what was actually
happening for characters to come out blank is that characters up to
U+00FF, which _were_ technically in the font image but as fully
transparent, would be shown as they were in the image, and characters
beyond U+00FF wouldn't be shown since they were outside of the image.

I don't really want to show blank characters for any character between
80-FF if it is technically inside the image, because pretty much every
single ASCII-only font.png in existence (including the one in data.zip)
contains a blank lower half, just because the font in the game had
always had this specific resolution. (We didn't want to do things that
might crash the game because something was different from what it
expected...)

We have had some confusing occasions before with the old behavior where
the fonts weren't correctly packaged or something (like when the
Catalan translator was sent the first version of the translator pack,
or when people customize their fonts wrong) and special characters were
just blank spaces.

So, instead, for characters beyond 7F, I decided to consider them part
of the font, as long as they are not blank. That means, if a character
beyond the ASCII range has any (non-alpha-0) pixels, then it will be
added, otherwise it won't be. This is just to handle legacy fonts, and
the case where all fonts are missing and the one from data.zip is used;
new fonts should just use .fontmeta or .txt to define their characters.
This commit is contained in:
Dav999 2023-12-07 18:02:43 +01:00 committed by Misa Elizabeth Kai
parent c2ad3d3b97
commit abf12632bb
1 changed files with 42 additions and 3 deletions

View File

@ -21,6 +21,7 @@ extern "C"
// Sigh... This is the second forward-declaration, we need to put this in a header file
SDL_Texture* LoadImage(const char *filename, TextureLoadType loadtype);
SDL_Surface* LoadImageSurface(const char* filename);
namespace font
{
@ -396,10 +397,48 @@ static uint8_t load_font(FontContainer* container, const char* name)
if (!charset_loaded)
{
/* If we don't have font.txt and no <chars> tag either,
* this font is 2.2-and-below-style plain ASCII. */
for (uint32_t codepoint = 0x00; codepoint < 0x80; codepoint++)
* this font is 2.2-and-below-style plain ASCII.
* Or well... 2.3 interpreted these as
* "all unicode from 0 to however much is in the image"... */
SDL_Surface* temp_surface = LoadImageSurface(name_png);
if (temp_surface != NULL)
{
add_glyphinfo(f, codepoint, codepoint);
const uint32_t chars_per_line = temp_surface->w / f->glyph_w;
const uint32_t max_codepoint = (temp_surface->h / f->glyph_h) * chars_per_line;
for (uint32_t codepoint = 0x00; codepoint <= max_codepoint; codepoint++)
{
if (codepoint > 0x7F)
{
/* Only include characters with actual pixels...
* If the font.png is too big (normally it is) we _want_ question marks. */
const int glyph_x = (codepoint % chars_per_line) * f->glyph_w;
const int glyph_y = (codepoint / chars_per_line) * f->glyph_h;
bool found_pixel = false;
for (int pixel_y = 0; pixel_y < f->glyph_h; pixel_y++)
{
for (int pixel_x = 0; pixel_x < f->glyph_w; pixel_x++)
{
if (ReadPixel(temp_surface, glyph_x+pixel_x, glyph_y+pixel_y).a > 0)
{
found_pixel = true;
goto no_more_pixels;
}
}
}
no_more_pixels:
if (!found_pixel)
{
// Do not add it
continue;
}
}
add_glyphinfo(f, codepoint, codepoint);
}
VVV_freefunc(SDL_FreeSurface, temp_surface);
}
}