text rendering & kerning was very broken

This commit is contained in:
Noel Berry 2020-09-21 00:36:19 -07:00
parent 484da29efb
commit 884eba85a2
3 changed files with 44 additions and 63 deletions

View File

@ -762,47 +762,37 @@ void Batch::tex(const Subtexture& sub, const Vec2& pos, const Vec2& origin, cons
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Color color) void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Color color)
{ {
str(font, text, pos, TextAlign::TopLeft, font.size(), color); str(font, text, pos, TextAlign::TopLeft, font.size, color);
} }
void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color) void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, TextAlign align, float size, Color color)
{ {
push_matrix( push_matrix(
Mat3x2::create_scale(size / font.size()) * Mat3x2::create_scale(size / font.size) *
Mat3x2::create_translation(pos) Mat3x2::create_translation(pos)
); );
Vec2 offset; Vec2 offset;
if ((align & TextAlign::Left) == TextAlign::Left) if ((align & TextAlign::Left) == TextAlign::Left)
offset.x = 0; offset.x = 0;
else if ((align & TextAlign::Right) == TextAlign::Right) else if ((align & TextAlign::Right) == TextAlign::Right)
offset.x -= font.width_of_line(text); offset.x -= font.width_of_line(text);
else else
offset.x -= font.width_of_line(text) * 0.5f; offset.x -= (int)(font.width_of_line(text) * 0.5f);
if ((align & TextAlign::Top) == TextAlign::Top) if ((align & TextAlign::Top) == TextAlign::Top)
offset.y = font.ascent() + font.descent(); offset.y = font.ascent + font.descent;
else if ((align & TextAlign::Bottom) == TextAlign::Bottom) else if ((align & TextAlign::Bottom) == TextAlign::Bottom)
offset.y = font.height() - font.height_of(text); offset.y = font.ascent + font.descent - font.height_of(text);
else else
offset.y = (font.ascent() + font.descent() + font.height() - font.height_of(text)) * 0.5f; offset.y = font.ascent + font.descent - (int)(font.height_of(text) * 0.5f);
Vec2 at;
for (int i = 0, l = text.length(); i < l; i++) for (int i = 0, l = text.length(); i < l; i++)
{ {
if (text[i] == '\n') if (text[i] == '\n')
{ {
// increment y at.x = 0;
offset.y += font.line_height(); at.y += font.line_height();
// re-align X for this line
if ((align & TextAlign::Left) == TextAlign::Left)
offset.x = 0;
else if ((align & TextAlign::Right) == TextAlign::Right)
offset.x = -font.width_of_line(text, i + 1);
else
offset.x = -font.width_of_line(text, i + 1) * 0.5f;
continue; continue;
} }
@ -813,20 +803,18 @@ void Batch::str(const SpriteFont& font, const String& text, const Vec2& pos, Tex
if (ch.subtexture.texture && ch.subtexture.texture->is_valid()) if (ch.subtexture.texture && ch.subtexture.texture->is_valid())
{ {
Vec2 at = offset + ch.offset; if (i > 0)
if (i > 0 && text[i - 1] != '\n')
{ {
// TODO: // TODO:
// This doesn't parse Unicode! // This doesn't parse Unicode!
at.x += font.get_kerning(text[i], text[i - 1]); at.x += font.get_kerning(text[i - 1], text[i]);
} }
tex(ch.subtexture, at, color); tex(ch.subtexture, at + offset + ch.offset, color);
} }
offset.x += ch.advance; at.x += ch.advance;
} }
pop_matrix(); pop_matrix();
} }

View File

@ -6,10 +6,10 @@ using namespace Blah;
SpriteFont::SpriteFont() SpriteFont::SpriteFont()
{ {
m_size = 0; size = 0;
m_ascent = 0; ascent = 0;
m_descent = 0; descent = 0;
m_line_gap = 0; line_gap = 0;
} }
const uint32_t ascii[]{ 32, 128, 0 }; const uint32_t ascii[]{ 32, 128, 0 };
@ -37,11 +37,11 @@ SpriteFont::SpriteFont(const Font& font, float size, const uint32_t* charset)
SpriteFont::SpriteFont(SpriteFont&& src) noexcept SpriteFont::SpriteFont(SpriteFont&& src) noexcept
{ {
m_name = src.m_name; name = src.name;
m_size = src.m_size; size = src.size;
m_ascent = src.m_ascent; ascent = src.ascent;
m_descent = src.m_descent; descent = src.descent;
m_line_gap = src.m_line_gap; line_gap = src.line_gap;
m_characters = std::move(src.m_characters); m_characters = std::move(src.m_characters);
m_kerning = std::move(src.m_kerning); m_kerning = std::move(src.m_kerning);
m_atlas = std::move(src.m_atlas); m_atlas = std::move(src.m_atlas);
@ -57,16 +57,16 @@ void SpriteFont::dispose()
m_atlas.dispose(); m_atlas.dispose();
m_characters.clear(); m_characters.clear();
m_kerning.clear(); m_kerning.clear();
m_name.dispose(); name.dispose();
} }
SpriteFont& SpriteFont::operator=(SpriteFont && src) noexcept SpriteFont& SpriteFont::operator=(SpriteFont && src) noexcept
{ {
m_name = src.m_name; name = src.name;
m_size = src.m_size; size = src.size;
m_ascent = src.m_ascent; ascent = src.ascent;
m_descent = src.m_descent; descent = src.descent;
m_line_gap = src.m_line_gap; line_gap = src.line_gap;
m_characters = std::move(src.m_characters); m_characters = std::move(src.m_characters);
m_kerning = std::move(src.m_kerning); m_kerning = std::move(src.m_kerning);
m_atlas = std::move(src.m_atlas); m_atlas = std::move(src.m_atlas);
@ -125,7 +125,7 @@ float SpriteFont::height_of(const String& text) const
height += line_height(); height += line_height();
} }
return height - m_line_gap; return height - line_gap;
} }
void SpriteFont::build(const char* file, float sz, const uint32_t* charset) void SpriteFont::build(const char* file, float sz, const uint32_t* charset)
@ -143,11 +143,11 @@ void SpriteFont::build(const Font& font, float size, const uint32_t* charset)
float scale = font.GetScale(size); float scale = font.GetScale(size);
m_name = font.FamilyName(); name = font.FamilyName();
m_ascent = font.Ascent() * scale; ascent = font.Ascent() * scale;
m_descent = font.Descent() * scale; descent = font.Descent() * scale;
m_line_gap = font.LineGap() * scale; line_gap = font.LineGap() * scale;
m_size = size; size = size;
Packer packer; Packer packer;
packer.spacing = 0; packer.spacing = 0;

