mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-11 22:11:51 +00:00
feat: rendering pages on demand
This commit is contained in:
parent
381cb77d08
commit
47809b4024
9 changed files with 106 additions and 39 deletions
|
|
@ -208,6 +208,7 @@ assetload::postfunc assetload::font(
|
||||||
logger.info() << "loading vector font " << util::quote(filename);
|
logger.info() << "loading vector font " << util::quote(filename);
|
||||||
return [=](auto assets) {
|
return [=](auto assets) {
|
||||||
auto font = vector_fonts::load_font(paths.find(filename).string());
|
auto font = vector_fonts::load_font(paths.find(filename).string());
|
||||||
|
assets->store(font, filename);
|
||||||
assets->store(font->createInstance(cfg ? cfg->size : 16), name);
|
assets->store(font->createInstance(cfg ? cfg->size : 16), name);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ static const char* get_ft_error_message(FT_Error error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class FTFontFile : public vector_fonts::FontFile {
|
class FTFontFile : public vector_fonts::FontFile,
|
||||||
|
public std::enable_shared_from_this<FTFontFile> {
|
||||||
public:
|
public:
|
||||||
FTFontFile(FT_Face face, util::Buffer<ubyte> buffer)
|
FTFontFile(FT_Face face, util::Buffer<ubyte> buffer)
|
||||||
: face(std::move(face)), buffer(std::move(buffer)) {
|
: face(std::move(face)), buffer(std::move(buffer)) {
|
||||||
|
|
@ -47,20 +48,42 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Texture>> pages;
|
std::vector<std::unique_ptr<Texture>> pages;
|
||||||
std::vector<Font::Glyph> glyphs;
|
std::vector<Glyph> glyphs;
|
||||||
|
|
||||||
int dstSize = size * 16;
|
int dstSize = size * 16;
|
||||||
ImageData canvas(ImageFormat::RGBA8888, dstSize, dstSize);
|
ImageData canvas(ImageFormat::RGBA8888, dstSize, dstSize);
|
||||||
ImageData bitmapDst(ImageFormat::RGBA8888, size, size);
|
ImageData bitmapDst(ImageFormat::RGBA8888, size, size);
|
||||||
|
|
||||||
for (int pageid = 0; pageid < FONT_PAGES; pageid++) {
|
for (int pageid = 0; pageid < DEFAULT_PRE_RENDER_FONT_PAGES; pageid++) {
|
||||||
renderPage(pageid, canvas, bitmapDst, glyphs);
|
renderPage(pageid, canvas, bitmapDst, glyphs);
|
||||||
pages.push_back(Texture::from(&canvas));
|
pages.push_back(Texture::from(&canvas));
|
||||||
}
|
}
|
||||||
return std::make_unique<Font>(
|
return std::make_unique<Font>(
|
||||||
std::move(pages), std::move(glyphs), size, size / 2
|
std::move(pages),
|
||||||
|
std::move(glyphs),
|
||||||
|
size,
|
||||||
|
size / 2,
|
||||||
|
shared_from_this()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Texture> renderPage(
|
||||||
|
int pageid, std::vector<Glyph>& glyphs, int size
|
||||||
|
) override {
|
||||||
|
if (FT_Error error = FT_Set_Pixel_Sizes(face, 0, size)) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"FT_Set_Pixel_Sizes error: " +
|
||||||
|
std::string(get_ft_error_message(error))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dstSize = size * 16;
|
||||||
|
ImageData canvas(ImageFormat::RGBA8888, dstSize, dstSize);
|
||||||
|
ImageData bitmapDst(ImageFormat::RGBA8888, size, size);
|
||||||
|
|
||||||
|
renderPage(pageid, canvas, bitmapDst, glyphs);
|
||||||
|
return Texture::from(&canvas);
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
util::Buffer<ubyte> buffer;
|
util::Buffer<ubyte> buffer;
|
||||||
|
|
@ -95,19 +118,19 @@ namespace {
|
||||||
int pageid,
|
int pageid,
|
||||||
ImageData& canvas,
|
ImageData& canvas,
|
||||||
ImageData& bitmapDst,
|
ImageData& bitmapDst,
|
||||||
std::vector<Font::Glyph>& glyphs
|
std::vector<Glyph>& glyphs
|
||||||
) {
|
) {
|
||||||
int size = canvas.getWidth() / 16;
|
int size = canvas.getWidth() / 16;
|
||||||
for (int c = 0; c < 256; c++) {
|
for (int c = 0; c < 256; c++) {
|
||||||
int codepoint = pageid << 8 | c;
|
int codepoint = pageid << 8 | c;
|
||||||
if (!renderGlyph(codepoint, bitmapDst)) {
|
if (!renderGlyph(codepoint, bitmapDst)) {
|
||||||
glyphs.push_back(Font::Glyph {0, size / 2});
|
glyphs.push_back(Glyph {0, size / 2});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.blit(bitmapDst, (c % 16) * size, (c / 16) * size);
|
canvas.blit(bitmapDst, (c % 16) * size, (c / 16) * size);
|
||||||
|
|
||||||
Font::Glyph glyph {
|
Glyph glyph {
|
||||||
face->glyph->bitmap_top - size,
|
face->glyph->bitmap_top - size,
|
||||||
static_cast<int>(face->glyph->advance.x >> 6)
|
static_cast<int>(face->glyph->advance.x >> 6)
|
||||||
};
|
};
|
||||||
|
|
@ -133,11 +156,14 @@ void vector_fonts::initialize() {
|
||||||
|
|
||||||
void vector_fonts::finalize() {
|
void vector_fonts::finalize() {
|
||||||
if (FT_Error error = FT_Done_FreeType(library)) {
|
if (FT_Error error = FT_Done_FreeType(library)) {
|
||||||
logger.error() << "error on FT_Done_FreeType: " << get_ft_error_message(error);
|
logger.error() << "error on FT_Done_FreeType: "
|
||||||
|
<< get_ft_error_message(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<vector_fonts::FontFile> vector_fonts::load_font(const std::string& filename) {
|
std::shared_ptr<vector_fonts::FontFile> vector_fonts::load_font(
|
||||||
|
const std::string& filename
|
||||||
|
) {
|
||||||
auto bytes = io::read_bytes_buffer(io::path(filename));
|
auto bytes = io::read_bytes_buffer(io::path(filename));
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
|
|
@ -150,5 +176,5 @@ std::unique_ptr<vector_fonts::FontFile> vector_fonts::load_font(const std::strin
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<FTFontFile>(std::move(face), std::move(bytes));
|
return std::make_shared<FTFontFile>(std::move(face), std::move(bytes));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,12 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
|
struct Glyph;
|
||||||
|
|
||||||
|
class Texture;
|
||||||
|
|
||||||
namespace vector_fonts {
|
namespace vector_fonts {
|
||||||
class FontFile {
|
class FontFile {
|
||||||
|
|
@ -11,10 +15,14 @@ namespace vector_fonts {
|
||||||
virtual ~FontFile() {}
|
virtual ~FontFile() {}
|
||||||
|
|
||||||
virtual std::unique_ptr<Font> createInstance(int size) = 0;
|
virtual std::unique_ptr<Font> createInstance(int size) = 0;
|
||||||
|
|
||||||
|
virtual std::unique_ptr<Texture> renderPage(
|
||||||
|
int pageid, std::vector<Glyph>& glyphs, int size
|
||||||
|
) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void finalize();
|
void finalize();
|
||||||
|
|
||||||
std::unique_ptr<vector_fonts::FontFile> load_font(const std::string& filename);
|
std::shared_ptr<vector_fonts::FontFile> load_font(const std::string& filename);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ inline constexpr int ATLAS_EXTRUSION = 2;
|
||||||
|
|
||||||
inline constexpr int DEFAULT_FONT_SIZE = 16;
|
inline constexpr int DEFAULT_FONT_SIZE = 16;
|
||||||
|
|
||||||
inline constexpr int FONT_PAGES = 5;
|
inline constexpr int DEFAULT_PRE_RENDER_FONT_PAGES = 1; // must be at least 1
|
||||||
|
|
||||||
inline const std::string SHADERS_FOLDER = "shaders";
|
inline const std::string SHADERS_FOLDER = "shaders";
|
||||||
inline const std::string TEXTURES_FOLDER = "textures";
|
inline const std::string TEXTURES_FOLDER = "textures";
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
#include "Font.hpp"
|
#include "Font.hpp"
|
||||||
|
|
||||||
|
#include "Batch2D.hpp"
|
||||||
|
#include "Batch3D.hpp"
|
||||||
|
#include "coders/vector_fonts.hpp"
|
||||||
|
#include "Texture.hpp"
|
||||||
|
#include "window/Camera.hpp"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "Texture.hpp"
|
|
||||||
#include "Batch2D.hpp"
|
|
||||||
#include "Batch3D.hpp"
|
|
||||||
#include "window/Camera.hpp"
|
|
||||||
|
|
||||||
inline constexpr uint GLYPH_SIZE = 16;
|
inline constexpr uint GLYPH_SIZE = 16;
|
||||||
inline constexpr uint MAX_CODEPAGES = 10000; // idk ho many codepages unicode has
|
inline constexpr uint MAX_CODEPAGES = 10000; // idk ho many codepages unicode has
|
||||||
|
|
@ -15,13 +17,15 @@ Font::Font(
|
||||||
std::vector<std::unique_ptr<Texture>> pages,
|
std::vector<std::unique_ptr<Texture>> pages,
|
||||||
std::vector<Glyph> glyphs,
|
std::vector<Glyph> glyphs,
|
||||||
int lineHeight,
|
int lineHeight,
|
||||||
int yoffset
|
int yoffset,
|
||||||
|
std::optional<std::weak_ptr<vector_fonts::FontFile>> fontFile
|
||||||
)
|
)
|
||||||
: lineHeight(lineHeight),
|
: lineHeight(lineHeight),
|
||||||
yoffset(yoffset),
|
yoffset(yoffset),
|
||||||
glyphInterval(lineHeight / 2),
|
glyphInterval(lineHeight / 2),
|
||||||
pages(std::move(pages)),
|
pages(std::move(pages)),
|
||||||
glyphs(std::move(glyphs)) {
|
glyphs(std::move(glyphs)),
|
||||||
|
fontFile(std::move(fontFile)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::~Font() = default;
|
Font::~Font() = default;
|
||||||
|
|
@ -139,7 +143,7 @@ static inline void draw_glyph(
|
||||||
|
|
||||||
template <class Batch>
|
template <class Batch>
|
||||||
static inline void draw_text(
|
static inline void draw_text(
|
||||||
const Font& font,
|
Font& font,
|
||||||
Batch& batch,
|
Batch& batch,
|
||||||
std::wstring_view text,
|
std::wstring_view text,
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
|
|
@ -244,7 +248,7 @@ void Font::draw(
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
size_t styleMapOffset,
|
size_t styleMapOffset,
|
||||||
float scale
|
float scale
|
||||||
) const {
|
) {
|
||||||
draw_text(
|
draw_text(
|
||||||
*this, batch, text,
|
*this, batch, text,
|
||||||
glm::vec3(x, y, 0),
|
glm::vec3(x, y, 0),
|
||||||
|
|
@ -264,7 +268,7 @@ void Font::draw(
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& right,
|
const glm::vec3& right,
|
||||||
const glm::vec3& up
|
const glm::vec3& up
|
||||||
) const {
|
) {
|
||||||
draw_text(
|
draw_text(
|
||||||
*this, batch, text, pos,
|
*this, batch, text, pos,
|
||||||
right * static_cast<float>(glyphInterval),
|
right * static_cast<float>(glyphInterval),
|
||||||
|
|
@ -296,3 +300,28 @@ std::unique_ptr<Font> Font::createBitmapFont(
|
||||||
}
|
}
|
||||||
return std::make_unique<Font>(std::move(textures), std::move(glyphs), res, 4);
|
return std::make_unique<Font>(std::move(textures), std::move(glyphs), res, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Glyph* Font::getGlyph(int codepoint) {
|
||||||
|
if (codepoint < 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (codepoint < glyphs.size()) {
|
||||||
|
return &glyphs.at(codepoint);
|
||||||
|
}
|
||||||
|
if (!this->fontFile.has_value() || this->fontFile->expired()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int codepage = codepoint >> 8;
|
||||||
|
if (codepage >= 1024) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (glyphs.size() < (codepage << 8)) {
|
||||||
|
glyphs.resize(codepage << 8);
|
||||||
|
}
|
||||||
|
auto fontFile = this->fontFile->lock();
|
||||||
|
if (pages.size() <= codepage) {
|
||||||
|
pages.resize(codepage);
|
||||||
|
}
|
||||||
|
pages.push_back(fontFile->renderPage(codepage, glyphs, lineHeight));
|
||||||
|
return &glyphs.at(codepoint);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
@ -18,18 +19,23 @@ class ImageData;
|
||||||
|
|
||||||
class Font;
|
class Font;
|
||||||
|
|
||||||
|
namespace vector_fonts {
|
||||||
|
class FontFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Glyph {
|
||||||
|
int yOffset;
|
||||||
|
int xAdvance;
|
||||||
|
};
|
||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
public:
|
public:
|
||||||
struct Glyph {
|
|
||||||
int yOffset;
|
|
||||||
int xAdvance;
|
|
||||||
};
|
|
||||||
|
|
||||||
Font(
|
Font(
|
||||||
std::vector<std::unique_ptr<Texture>> pages,
|
std::vector<std::unique_ptr<Texture>> pages,
|
||||||
std::vector<Glyph> glyphs,
|
std::vector<Glyph> glyphs,
|
||||||
int lineHeight,
|
int lineHeight,
|
||||||
int yoffset
|
int yoffset,
|
||||||
|
std::optional<std::weak_ptr<vector_fonts::FontFile>> fontFile = std::nullopt
|
||||||
);
|
);
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
|
|
@ -61,7 +67,7 @@ public:
|
||||||
const FontStylesScheme* styles,
|
const FontStylesScheme* styles,
|
||||||
size_t styleMapOffset,
|
size_t styleMapOffset,
|
||||||
float scale = 1
|
float scale = 1
|
||||||
) const;
|
);
|
||||||
|
|
||||||
void draw(
|
void draw(
|
||||||
Batch3D& batch,
|
Batch3D& batch,
|
||||||
|
|
@ -71,7 +77,7 @@ public:
|
||||||
const glm::vec3& pos,
|
const glm::vec3& pos,
|
||||||
const glm::vec3& right={1, 0, 0},
|
const glm::vec3& right={1, 0, 0},
|
||||||
const glm::vec3& up={0, 1, 0}
|
const glm::vec3& up={0, 1, 0}
|
||||||
) const;
|
);
|
||||||
|
|
||||||
const Texture* getPage(int page) const;
|
const Texture* getPage(int page) const;
|
||||||
|
|
||||||
|
|
@ -79,11 +85,7 @@ public:
|
||||||
return {std::nullopt, lineHeight, yoffset, glyphInterval};
|
return {std::nullopt, lineHeight, yoffset, glyphInterval};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Glyph* getGlyph(int codepoint) const {
|
const Glyph* getGlyph(int codepoint);
|
||||||
return (codepoint < 0 || codepoint >= glyphs.size())
|
|
||||||
? nullptr
|
|
||||||
: &glyphs.at(codepoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::unique_ptr<Font> createBitmapFont(
|
static std::unique_ptr<Font> createBitmapFont(
|
||||||
std::vector<std::unique_ptr<ImageData>> pages
|
std::vector<std::unique_ptr<ImageData>> pages
|
||||||
|
|
@ -94,4 +96,5 @@ private:
|
||||||
int glyphInterval;
|
int glyphInterval;
|
||||||
std::vector<std::unique_ptr<Texture>> pages;
|
std::vector<std::unique_ptr<Texture>> pages;
|
||||||
std::vector<Glyph> glyphs;
|
std::vector<Glyph> glyphs;
|
||||||
|
std::optional<std::weak_ptr<vector_fonts::FontFile>> fontFile;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ void TextsRenderer::renderNote(
|
||||||
}
|
}
|
||||||
opacity = preset.xrayOpacity;
|
opacity = preset.xrayOpacity;
|
||||||
}
|
}
|
||||||
const auto& font = assets.require<Font>(FONT_DEFAULT);
|
auto& font = assets.require<Font>(FONT_DEFAULT);
|
||||||
|
|
||||||
glm::vec3 xvec = note.getAxisX();
|
glm::vec3 xvec = note.getAxisX();
|
||||||
glm::vec3 yvec = note.getAxisY();
|
glm::vec3 yvec = note.getAxisY();
|
||||||
|
|
|
||||||
|
|
@ -276,13 +276,13 @@ void SlotView::draw(const DrawContext& pctx, const Assets& assets) {
|
||||||
drawItemIcon(batch, stack, item, assets, tint, pos);
|
drawItemIcon(batch, stack, item, assets, tint, pos);
|
||||||
|
|
||||||
if (stack.getCount() > 1 || stack.getFields() != nullptr) {
|
if (stack.getCount() > 1 || stack.getFields() != nullptr) {
|
||||||
const auto& font = assets.require<Font>(FONT_DEFAULT);
|
auto& font = assets.require<Font>(FONT_DEFAULT);
|
||||||
drawItemInfo(batch, stack, item, font, pos);
|
drawItemInfo(batch, stack, item, font, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_shaded_text(
|
static void draw_shaded_text(
|
||||||
Batch2D& batch, const Font& font, const std::wstring& text, int x, int y
|
Batch2D& batch, Font& font, const std::wstring& text, int x, int y
|
||||||
) {
|
) {
|
||||||
batch.setColor({0, 0, 0, 1.0f});
|
batch.setColor({0, 0, 0, 1.0f});
|
||||||
font.draw(batch, text, x + 1, y + 1, nullptr, 0);
|
font.draw(batch, text, x + 1, y + 1, nullptr, 0);
|
||||||
|
|
@ -294,7 +294,7 @@ void SlotView::drawItemInfo(
|
||||||
Batch2D& batch,
|
Batch2D& batch,
|
||||||
const ItemStack& stack,
|
const ItemStack& stack,
|
||||||
const ItemDef& item,
|
const ItemDef& item,
|
||||||
const Font& font,
|
Font& font,
|
||||||
const glm::vec2& pos
|
const glm::vec2& pos
|
||||||
) {
|
) {
|
||||||
const int SLOT_SIZE = InventoryView::SLOT_SIZE;
|
const int SLOT_SIZE = InventoryView::SLOT_SIZE;
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace gui {
|
||||||
Batch2D& batch,
|
Batch2D& batch,
|
||||||
const ItemStack& stack,
|
const ItemStack& stack,
|
||||||
const ItemDef& item,
|
const ItemDef& item,
|
||||||
const Font& font,
|
Font& font,
|
||||||
const glm::vec2& pos
|
const glm::vec2& pos
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue