|
|
|
@ -4,13 +4,18 @@
|
|
|
|
|
* SPDX-License-Identifier: MIT |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include <array> // std::array |
|
|
|
|
#include <charconv> // std;:from_chars |
|
|
|
|
#include <cstdint> // int32_t, uint32_t |
|
|
|
|
#include <limits> // std::numeric_limits |
|
|
|
|
#include <string> // std::getline, std::stoi |
|
|
|
|
#include <ranges> // std::views::split |
|
|
|
|
#include <string> // std::getline |
|
|
|
|
#include <utility> // std::move |
|
|
|
|
|
|
|
|
|
#include "ruc/file.h" |
|
|
|
|
#include "ruc/format/log.h" |
|
|
|
|
#include "ruc/meta/assert.h" |
|
|
|
|
#include "ruc/meta/concepts.h" |
|
|
|
|
|
|
|
|
|
#include "inferno/render/font.h" |
|
|
|
|
#include "inferno/render/texture.h" |
|
|
|
@ -30,43 +35,96 @@ Font::Font(const std::string& name)
|
|
|
|
|
m_texture = std::make_shared<Texture>(image); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: Move this to ruc
|
|
|
|
|
template<Integral T> |
|
|
|
|
static T convert(std::string_view value) |
|
|
|
|
{ |
|
|
|
|
T tmp; |
|
|
|
|
std::from_chars(value.data(), value.data() + value.size(), tmp); |
|
|
|
|
return tmp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Font::parseFont(const std::string& font) |
|
|
|
|
{ |
|
|
|
|
std::istringstream iss(font); |
|
|
|
|
for (std::string line; std::getline(iss, line);) { |
|
|
|
|
std::string action = findAction(line); |
|
|
|
|
const std::vector<std::string> columns = findColumns(line); |
|
|
|
|
|
|
|
|
|
// Info
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
if (findAction(line).compare("info") != 0 && findAction(line).compare("char") != 0) { |
|
|
|
|
if (action.compare("info") == 0) { |
|
|
|
|
m_size = convert<uint32_t>(findValue("size", columns)); |
|
|
|
|
auto paddings = findValue("padding", columns) | std::views::split(','); |
|
|
|
|
size_t i = 0; |
|
|
|
|
for (const auto& padding : paddings) { |
|
|
|
|
// top, right, bottom, left
|
|
|
|
|
m_padding[i++] = convert<uint32_t>(padding.data()) - PADDING; |
|
|
|
|
} |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const std::vector<std::string> columns = findColumns(line); |
|
|
|
|
|
|
|
|
|
// Info
|
|
|
|
|
// Common
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
if (findAction(line).compare("info") == 0) { |
|
|
|
|
m_size = std::stou(findValue("size", columns)); |
|
|
|
|
if (action.compare("common") == 0) { |
|
|
|
|
m_lineSpacing = convert<uint32_t>(findValue("lineHeight", columns)) - m_padding[Padding::Top] - m_padding[Padding::Bottom]; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Character
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
unsigned char id = std::stoi(findValue("id", columns)); |
|
|
|
|
if (action.compare("char") == 0) { |
|
|
|
|
unsigned char id = convert<unsigned char>(findValue("id", columns)); |
|
|
|
|
uint32_t width = convert<uint32_t>(findValue("width", columns)); |
|
|
|
|
uint32_t height = convert<uint32_t>(findValue("height", columns)); |
|
|
|
|
Character character = { |
|
|
|
|
{ std::stou(findValue("x", columns)), std::stou(findValue("y", columns)) }, |
|
|
|
|
{ std::stou(findValue("width", columns)), std::stou(findValue("height", columns)) }, |
|
|
|
|
{ std::stoi(findValue("xoffset", columns)), std::stoi(findValue("yoffset", columns)) }, |
|
|
|
|
std::stou(findValue("xadvance", columns)) |
|
|
|
|
.position = { |
|
|
|
|
convert<uint32_t>(findValue("x", columns)) + m_padding[Padding::Left], |
|
|
|
|
convert<uint32_t>(findValue("y", columns)) + m_padding[Padding::Top], |
|
|
|
|
}, |
|
|
|
|
.size = { |
|
|
|
|
width == 0 ? 0 : width - m_padding[Padding::Left] - m_padding[Padding::Right], |
|
|
|
|
height == 0 ? 0 : height - m_padding[Padding::Top] - m_padding[Padding::Bottom], |
|
|
|
|
}, |
|
|
|
|
.offset = { |
|
|
|
|
convert<int32_t>(findValue("xoffset", columns)) + m_padding[Padding::Left], |
|
|
|
|
convert<int32_t>(findValue("yoffset", columns)) + m_padding[Padding::Top], |
|
|
|
|
}, |
|
|
|
|
.advance = convert<uint32_t>(findValue("xadvance", columns)) - m_padding[Padding::Left] - m_padding[Padding::Right] |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
m_characterList.emplace(id, std::make_shared<Character>(character)); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Kerning
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
if (action.compare("kerning") == 0) { |
|
|
|
|
unsigned char first = convert<unsigned char>(findValue("first", columns)); |
|
|
|
|
unsigned char second = convert<unsigned char>(findValue("second", columns)); |
|
|
|
|
char amount = convert<char>(findValue("amount", columns)); |
|
|
|
|
|
|
|
|
|
// Add the kerning of the previous character to this character
|
|
|
|
|
if (m_characterList.find(second) != m_characterList.end()) { |
|
|
|
|
auto character = m_characterList.at(second); |
|
|
|
|
character->kernings.emplace(first, amount); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const std::string Font::findAction(const std::string& line) |
|
|
|
|
std::string Font::findAction(const std::string& line) const |
|
|
|
|
{ |
|
|
|
|
return line.substr(0, line.find(" ")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const std::vector<std::string> Font::findColumns(const std::string& line) |
|
|
|
|
std::vector<std::string> Font::findColumns(const std::string& line) const |
|
|
|
|
{ |
|
|
|
|
std::vector<std::string> elements; |
|
|
|
|
|
|
|
|
@ -93,7 +151,7 @@ const std::vector<std::string> Font::findColumns(const std::string& line)
|
|
|
|
|
return elements; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const std::string Font::findValue(const std::string& key, const std::vector<std::string>& columns) |
|
|
|
|
std::string Font::findValue(const std::string& key, const std::vector<std::string>& columns) const |
|
|
|
|
{ |
|
|
|
|
size_t find = 0; |
|
|
|
|
// Loop over columns
|
|
|
|
|