View File

@ -20,21 +20,13 @@ namespace Blah
Vec2 offset; Vec2 offset;
}; };
private: private:
// properties
String m_name;
float m_size;
float m_ascent;
float m_descent;
float m_line_gap;
// tuple between two characters // tuple between two characters
struct Tuple { uint32_t first; uint32_t second; }; struct Tuple { uint32_t first; uint32_t second; };
struct TupleCompare struct TupleCompare
{ {
bool operator() (const Tuple& lhs, const Tuple& rhs) const bool operator() (const Tuple& lhs, const Tuple& rhs) const
{ {
return lhs.first < rhs.first && lhs.second < rhs.second; return ((uint64_t)(lhs.first) | ((uint64_t)lhs.second << 32)) < ((uint64_t)(rhs.first) | ((uint64_t)rhs.second << 32));
} }
}; };
@ -48,6 +40,12 @@ namespace Blah
public: public:
static const uint32_t* ASCII; static const uint32_t* ASCII;
String name;
float size;
float ascent;
float descent;
float line_gap;
// Note: // Note:
// charset is a list of range pairs, until a 0 terminator (ex. 32,128,0) // charset is a list of range pairs, until a 0 terminator (ex. 32,128,0)
@ -65,13 +63,8 @@ namespace Blah
SpriteFont& operator=(const SpriteFont&) = delete; SpriteFont& operator=(const SpriteFont&) = delete;
SpriteFont& operator=(SpriteFont&& src) noexcept; SpriteFont& operator=(SpriteFont&& src) noexcept;
const String& name() const { return m_name; } float height() const { return ascent - descent; }
float size() const { return m_size; } float line_height() const { return ascent - descent + line_gap; }
float ascent() const { return m_ascent; }
float descent() const { return m_descent; }
float line_gap() const { return m_line_gap; }
float height() const { return m_ascent - m_descent; }
float line_height() const { return m_ascent - m_descent + m_line_gap; }
List<TextureRef>& textures() { return m_atlas; } List<TextureRef>& textures() { return m_atlas; }