159 lines
3.8 KiB
C
159 lines
3.8 KiB
C
/**
|
|
* Copyright (c) 2025 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "rendertext.h"
|
|
#include "display/render.h"
|
|
#include "assert/assert.h"
|
|
#include "display/spritebatch/spritebatch.h"
|
|
#include "util/memory.h"
|
|
#include "util/math.h"
|
|
|
|
texture_t RENDER_TEXT_TEXTURE;
|
|
|
|
static mesh_t RENDER_TEXT_QUAD_MESH;
|
|
|
|
void renderTextInit(void) {
|
|
const int32_t cols = FONT_COLUMN_COUNT;
|
|
const int32_t rows = (FONT_TILE_COUNT + cols - 1) / cols;
|
|
const int32_t inputFontWidth = cols * FONT_TILE_WIDTH;
|
|
const int32_t inputFontHeight = rows * FONT_TILE_HEIGHT;
|
|
|
|
int32_t outputFontWidth = inputFontWidth;
|
|
int32_t outputFontHeight = inputFontHeight;
|
|
|
|
// Round up to nearest power of 2
|
|
#if PSP
|
|
outputFontWidth = mathNextPowTwo(inputFontWidth);
|
|
outputFontHeight = mathNextPowTwo(inputFontHeight);
|
|
#endif
|
|
|
|
uint8_t *pixels = (uint8_t *)memoryAllocate(
|
|
outputFontWidth * outputFontHeight *
|
|
sizeof(uint8_t)
|
|
);
|
|
|
|
// Buffer the pixels.
|
|
for(int tileIndex = 0; tileIndex < FONT_TILE_COUNT; ++tileIndex) {
|
|
const int32_t tileX = (tileIndex % FONT_COLUMN_COUNT) * FONT_TILE_WIDTH;
|
|
const int32_t tileY = (tileIndex / FONT_COLUMN_COUNT) * FONT_TILE_HEIGHT;
|
|
const uint8_t* tile = TILE_PIXEL_DATA[tileIndex];
|
|
|
|
for (int y = 0; y < FONT_TILE_HEIGHT; ++y) {
|
|
for (int x = 0; x < FONT_TILE_WIDTH; ++x) {
|
|
const int32_t pixel = (tileY + y) * outputFontWidth + (tileX + x);
|
|
const int32_t pixelOffset = pixel;
|
|
uint8_t value = tile[y * FONT_TILE_WIDTH + x];
|
|
pixels[pixel] = value ? 0xFF : 0x00; // Alpha channel
|
|
}
|
|
}
|
|
}
|
|
|
|
textureInit(
|
|
&RENDER_TEXT_TEXTURE,
|
|
outputFontWidth, outputFontHeight,
|
|
GL_ALPHA, pixels
|
|
);
|
|
memoryFree(pixels);
|
|
}
|
|
|
|
void renderTextDrawChar(
|
|
const float_t x,
|
|
const float_t y,
|
|
const char_t c,
|
|
const uint8_t r,
|
|
const uint8_t g,
|
|
const uint8_t b
|
|
) {
|
|
int32_t tileIndex = (int32_t)(c) - FONT_CHAR_START;
|
|
assertTrue(
|
|
tileIndex >= 0 && tileIndex < FONT_TILE_COUNT,
|
|
"Character is out of bounds for font tiles"
|
|
);
|
|
|
|
const float_t w = (float)RENDER_TEXT_TEXTURE.width;
|
|
const float_t h = (float)RENDER_TEXT_TEXTURE.height;
|
|
const int32_t tileX = (tileIndex % FONT_COLUMN_COUNT);
|
|
const int32_t tileY = (tileIndex / FONT_COLUMN_COUNT);
|
|
|
|
spriteBatchPush(
|
|
&RENDER_TEXT_TEXTURE,
|
|
x, y,
|
|
x + FONT_TILE_WIDTH, y + FONT_TILE_HEIGHT,
|
|
r, g, b, 0xFF,
|
|
(tileX * FONT_TILE_WIDTH) / w,
|
|
(tileY * FONT_TILE_HEIGHT) / h,
|
|
((tileX + 1) * FONT_TILE_WIDTH) / w,
|
|
((tileY + 1) * FONT_TILE_HEIGHT) / h
|
|
);
|
|
}
|
|
|
|
void renderTextDraw(
|
|
const float_t x,
|
|
const float_t y,
|
|
const char_t *text,
|
|
const uint8_t r,
|
|
const uint8_t g,
|
|
const uint8_t b
|
|
) {
|
|
assertNotNull(text, "Text cannot be NULL");
|
|
|
|
float_t posX = x;
|
|
float_t posY = y;
|
|
|
|
char_t c;
|
|
int32_t i = 0;
|
|
while((c = text[i++]) != '\0') {
|
|
if(c == '\n') {
|
|
posX = x;
|
|
posY += FONT_TILE_HEIGHT;
|
|
continue;
|
|
}
|
|
|
|
renderTextDrawChar(posX, posY, c, r, g, b);
|
|
posX += FONT_TILE_WIDTH;
|
|
}
|
|
}
|
|
|
|
void renderTextMeasure(
|
|
const char_t *text,
|
|
int32_t *outWidth,
|
|
int32_t *outHeight
|
|
) {
|
|
assertNotNull(text, "Text cannot be NULL");
|
|
assertNotNull(outWidth, "Output width pointer cannot be NULL");
|
|
assertNotNull(outHeight, "Output height pointer cannot be NULL");
|
|
|
|
int32_t width = 0;
|
|
int32_t height = FONT_TILE_HEIGHT;
|
|
int32_t lineWidth = 0;
|
|
|
|
char_t c;
|
|
int32_t i = 0;
|
|
while((c = text[i++]) != '\0') {
|
|
if(c == '\n') {
|
|
if(lineWidth > width) {
|
|
width = lineWidth;
|
|
}
|
|
lineWidth = 0;
|
|
height += FONT_TILE_HEIGHT;
|
|
continue;
|
|
}
|
|
|
|
lineWidth += FONT_TILE_WIDTH;
|
|
}
|
|
|
|
if(lineWidth > width) {
|
|
width = lineWidth;
|
|
}
|
|
|
|
*outWidth = width;
|
|
*outHeight = height;
|
|
}
|
|
|
|
void renderTextDispose(void) {
|
|
textureDispose(&RENDER_TEXT_TEXTURE);
|
|
} |