// 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(0), tileset->getTileHeight(0)) * (fontSize / this->getDefaultFontSize()) ; // 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(info->width, xy0.x); xy0.x = 0; xy0.y += tileSize.y; info->height = mathMax(info->height, xy0.y); continue; } xy0.x += tileSize.x; continue; } if(c == FONT_NEWLINE) { info->addLine(i, 0); info->width = mathMax(info->width, xy0.x); xy0.x = 0; xy0.y += tileSize.y; info->height = mathMax(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( info->width, (xy0.x - (tileSize.x * charsToBeRewound)) - (wordStart > 0 && text[wordStart - 1] == FONT_SPACE ? tileSize.x : 0) ); 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++; } } 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(info->width, xy0.x); info->height = mathMax(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 tileset->getTileHeight(0); } float_t BitmapFont::getDefaultFontSize() { return tileset->getTileHeight(0); }