mirror of
https://github.com/love2d/love.git
synced 2026-08-18 11:44:15 +02:00
Move most of Text and Video love.graphics classes out of the opengl subfolder.
--HG-- branch : minor
This commit is contained in:
@@ -19,12 +19,9 @@
|
||||
**/
|
||||
|
||||
#include "Text.h"
|
||||
#include "common/Matrix.h"
|
||||
#include "graphics/Graphics.h"
|
||||
#include "OpenGL.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
@@ -32,174 +29,13 @@ namespace graphics
|
||||
namespace opengl
|
||||
{
|
||||
|
||||
love::Type Text::type("Text", &Drawable::type);
|
||||
|
||||
Text::Text(love::graphics::Graphics *gfx, love::graphics::Font *font, const std::vector<Font::ColoredString> &text)
|
||||
: font(font)
|
||||
, vbo(nullptr)
|
||||
, quadIndices(gfx, 20)
|
||||
, vert_offset(0)
|
||||
, texture_cache_id((uint32) -1)
|
||||
: love::graphics::Text(gfx, font, text)
|
||||
{
|
||||
set(text);
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
delete vbo;
|
||||
}
|
||||
|
||||
void Text::uploadVertices(const std::vector<Font::GlyphVertex> &vertices, size_t vertoffset)
|
||||
{
|
||||
size_t offset = vertoffset * sizeof(Font::GlyphVertex);
|
||||
size_t datasize = vertices.size() * sizeof(Font::GlyphVertex);
|
||||
uint8 *vbodata = nullptr;
|
||||
|
||||
// If we haven't created a VBO or the vertices are too big, make a new one.
|
||||
if (datasize > 0 && (!vbo || (offset + datasize) > vbo->getSize()))
|
||||
{
|
||||
// Make it bigger than necessary to reduce potential future allocations.
|
||||
size_t newsize = size_t((offset + datasize) * 1.5);
|
||||
|
||||
if (vbo != nullptr)
|
||||
newsize = std::max(size_t(vbo->getSize() * 1.5), newsize);
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
Buffer *new_vbo = gfx->newBuffer(newsize, nullptr, BUFFER_VERTEX, vertex::USAGE_DYNAMIC, 0);
|
||||
|
||||
if (vbo != nullptr)
|
||||
vbo->copyTo(0, vbo->getSize(), new_vbo, 0);
|
||||
|
||||
delete vbo;
|
||||
vbo = new_vbo;
|
||||
}
|
||||
|
||||
if (vbo != nullptr && datasize > 0)
|
||||
{
|
||||
vbodata = (uint8 *) vbo->map();
|
||||
memcpy(vbodata + offset, &vertices[0], datasize);
|
||||
// We unmap when we draw, to avoid unnecessary full map()/unmap() calls.
|
||||
}
|
||||
}
|
||||
|
||||
void Text::regenerateVertices()
|
||||
{
|
||||
// If the font's texture cache was invalidated then we need to recreate the
|
||||
// text's vertices, since glyph texcoords might have changed.
|
||||
if (font->getTextureCacheID() != texture_cache_id)
|
||||
{
|
||||
std::vector<TextData> textdata = text_data;
|
||||
|
||||
clear();
|
||||
|
||||
for (const TextData &t : textdata)
|
||||
addTextData(t);
|
||||
|
||||
texture_cache_id = font->getTextureCacheID();
|
||||
}
|
||||
}
|
||||
|
||||
void Text::addTextData(const TextData &t)
|
||||
{
|
||||
std::vector<Font::GlyphVertex> vertices;
|
||||
std::vector<Font::DrawCommand> new_commands;
|
||||
|
||||
Font::TextInfo text_info;
|
||||
|
||||
Colorf constantcolor = Colorf(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// We only have formatted text if the align mode is valid.
|
||||
if (t.align == Font::ALIGN_MAX_ENUM)
|
||||
new_commands = font->generateVertices(t.codepoints, constantcolor, vertices, 0.0f, Vector(0.0f, 0.0f), &text_info);
|
||||
else
|
||||
new_commands = font->generateVerticesFormatted(t.codepoints, constantcolor, t.wrap, t.align, vertices, &text_info);
|
||||
|
||||
if (t.use_matrix)
|
||||
t.matrix.transform(&vertices[0], &vertices[0], (int) vertices.size());
|
||||
|
||||
size_t voffset = vert_offset;
|
||||
|
||||
if (!t.append_vertices)
|
||||
{
|
||||
voffset = 0;
|
||||
draw_commands.clear();
|
||||
text_data.clear();
|
||||
}
|
||||
|
||||
uploadVertices(vertices, voffset);
|
||||
|
||||
if (!new_commands.empty())
|
||||
{
|
||||
// The start vertex should be adjusted to account for the vertex offset.
|
||||
for (Font::DrawCommand &cmd : new_commands)
|
||||
cmd.startvertex += (int) voffset;
|
||||
|
||||
auto firstcmd = new_commands.begin();
|
||||
|
||||
// If the first draw command in the new list has the same texture as the
|
||||
// last one in the existing list we're building and its vertices are
|
||||
// in-order, we can combine them (saving a draw call.)
|
||||
if (!draw_commands.empty())
|
||||
{
|
||||
auto prevcmd = draw_commands.back();
|
||||
if (prevcmd.texture == firstcmd->texture && (prevcmd.startvertex + prevcmd.vertexcount) == firstcmd->startvertex)
|
||||
{
|
||||
draw_commands.back().vertexcount += firstcmd->vertexcount;
|
||||
++firstcmd;
|
||||
}
|
||||
}
|
||||
|
||||
// Append the new draw commands to the list we're building.
|
||||
draw_commands.insert(draw_commands.end(), firstcmd, new_commands.end());
|
||||
}
|
||||
|
||||
vert_offset = voffset + vertices.size();
|
||||
|
||||
text_data.push_back(t);
|
||||
text_data.back().text_info = text_info;
|
||||
|
||||
// Font::generateVertices can invalidate the font's texture cache.
|
||||
if (font->getTextureCacheID() != texture_cache_id)
|
||||
regenerateVertices();
|
||||
}
|
||||
|
||||
void Text::set(const std::vector<Font::ColoredString> &text)
|
||||
{
|
||||
return set(text, -1.0f, Font::ALIGN_MAX_ENUM);
|
||||
}
|
||||
|
||||
void Text::set(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align)
|
||||
{
|
||||
if (text.empty() || (text.size() == 1 && text[0].str.empty()))
|
||||
return clear();
|
||||
|
||||
Font::ColoredCodepoints codepoints;
|
||||
Font::getCodepointsFromString(text, codepoints);
|
||||
|
||||
addTextData({codepoints, wrap, align, {}, false, false, Matrix4()});
|
||||
}
|
||||
|
||||
int Text::add(const std::vector<Font::ColoredString> &text, const Matrix4 &m)
|
||||
{
|
||||
return addf(text, -1.0f, Font::ALIGN_MAX_ENUM, m);
|
||||
}
|
||||
|
||||
int Text::addf(const std::vector<Font::ColoredString> &text, float wrap, Font::AlignMode align, const Matrix4 &m)
|
||||
{
|
||||
Font::ColoredCodepoints codepoints;
|
||||
Font::getCodepointsFromString(text, codepoints);
|
||||
|
||||
addTextData({codepoints, wrap, align, {}, true, true, m});
|
||||
|
||||
return (int) text_data.size() - 1;
|
||||
}
|
||||
|
||||
void Text::clear()
|
||||
{
|
||||
text_data.clear();
|
||||
draw_commands.clear();
|
||||
texture_cache_id = font->getTextureCacheID();
|
||||
vert_offset = 0;
|
||||
}
|
||||
|
||||
void Text::draw(Graphics *gfx, const Matrix4 &m)
|
||||
@@ -260,43 +96,6 @@ void Text::draw(Graphics *gfx, const Matrix4 &m)
|
||||
}
|
||||
}
|
||||
|
||||
void Text::setFont(love::graphics::Font *f)
|
||||
{
|
||||
font.set(f);
|
||||
|
||||
// Invalidate the texture cache ID since the font is different. We also have
|
||||
// to re-upload all the vertices based on the new font's textures.
|
||||
texture_cache_id = (uint32) -1;
|
||||
regenerateVertices();
|
||||
}
|
||||
|
||||
love::graphics::Font *Text::getFont() const
|
||||
{
|
||||
return font.get();
|
||||
}
|
||||
|
||||
int Text::getWidth(int index) const
|
||||
{
|
||||
if (index < 0)
|
||||
index = std::max((int) text_data.size() - 1, 0);
|
||||
|
||||
if (index >= (int) text_data.size())
|
||||
return 0;
|
||||
|
||||
return text_data[index].text_info.width;
|
||||
}
|
||||
|
||||
int Text::getHeight(int index) const
|
||||
{
|
||||
if (index < 0)
|
||||
index = std::max((int) text_data.size() - 1, 0);
|
||||
|
||||
if (index >= (int) text_data.size())
|
||||
return 0;
|
||||
|
||||
return text_data[index].text_info.height;
|
||||
}
|
||||
|
||||
} // opengl
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
Reference in New Issue
Block a user