#include "text.h" #include "fontBig_0.h" #include "fontMedium_0.h" #include "fontSmall_0.h" #include "gfx/fontBigUVCoords.h" #include "gfx/fontMediumUVCoords.h" #include "gfx/fontSmallUVCoords.h" #include #include glImage fontBig[FONTBIG_NUM_IMAGES]; glImage fontMedium[FONTBIG_NUM_IMAGES]; glImage fontSmall[FONTSMALL_NUM_IMAGES]; int fontBigTextureId; int fontMediumTextureId; int fontSmallTextureId; struct GuiText { size_t width; size_t height; size_t posX; size_t posY; char* text; u16 color; size_t length; GuiTextHAlign hAlign; GuiTextVAlign vAlign; size_t maxWidth; size_t maxHeight; bool wrap; int textureId; glImage* font; }; void initGuiFont(void) { fontBigTextureId = glLoadSpriteSet( fontBig, FONTBIG_NUM_IMAGES, fontBigTexCoords, GL_RGB256, TEXTURE_SIZE_256, TEXTURE_SIZE_256, TEXGEN_OFF | GL_TEXTURE_COLOR0_TRANSPARENT, 256, fontBig_0Pal, (u8*)fontBig_0Bitmap); fontMediumTextureId = glLoadSpriteSet( fontMedium, FONTMEDIUM_NUM_IMAGES, fontMediumTexCoords, GL_RGB256, TEXTURE_SIZE_256, TEXTURE_SIZE_256, TEXGEN_OFF | GL_TEXTURE_COLOR0_TRANSPARENT, 256, fontMedium_0Pal, (u8*)fontMedium_0Bitmap); fontSmallTextureId = glLoadSpriteSet( fontSmall, FONTSMALL_NUM_IMAGES, fontSmallTexCoords, GL_RGB256, TEXTURE_SIZE_256, TEXTURE_SIZE_256, TEXGEN_OFF | GL_TEXTURE_COLOR0_TRANSPARENT, 256, fontSmall_0Pal, (u8*)fontSmall_0Bitmap); } GuiText newGuiText(const char* text, GuiTextSize size, u16 color) { GuiText gt = malloc(sizeof(struct GuiText)); gt->width = 0; gt->height = 0; gt->posX = 0; gt->posY = 0; gt->text = NULL; gt->color = color; gt->hAlign = GUI_TEXT_H_ALIGN_LEFT; gt->vAlign = GUI_TEXT_V_ALIGN_TOP; gt->maxWidth = 0; gt->maxHeight = 0; gt->wrap = false; switch (size) { case GUI_TEXT_SIZE_BIG: gt->textureId = fontBigTextureId; gt->font = fontBig; break; case GUI_TEXT_SIZE_MEDIUM: gt->textureId = fontMediumTextureId; gt->font = fontMedium; break; case GUI_TEXT_SIZE_SMALL: gt->textureId = fontSmallTextureId; gt->font = fontSmall; break; } setGuiTextText(gt, text); return gt; } void freeGuiText(GuiText gt) { free(gt->text); free(gt); } void updateWH(GuiText gt) { size_t x = 0; size_t y = 0; size_t lineWidth = 0; size_t lineStart = 0; size_t lastSpace = -1; for (size_t i = 0; i < gt->length; i++) { glImage currChar = gt->font[gt->text[i] - 1]; lineWidth += currChar.width + 1; if (gt->text[i] == ' ') lastSpace = i; if (gt->maxWidth && (lineWidth > gt->maxWidth || gt->text[i] == '\n')) { if (lineWidth > gt->maxWidth) { if (lastSpace != -1 && lastSpace > lineStart) { i = lastSpace; lineWidth = 0; for (size_t j = lineStart; j <= lastSpace; j++) lineWidth += gt->font[gt->text[j] - 1].width + 1; } else { lineWidth -= currChar.width + 1; i--; } } switch (gt->hAlign) { case GUI_TEXT_H_ALIGN_LEFT: x = 0; break; case GUI_TEXT_H_ALIGN_CENTER: x = 0 - lineWidth / 2; break; case GUI_TEXT_H_ALIGN_RIGHT: x = 0 - lineWidth; break; } for (size_t j = lineStart; j <= i; j++) { currChar = gt->font[gt->text[j] - 1]; if (gt->text[j] != '\n') x += currChar.width + 1; } lineStart = i + 1; lineWidth = 0; y += currChar.height + 1; lastSpace = -1; if (!gt->wrap || (gt->maxHeight && y + currChar.height > gt->maxHeight)) { gt->width = x; gt->height = y; return; } } } if (lineStart < gt->length) { switch (gt->hAlign) { case GUI_TEXT_H_ALIGN_LEFT: x = 0; break; case GUI_TEXT_H_ALIGN_CENTER: x = 0 - lineWidth / 2; break; case GUI_TEXT_H_ALIGN_RIGHT: x = 0 - lineWidth; break; } for (size_t j = lineStart; j < gt->length; j++) { glImage currChar = gt->font[gt->text[j] - 1]; x += currChar.width + 1; } } gt->width = x; gt->height = y + gt->font[0].height + 1; } void setGuiTextPos(GuiText gt, size_t posX, size_t posY) { gt->posX = posX; gt->posY = posY; } void setGuiTextText(GuiText gt, const char* text) { free(gt->text); gt->text = strdup(text); gt->length = strlen(text); updateWH(gt); } void setGuiTextAlignment(GuiText gt, GuiTextHAlign hAlignment, GuiTextVAlign vAlignment) { gt->hAlign = hAlignment; gt->vAlign = vAlignment; } void setGuiTextMaxWidth(GuiText gt, size_t maxWidth) { gt->maxWidth = maxWidth; updateWH(gt); } void setGuiTextMaxHeight(GuiText gt, size_t maxHeight) { gt->maxHeight = maxHeight; updateWH(gt); } void setGuiTextWrap(GuiText gt, bool wrap) { gt->wrap = wrap; updateWH(gt); } size_t getGuiTextWidth(GuiText gt) { return gt->width; } size_t getGuiTextHeight(GuiText gt) { return gt->height; } size_t getGuiTextPosX(GuiText gt) { return gt->posX; } size_t getGuiTextPosY(GuiText gt) { return gt->posY; } GuiTextHAlign getGuiTextHAlignment(GuiText gt) { return gt->hAlign; } GuiTextVAlign getGuiTextVAlignment(GuiText gt) { return gt->vAlign; } void drawGuiTextPos(GuiText gt, size_t posX, size_t posY) { size_t x = posX; size_t y = posY; size_t lineWidth = 0; size_t lineStart = 0; size_t lastSpace = -1; switch (gt->vAlign) { case GUI_TEXT_V_ALIGN_TOP: y = posY; break; case GUI_TEXT_V_ALIGN_MIDDLE: y = posY - gt->height / 2; break; case GUI_TEXT_V_ALIGN_BOTTOM: y = posY - gt->height; break; } size_t yStart = y; glSetActiveTexture(gt->textureId); glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_ID(1)); glColor(gt->color); for (size_t i = 0; i < gt->length; i++) { glImage currChar = gt->font[gt->text[i] - 1]; lineWidth += currChar.width + 1; if (gt->text[i] == ' ') lastSpace = i; if (gt->maxWidth && (lineWidth > gt->maxWidth || gt->text[i] == '\n')) { if (lineWidth > gt->maxWidth) { if (lastSpace != -1 && lastSpace > lineStart) { i = lastSpace; lineWidth = 0; for (size_t j = lineStart; j <= lastSpace; j++) lineWidth += gt->font[gt->text[j] - 1].width + 1; } else { lineWidth -= currChar.width + 1; i--; } } switch (gt->hAlign) { case GUI_TEXT_H_ALIGN_LEFT: x = posX; break; case GUI_TEXT_H_ALIGN_CENTER: x = posX - lineWidth / 2; break; case GUI_TEXT_H_ALIGN_RIGHT: x = posX - lineWidth; break; } for (size_t j = lineStart; j <= i; j++) { currChar = gt->font[gt->text[j] - 1]; if (gt->text[j] != '\n') { glSprite(x, y, GL_FLIP_NONE, &currChar); x += currChar.width + 1; } } lineStart = i + 1; lineWidth = 0; y += currChar.height + 1; lastSpace = -1; if (!gt->wrap || (gt->maxHeight && (y - yStart) + currChar.height > gt->maxHeight)) return; } } if (lineStart < gt->length) { switch (gt->hAlign) { case GUI_TEXT_H_ALIGN_LEFT: x = posX; break; case GUI_TEXT_H_ALIGN_CENTER: x = posX - lineWidth / 2; break; case GUI_TEXT_H_ALIGN_RIGHT: x = posX - lineWidth; break; } for (size_t j = lineStart; j < gt->length; j++) { glImage currChar = gt->font[gt->text[j] - 1]; glSprite(x, y, GL_FLIP_NONE, &currChar); x += currChar.width + 1; } } glColor(RGB15(31, 31, 31)); } void drawGuiText(GuiText gt) { drawGuiTextPos(gt, gt->posX, gt->posY); }