Render non-ascii glyphs.

This commit is contained in:
Steve 2018-12-08 19:07:15 +00:00
parent a851ea6c01
commit 3d4d9fcf14
6 changed files with 181 additions and 46 deletions

View File

@ -0,0 +1 @@
# POfileorTBFS:handWCpygt2015-6,JwsbuGNUL3.Emj@c/"IV\RMD8+v?x;=%!AYq()'kH[]KzQX4Z79*àéí¡Çóè·úïçüºòÉÒÍÀ°æåøÆÅØ<>öÄäßÜá¿ñÁÊûâîôÈêùœÙìëęąłćżńśźŻŚŁĆÖ

View File

@ -77,6 +77,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define NUM_TEXTURE_BUCKETS 32 #define NUM_TEXTURE_BUCKETS 32
#define NUM_ATLAS_BUCKETS 64 #define NUM_ATLAS_BUCKETS 64
#define NUM_GLYPH_BUCKETS 128
#define MAX_STARS 500 #define MAX_STARS 500

View File

@ -43,6 +43,7 @@ typedef struct Tuple Tuple;
typedef struct Credit Credit; typedef struct Credit Credit;
typedef struct AtlasImage AtlasImage; typedef struct AtlasImage AtlasImage;
typedef struct Font Font; typedef struct Font Font;
typedef struct Glyph Glyph;
typedef struct { typedef struct {
int debug; int debug;
@ -544,10 +545,16 @@ struct Credit {
Credit *next; Credit *next;
}; };
struct Glyph {
char character[MAX_NAME_LENGTH];
SDL_Rect rect;
Glyph *next;
};
struct Font { struct Font {
char name[MAX_NAME_LENGTH]; char name[MAX_NAME_LENGTH];
SDL_Texture *texture; SDL_Texture *texture;
AtlasImage glyphs[128]; Glyph glyphHead[NUM_GLYPH_BUCKETS];
Font *next; Font *next;
}; };

View File

@ -46,9 +46,11 @@ char *getFileLocation(char *filename)
char *readFile(char *filename) char *readFile(char *filename)
{ {
char *buffer = 0; char *buffer;
long length; long length;
FILE *file = fopen(getFileLocation(filename), "rb"); FILE *file;
file = fopen(getFileLocation(filename), "rb");
if (file) if (file)
{ {

View File

@ -26,6 +26,10 @@ static void drawTextLines(int x, int y, int size, int align, SDL_Color color);
static void drawTextLine(int x, int y, int size, int align, SDL_Color color, const char *line); static void drawTextLine(int x, int y, int size, int align, SDL_Color color, const char *line);
void calcTextDimensions(const char *text, int size, int *w, int *h); void calcTextDimensions(const char *text, int size, int *w, int *h);
void useFont(char *name); void useFont(char *name);
static void initChars(Font *f);
static char *nextCharacter(const char *str, int *i);
static Glyph *findGlyph(char *c);
static int strlenMB(char *text);
static SDL_Color white = {255, 255, 255, 255}; static SDL_Color white = {255, 255, 255, 255};
static char drawTextBuffer[1024]; static char drawTextBuffer[1024];
@ -40,6 +44,7 @@ void initFonts(void)
fontTail = &fontHead; fontTail = &fontHead;
initFont("roboto", getFileLocation("data/fonts/Roboto-Medium.ttf")); initFont("roboto", getFileLocation("data/fonts/Roboto-Medium.ttf"));
initFont("khosrau", getFileLocation("data/fonts/Khosrau.ttf")); initFont("khosrau", getFileLocation("data/fonts/Khosrau.ttf"));
useFont("roboto"); useFont("roboto");
@ -52,8 +57,13 @@ static void initFont(char *name, char *filename)
Font *f; Font *f;
SDL_Surface *surface, *text; SDL_Surface *surface, *text;
SDL_Rect dest; SDL_Rect dest;
Glyph *g;
int i; int i;
char c[2];
f = malloc(sizeof(Font));
memset(f, 0, sizeof(Font));
initChars(f);
surface = SDL_CreateRGBSurface(0, FONT_TEXTURE_SIZE, FONT_TEXTURE_SIZE, 32, 0, 0, 0, 0xff); surface = SDL_CreateRGBSurface(0, FONT_TEXTURE_SIZE, FONT_TEXTURE_SIZE, 32, 0, 0, 0, 0xff);
@ -61,35 +71,31 @@ static void initFont(char *name, char *filename)
font = TTF_OpenFont(filename, FONT_SIZE); font = TTF_OpenFont(filename, FONT_SIZE);
f = malloc(sizeof(Font));
memset(f, 0, sizeof(Font));
dest.x = dest.y = 0; dest.x = dest.y = 0;
for (i = ' ' ; i <= 'z' ; i++) for (i = 0 ; i < NUM_GLYPH_BUCKETS ; i++)
{ {
memset(c, 0, 2); for (g = f->glyphHead[i].next ; g != NULL ; g = g->next)
sprintf(c, "%c", i);
text = TTF_RenderUTF8_Blended(font, c, white);
TTF_SizeText(font, c, &dest.w, &dest.h);
if (dest.x + dest.w >= FONT_TEXTURE_SIZE)
{ {
dest.x = 0; text = TTF_RenderUTF8_Blended(font, g->character, white);
dest.y += dest.h + 1; TTF_SizeText(font, g->character, &dest.w, &dest.h);
if (dest.x + dest.w >= FONT_TEXTURE_SIZE)
{
dest.x = 0;
dest.y += dest.h + 1;
}
SDL_BlitSurface(text, NULL, surface, &dest);
g->rect = dest;
SDL_FreeSurface(text);
dest.x += dest.w;
} }
SDL_BlitSurface(text, NULL, surface, &dest);
f->glyphs[i].rect = dest;
SDL_FreeSurface(text);
dest.x += dest.w;
} }
TTF_CloseFont(font); TTF_CloseFont(font);
@ -98,17 +104,47 @@ static void initFont(char *name, char *filename)
f->texture = texture; f->texture = texture;
for (i = 0 ; i < 128 ; i++)
{
f->glyphs[i].texture = texture;
}
strcpy(f->name, name); strcpy(f->name, name);
fontTail->next = f; fontTail->next = f;
fontTail = f; fontTail = f;
} }
static void initChars(Font *f)
{
char *characters, *character;
Glyph *g, *glyphTail;
int i, bucket;
characters = readFile("data/locale/characters.dat");
i = 0;
character = nextCharacter(characters, &i);
while (character)
{
bucket = hashcode(character) % NUM_GLYPH_BUCKETS;
glyphTail = &f->glyphHead[bucket];
/* horrible bit to look for the tail */
while (glyphTail->next)
{
glyphTail = glyphTail->next;
}
g = malloc(sizeof(Glyph));
memset(g, 0, sizeof(Glyph));
glyphTail->next = g;
glyphTail = g;
STRNCPY(g->character, character, MAX_NAME_LENGTH);
character = nextCharacter(characters, &i);
}
}
void drawText(int x, int y, int size, int align, SDL_Color color, const char *format, ...) void drawText(int x, int y, int size, int align, SDL_Color color, const char *format, ...)
{ {
va_list args; va_list args;
@ -143,7 +179,7 @@ static void drawTextLines(int x, int y, int size, int align, SDL_Color color)
memset(&line, '\0', sizeof(line)); memset(&line, '\0', sizeof(line));
memset(&token, '\0', sizeof(token)); memset(&token, '\0', sizeof(token));
len = strlen(drawTextBuffer); len = strlenMB(drawTextBuffer);
n = currentWidth = 0; n = currentWidth = 0;
@ -222,24 +258,53 @@ static void drawTextLine(int x, int y, int size, int align, SDL_Color color, con
static void drawWord(char *word, int *x, int *y, int startX) static void drawWord(char *word, int *x, int *y, int startX)
{ {
int i, c; int i;
char *character;
SDL_Rect dest; SDL_Rect dest;
Glyph *g;
for (i = 0 ; i < strlen(word) ; i++) i = 0;
character = nextCharacter(word, &i);
while (character)
{ {
c = word[i]; g = findGlyph(character);
dest.x = *x; dest.x = *x;
dest.y = *y; dest.y = *y;
dest.w = activeFont->glyphs[c].rect.w * scale; dest.w = g->rect.w * scale;
dest.h = activeFont->glyphs[c].rect.h * scale; dest.h = g->rect.h * scale;
SDL_RenderCopy(app.renderer, activeFont->texture, &activeFont->glyphs[c].rect, &dest); SDL_RenderCopy(app.renderer, activeFont->texture, &g->rect, &dest);
*x += activeFont->glyphs[c].rect.w * scale; *x += g->rect.w * scale;
character = nextCharacter(word, &i);
} }
} }
static Glyph *findGlyph(char *c)
{
Glyph *g;
int bucket;
bucket = hashcode(c) % NUM_GLYPH_BUCKETS;
for (g = activeFont->glyphHead[bucket].next ; g != NULL ; g = g->next)
{
if (strcmp(g->character, c) == 0)
{
return g;
}
}
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, "Couldn't find glyph for '%s'\n", c);
exit(1);
return NULL;
}
void useFont(char *name) void useFont(char *name)
{ {
Font *f; Font *f;
@ -256,20 +321,28 @@ void useFont(char *name)
void calcTextDimensions(const char *text, int size, int *w, int *h) void calcTextDimensions(const char *text, int size, int *w, int *h)
{ {
int i, c;
float scale; float scale;
int i;
char *character;
Glyph *g;
scale = size / (FONT_SIZE * 1.0f); scale = size / (FONT_SIZE * 1.0f);
*w = 0; *w = 0;
*h = 0; *h = 0;
for (i = 0 ; i < strlen(text) ; i++) i = 0;
{
c = text[i];
*w += activeFont->glyphs[c].rect.w * scale; character = nextCharacter(text, &i);
*h = MAX(activeFont->glyphs[c].rect.h * scale, *h);
while (character)
{
g = findGlyph(character);
*w += g->rect.w * scale;
*h = MAX(g->rect.h * scale, *h);
character = nextCharacter(text, &i);
} }
} }
@ -284,7 +357,7 @@ int getWrappedTextHeight(char *text, int size)
y = 0; y = 0;
h = 0; h = 0;
currentWidth = 0; currentWidth = 0;
len = strlen(drawTextBuffer); len = strlenMB(drawTextBuffer);
memset(word, 0, MAX_WORD_LENGTH); memset(word, 0, MAX_WORD_LENGTH);
for (i = 0 ; i < len ; i++) for (i = 0 ; i < len ; i++)
@ -311,3 +384,52 @@ int getWrappedTextHeight(char *text, int size)
return y + h; return y + h;
} }
static char *nextCharacter(const char *str, int *i)
{
static char character[MAX_NAME_LENGTH];
unsigned char bit;
int n;
memset(character, '\0', MAX_NAME_LENGTH);
n = 0;
while (1)
{
bit = (unsigned char)str[*i];
if ((bit >= ' ' && bit <= 'z') || bit >= 0xC0 || bit == '\0')
{
if (n > 0)
{
return character[0] != '\0' ? character : NULL;
}
}
character[n++] = str[*i];
*i = *i + 1;
}
}
static int strlenMB(char *text)
{
int i, n;
unsigned char bit;
n = 0;
for (i = 0 ; i < strlen(text) ; i++)
{
bit = (unsigned char)text[i];
if ((bit >= ' ' && bit <= 'z') || bit >= 0xC0)
{
n++;
}
}
return n;
}

View File

@ -31,6 +31,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_WORD_LENGTH 128 #define MAX_WORD_LENGTH 128
extern char *getFileLocation(char *filename); extern char *getFileLocation(char *filename);
extern unsigned long hashcode(const char *str);
extern char *readFile(char *filename);
extern SDL_Texture *toTexture(SDL_Surface *surface, int destroySurface); extern SDL_Texture *toTexture(SDL_Surface *surface, int destroySurface);
extern App app; extern App app;