Dawn/src/dawn/display/font/BitmapFont.cpp

146 lines
3.5 KiB
C++

// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "BitmapFont.hpp"
using namespace Dawn;
void BitmapFont::buffer(
std::string text,
float_t fontSize,
float_t maxWidth,
Mesh *mesh,
struct FontMeasure *info
) {
assertNotNull(mesh);
assertNotNull(info);
assertTrue(maxWidth == -1 || maxWidth > 0);
assertTrue(this->isReady());
// Initialize primitive
mesh->createBuffers(
QUAD_VERTICE_COUNT * text.size(),
QUAD_INDICE_COUNT * text.size()
);
// Setup Scales
info->length = 0;
info->realLength = 0;
info->lines.clear();
info->lineHeight = this->getLineHeight(fontSize);
// Prepare the line counters
info->addLine(0, 0);
// Reset Dimensions
char c;
Tile tile;
info->width = info->height = 0;
float_t x = 0;
float_t y = 0;
size_t i = 0;
size_t j = 0;
size_t wordStart = 0;
glm::vec2 xy0(0, 0);
glm::vec2 tileSize = glm::vec2(tileset->getTileWidth(), tileset->getTileHeight());
// Buffer quads
while(c = text[i++]) {
if(c == FONT_SPACE) {
wordStart = i;
// Did this space cause a newline?
if(maxWidth != -1 && xy0.x > maxWidth) {
info->addLine(i, 0);
info->width = mathMax<float_t>(info->width, xy0.x);
xy0.x = 0;
xy0.y += tileSize.y;
info->height = mathMax<float_t>(info->height, xy0.y);
continue;
}
xy0.x += tileSize.x;
continue;
}
if(c == FONT_NEWLINE) {
info->addLine(i, 0);
info->width = mathMax<float_t>(info->width, xy0.x);
xy0.x = 0;
xy0.y += tileSize.y;
info->height = mathMax<float_t>(info->height, xy0.y);
wordStart = i;
continue;
}
// Check for wrapping, todo.
if(maxWidth != -1 && (xy0.x+tileSize.x) > maxWidth) {
// We've exceeded the edge on THIS character. We first need to go back to
// the start of the word and push it to the new line
size_t charsToBeRewound = ((i - 1) - wordStart);
info->width = mathMax<float_t>(info->width, xy0.x - (tileSize.x * charsToBeRewound));
xy0.x = 0;
xy0.y += tileSize.y;
j -= charsToBeRewound;// Rewind j back to wordStart.
for(auto k = wordStart; k < (i-1); k++) {
char c2 = text[k];
tile = this->tileset->getTile(c2);
QuadMesh::bufferQuadMesh(mesh,
xy0, tile.uv0,
xy0+tileSize, tile.uv1,
j * QUAD_VERTICE_COUNT, j * QUAD_INDICE_COUNT
);
xy0.x += tileSize.x;
j++;
}
// Next line begins with this word
}
tile = this->tileset->getTile(c);
QuadMesh::bufferQuadMesh(mesh,
xy0, tile.uv0,
xy0+tileSize, tile.uv1,
j * QUAD_VERTICE_COUNT, j * QUAD_INDICE_COUNT
);
xy0.x += tileSize.x;
j++;
}
info->width = mathMax<float_t>(info->width, xy0.x);
info->height = mathMax<float_t>(info->height, xy0.y + (xy0.x > 0 ? tileSize.y : 0));
}
bool_t BitmapFont::isReady() {
if(this->texture == nullptr) return false;
if(this->tileset == nullptr) return false;
return this->texture->isReady();
}
Texture * BitmapFont::getTexture() {
return this->texture;
}
void BitmapFont::draw(Mesh *mesh, int32_t start, int32_t len) {
assertNotNull(mesh);
mesh->draw(
MESH_DRAW_MODE_TRIANGLES,
start * QUAD_INDICE_COUNT,
len == -1 ? len : len * QUAD_INDICE_COUNT
);
}
float_t BitmapFont::getLineHeight(float_t fontSize) {
return 16.0f;
}
float_t BitmapFont::getDefaultFontSize() {
return 16.0f;
}