diff --git a/src/system/text.c b/src/system/text.c index 4d60fbb..c428134 100644 --- a/src/system/text.c +++ b/src/system/text.c @@ -40,11 +40,11 @@ void initFonts(void) { memset(&fontHead, 0, sizeof(Font)); fontTail = &fontHead; - + initFont("roboto", getFileLocation("data/fonts/Roboto-Medium.ttf")); - + initFont("khosrau", getFileLocation("data/fonts/Khosrau.ttf")); - + useFont("roboto"); } @@ -58,59 +58,59 @@ static void initFont(char *name, char *filename) Glyph *g; int i; SDL_Color white = {255, 255, 255, 255}; - + f = malloc(sizeof(Font)); memset(f, 0, sizeof(Font)); - + font = TTF_OpenFont(filename, FONT_SIZE); - + initChars(f); - + surface = SDL_CreateRGBSurface(0, FONT_TEXTURE_SIZE, FONT_TEXTURE_SIZE, 32, 0, 0, 0, 0xff); - + SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGBA(surface->format, 0, 0, 0, 0)); - + dest.x = dest.y = 0; - + for (i = 0 ; i < NUM_GLYPH_BUCKETS ; i++) { for (g = f->glyphHead[i].next ; g != NULL ; g = g->next) { text = TTF_RenderUTF8_Blended(font, g->character, white); - + 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; - + if (dest.y + dest.h >= FONT_TEXTURE_SIZE) { SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, "Out of glyph space in %dx%d font atlas texture map.", FONT_TEXTURE_SIZE, FONT_TEXTURE_SIZE); exit(1); } } - + SDL_BlitSurface(text, NULL, surface, &dest); - + g->rect = dest; - + SDL_FreeSurface(text); - + dest.x += dest.w; } } - + TTF_CloseFont(font); - + texture = toTexture(surface, 1); - + f->texture = texture; - + strcpy(f->name, name); - + fontTail->next = f; fontTail = f; } @@ -120,17 +120,17 @@ 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 */ @@ -138,35 +138,35 @@ static void initChars(Font *f) { 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); } - + free(characters); } void drawText(int x, int y, int size, int align, SDL_Color color, const char *format, ...) { va_list args; - + if (activeFont) { SDL_SetTextureColorMod(activeFont->texture, color.r, color.g, color.b); SDL_SetTextureAlphaMod(activeFont->texture, color.a); - + memset(&drawTextBuffer, '\0', sizeof(drawTextBuffer)); va_start(args, format); vsprintf(drawTextBuffer, format, args); va_end(args); - + if (app.textWidth == 0) { drawTextLine(x, y, size, align, drawTextBuffer); @@ -182,43 +182,43 @@ static void drawTextLines(int x, int y, int size, int align) { char line[MAX_LINE_LENGTH], token[MAX_WORD_LENGTH]; int i, n, w, h, currentWidth, len; - + memset(&line, '\0', sizeof(line)); memset(&token, '\0', sizeof(token)); - + len = strlen(drawTextBuffer); - + n = currentWidth = 0; - + for (i = 0 ; i < len ; i++) { token[n++] = drawTextBuffer[i]; - + if (drawTextBuffer[i] == ' ' || i == len - 1) { calcTextDimensions(token, size, &w, &h); - + if (currentWidth + w > app.textWidth) { drawTextLine(x, y, size, align, line); - + currentWidth = 0; - + y += h; - + memset(&line, '\0', sizeof(line)); } - + strcat(line, token); - + n = 0; - + memset(&token, '\0', sizeof(token)); - + currentWidth += w; } } - + drawTextLine(x, y, size, align, line); } @@ -226,17 +226,17 @@ static void drawTextLine(int x, int y, int size, int align, const char *line) { int i, startX, n, w, h; char word[MAX_WORD_LENGTH]; - + scale = size / (FONT_SIZE * 1.0f); - + startX = x; - + memset(word, 0, MAX_WORD_LENGTH); - + n = 0; - + calcTextDimensions(line, size, &w, &h); - + if (align == TA_RIGHT) { x -= w; @@ -245,21 +245,21 @@ static void drawTextLine(int x, int y, int size, int align, const char *line) { x -= (w / 2); } - + for (i = 0 ; i < strlen(line) ; i++) { word[n++] = line[i]; - + if (line[i] == ' ') { drawWord(word, &x, &y, startX); - + memset(word, 0, MAX_WORD_LENGTH); - + n = 0; } } - + drawWord(word, &x, &y, startX); } @@ -269,24 +269,24 @@ static void drawWord(char *word, int *x, int *y, int startX) char *character; SDL_Rect dest; Glyph *g; - + i = 0; - + character = nextCharacter(word, &i); - + while (character) { g = findGlyph(character); - + dest.x = *x; dest.y = *y; dest.w = g->rect.w * scale; dest.h = g->rect.h * scale; - + SDL_RenderCopy(app.renderer, activeFont->texture, &g->rect, &dest); - + *x += g->rect.w * scale; - + character = nextCharacter(word, &i); } } @@ -295,9 +295,9 @@ 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) @@ -305,17 +305,17 @@ static Glyph *findGlyph(char *c) return g; } } - + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_CRITICAL, "Couldn't find glyph for '%s'", c); exit(1); - + return NULL; } void useFont(char *name) { Font *f; - + for (f = fontHead.next ; f != NULL ; f = f->next) { if (strcmp(f->name, name) == 0) @@ -332,23 +332,23 @@ void calcTextDimensions(const char *text, int size, int *w, int *h) int i; char *character; Glyph *g; - + scale = size / (FONT_SIZE * 1.0f); - + *w = 0; *h = 0; - + i = 0; - + character = nextCharacter(text, &i); - + while (character) { g = findGlyph(character); - + *w += g->rect.w * scale; *h = MAX(g->rect.h * scale, *h); - + character = nextCharacter(text, &i); } } @@ -357,66 +357,87 @@ int getWrappedTextHeight(char *text, int size) { char word[MAX_WORD_LENGTH]; int i, y, n, w, h, currentWidth, len; - + STRNCPY(drawTextBuffer, text, MAX_LINE_LENGTH); - + n = 0; y = 0; h = 0; currentWidth = 0; len = strlen(drawTextBuffer); memset(word, 0, MAX_WORD_LENGTH); - + for (i = 0 ; i < len ; i++) { word[n++] = drawTextBuffer[i]; - + if (drawTextBuffer[i] == ' ' || i == len - 1) { calcTextDimensions(word, size, &w, &h); - + if (currentWidth + w > app.textWidth) { currentWidth = 0; y += h; } - + currentWidth += w; - + memset(word, 0, MAX_WORD_LENGTH); - + n = 0; } } - + return y + h; } static char *nextCharacter(const char *str, int *i) { static char character[MAX_NAME_LENGTH]; - + unsigned char bit; - int n; - + int n, numBits; + memset(character, '\0', MAX_NAME_LENGTH); - - n = 0; - - while (1) + + bit = (unsigned char)str[*i]; + + numBits = 0; + + if (bit == '\0') { - bit = (unsigned char)str[*i]; - - if ((bit >= ' ' && bit <= '~') || bit >= 0xC0 || bit == '\0') - { - if (n > 0) - { - return character[0] != '\0' ? character : NULL; - } - } - - character[n++] = str[*i]; - - *i = *i + 1; + return NULL; } + else if (bit <= 0x0000007F) + { + numBits = 1; + } + else if (bit <= 0x000007FF) + { + numBits = 2; + } + else if (bit <= 0x0000FFFF) + { + numBits = 3; + } + else if (bit <= 0x001FFFFF) + { + numBits = 4; + } + else if (bit <= 0x03FFFFFF) + { + numBits = 5; + } + else if (bit <= 0x7FFFFFFF) + { + numBits = 6; + } + + for (n = 0 ; n < numBits ; n++) + { + character[n] = str[(*i)++]; + } + + return character; }