mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/LCE-Revelations.git
synced 2026-05-22 16:35:09 +00:00
Goal: Allow players to type and display text in any language supported by Unicode, including Chinese, Japanese, Korean, Thai, Arabic, Korean, Hindi, and more. This covers all text surfaces: chat editor, chat messages, signs (in-world and editor), world name/seed, server address/port fields, and all Iggy Flash UI text fields. Multi-language support: Two complementary rendering systems were added to handle Unicode text across the entire client: 1. Iggy UI (Flash-based text fields): A new UIUnicodeBitmapFont class serves Java Minecraft's glyph page PNGs (glyph_00.png-glyph_FF.png) through Iggy's bitmap font provider API. Registered as the global fallback font with metrics matching the Mojangles bitmap font for correct baseline alignment. When the primary bitmap font lacks a glyph, it returns IGGY_GLYPH_INVALID and Iggy seamlessly falls back to the unicode bitmap font. 2. Legacy C++ Font renderer (chat editor, in-world signs): Revived the commented-out unicode glyph page system in Font.cpp. Characters not in the bitmap font texture are rendered from glyph page PNGs loaded on demand, with proper texture switching mid-string. 3. ChatScreen input: Removed the restrictive acceptableLetters filter so all printable Unicode characters are accepted in chat. Languages now supported for text input and rendering: - Japanese (Hiragana, Katakana, Kanji) - Chinese (Simplified and Traditional) - Korean (Hangul) - Thai - Arabic - Hindi (Devanagari) - Russian (Cyrillic) - already worked via bitmap font - Greek - already worked via bitmap font - Polish, Czech, Turkish (Extended Latin) - already worked via bitmap font - Armenian, Georgian, and other scripts covered by glyph pages Security fixes: - Fixed memset under-initialization of Font::charWidths (zeroed 460 bytes instead of 460*sizeof(int)=1840 bytes, leaving entries 115+ uninitialized) - pre-existing bug - Added bounds checks to all UIUnicodeBitmapFont callbacks to reject glyph IDs outside [0, 65535], preventing OOB array access - Added bounds check in Font::width() section-sign fallback path to prevent OOB read on charWidths[] with high codepoints - Blocked Unicode bidirectional override characters (U+202A-202E, U+2066-2069) in chat input to prevent message spoofing Memory leak fix: - Fixed SignTileEntity::load allocating wchar_t[256] with new[] on every sign load without freeing. Replaced with stack allocation. Debug logging: - Added [SIGN] prefixed logging for sign save/update operations - Added [CHAT] prefixed logging for chat send/receive operations Files changed: - UIUnicodeBitmapFont.h/.cpp (new) - Iggy bitmap font for glyph pages - UIBitmapFont.cpp - Return IGGY_GLYPH_INVALID for unknown chars - UIFontData.h/.cpp - Added hasGlyph() method - UIController.h/.cpp - Load and register unicode bitmap fallback font - UITTFFont.h/.cpp - Added registerAsDefaultFonts parameter - Font.h/.cpp - Revived unicode glyph page rendering system - ChatScreen.cpp - Accept all Unicode input, block bidi overrides - Gui.cpp - Chat display debug logging - ClientConnection.cpp - Sign update debug logging - SignTileEntity.cpp - Sign save logging, memory leak fix
137 lines
3.3 KiB
C++
137 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <unordered_map>
|
|
|
|
using namespace std;
|
|
|
|
#define _DEBUG_BLOCK_CHARS 0
|
|
|
|
// For hardcoded font data.
|
|
struct SFontData
|
|
{
|
|
public:
|
|
static const unsigned short FONTCOLS = 23;
|
|
static const unsigned short FONTROWS = 20;
|
|
|
|
static const unsigned short FONTSIZE = FONTCOLS * FONTROWS;
|
|
|
|
public:
|
|
// Font name.
|
|
string m_strFontName;
|
|
|
|
// Filename of the glyph archive.
|
|
wstring m_wstrFilename;
|
|
|
|
// Number of glyphs in the archive.
|
|
unsigned int m_uiGlyphCount;
|
|
|
|
// Unicode values of each glyph.
|
|
unsigned short *m_arrCodepoints;
|
|
|
|
// X resolution of glyph archive.
|
|
unsigned int m_uiGlyphMapX;
|
|
|
|
// Y resolution of glyph archive.
|
|
unsigned int m_uiGlyphMapY;
|
|
|
|
// Number of columns in the glyph archive.
|
|
unsigned int m_uiGlyphMapCols;
|
|
|
|
// Number of rows in the glyph archive.
|
|
unsigned int m_uiGlyphMapRows;
|
|
|
|
// Width of each glyph.
|
|
unsigned int m_uiGlyphWidth;
|
|
|
|
// Height of each glyph.
|
|
unsigned int m_uiGlyphHeight;
|
|
|
|
// Ascent of each glyph above the baseline (units?).
|
|
float m_fAscent;
|
|
|
|
// Descent of each glyph below the baseline (units?).
|
|
float m_fDescent;
|
|
|
|
// How much to advance for each pixel wide the glyph is.
|
|
float m_fAdvPerPixel;
|
|
|
|
// How many pixels wide any whitespace characters are.
|
|
unsigned int m_uiWhitespaceWidth;
|
|
|
|
public:
|
|
static unsigned short Codepoints[FONTSIZE];
|
|
static SFontData Mojangles_7;
|
|
static SFontData Mojangles_11;
|
|
};
|
|
|
|
// Provides a common interface for dealing with font data.
|
|
class CFontData
|
|
{
|
|
public:
|
|
CFontData();
|
|
|
|
// pbRawImage consumed by constructor.
|
|
CFontData(SFontData &sFontData, int *pbRawImage);
|
|
|
|
// Release memory.
|
|
void release();
|
|
|
|
protected:
|
|
|
|
// Hardcoded font data.
|
|
SFontData *m_sFontData;
|
|
|
|
// Map Unicodepoints to glyph ids.
|
|
unordered_map<unsigned int, unsigned short> m_unicodeMap;
|
|
|
|
// Kerning value for each glyph.
|
|
unsigned short *m_kerningTable;
|
|
|
|
// Binary blob of the archive image.
|
|
unsigned char *m_pbRawImage;
|
|
|
|
// Total advance of each character.
|
|
float *m_pfAdvanceTable;
|
|
|
|
public:
|
|
|
|
// Accessor for the font name in the internal SFontData.
|
|
const string getFontName();
|
|
|
|
// Accessor for the hardcoded internal font data.
|
|
SFontData *getFontData();
|
|
|
|
// Get the glyph id corresponding to a unicode point.
|
|
unsigned short getGlyphId(unsigned int unicodepoint);
|
|
|
|
// Get the unicodepoint corresponding to a glyph id.
|
|
unsigned int getUnicode(unsigned short glyphId);
|
|
|
|
// Get a pointer to the top left pixel of a row/column in the raw image.
|
|
unsigned char *topLeftPixel(int row, int col);
|
|
|
|
// Get the row and column where a glyph appears in the archive.
|
|
void getPos(unsigned short gyphId, int &row, int &col);
|
|
|
|
// Get the advance of this character (units?).
|
|
float getAdvance(unsigned short glyphId);
|
|
|
|
// Get the width (in pixels) of a given character.
|
|
int getWidth(unsigned short glyphId);
|
|
|
|
// Returns true if this glyph is whitespace.
|
|
bool glyphIsWhitespace(unsigned short glyphId);
|
|
|
|
// Returns true if this unicodepoint is whitespace
|
|
bool unicodeIsWhitespace(unsigned int unicodepoint);
|
|
|
|
// Returns true if this unicodepoint exists in the font's glyph map.
|
|
bool hasGlyph(unsigned int unicodepoint);
|
|
|
|
private:
|
|
|
|
// Move a pointer in an image dx pixels right and dy pixels down, wrap around in either dimension leads to unknown behaviour.
|
|
void moveCursor(unsigned char *&cursor, unsigned int dx, unsigned int dy);
|
|
};
|
|
|