mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-03-06 14:27:43 +00:00
Improved font rendering quality and always enabled linear texture interpolation for both minification and magnification
This commit is contained in:
parent
bf16bed03f
commit
ee2573345f
|
@ -715,7 +715,8 @@ void GuiScraperSearch::render(const glm::mat4& parentTrans)
|
|||
|
||||
// Slight adjustment upwards so the busy grid is not rendered precisely at the text edge.
|
||||
trans = glm::translate(
|
||||
trans, glm::vec3 {0.0f, -(mRenderer->getScreenResolutionModifier() * 10.0f), 0.0f});
|
||||
trans,
|
||||
glm::vec3 {0.0f, std::round(-(mRenderer->getScreenResolutionModifier() * 10.0f)), 0.0f});
|
||||
|
||||
if (mBlockAccept) {
|
||||
mRenderer->setMatrix(trans);
|
||||
|
|
|
@ -157,7 +157,7 @@ void GuiScraperSingle::onSizeChanged()
|
|||
else
|
||||
mGrid.setColWidthPerc(1, 0.04f);
|
||||
|
||||
mGrid.setSize(glm::round(mSize));
|
||||
mGrid.setSize(mSize);
|
||||
mBackground.fitTo(mSize);
|
||||
|
||||
// Add some extra margins to the game name.
|
||||
|
|
|
@ -79,14 +79,13 @@ void HelpStyle::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::s
|
|||
iconColorDimmed = iconColor;
|
||||
|
||||
if (elem->has("fontPath") || elem->has("fontSize")) {
|
||||
font = Font::getFromTheme(elem, ThemeFlags::ALL, font, 0.0f, false);
|
||||
font = Font::getFromTheme(elem, ThemeFlags::ALL, font);
|
||||
if (!elem->has("fontSizeDimmed"))
|
||||
fontDimmed = Font::getFromTheme(elem, ThemeFlags::ALL, font, 0.0f, false);
|
||||
fontDimmed = Font::getFromTheme(elem, ThemeFlags::ALL, font);
|
||||
}
|
||||
|
||||
if (elem->has("fontSizeDimmed")) {
|
||||
fontDimmed = Font::getFromTheme(elem, ThemeFlags::ALL, font, 0.0f, false, 1.0f, true);
|
||||
}
|
||||
if (elem->has("fontSizeDimmed"))
|
||||
fontDimmed = Font::getFromTheme(elem, ThemeFlags::ALL, font, 0.0f, 1.0f, true);
|
||||
|
||||
if (elem->has("entrySpacing"))
|
||||
entrySpacing = glm::clamp(elem->get<float>("entrySpacing"), 0.0f, 0.04f);
|
||||
|
|
|
@ -237,5 +237,5 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
if (properties & LINE_SPACING && elem->has("lineSpacing"))
|
||||
setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
|
||||
|
||||
setFont(Font::getFromTheme(elem, properties, mFont, maxHeight, false));
|
||||
setFont(Font::getFromTheme(elem, properties, mFont, maxHeight));
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ void DateTimeEditComponent::render(const glm::mat4& parentTrans)
|
|||
|
||||
if (mAlignRight)
|
||||
off.x += referenceSize - mTextCache->metrics.size.x;
|
||||
trans = glm::translate(trans, off);
|
||||
trans = glm::translate(trans, glm::round(off));
|
||||
|
||||
mRenderer->setMatrix(trans);
|
||||
|
||||
|
|
|
@ -252,21 +252,22 @@ void TextComponent::render(const glm::mat4& parentTrans)
|
|||
mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, mBgColor, mBgColor, false,
|
||||
mOpacity * mThemeOpacity, mDimming);
|
||||
if (mTextCache) {
|
||||
const glm::vec2& textSize {mTextCache->metrics.size};
|
||||
const float textHeight {mTextCache->metrics.size.y};
|
||||
float yOff {0.0f};
|
||||
float yOffDebugOverlay {0.0f};
|
||||
|
||||
if (mSize.y > textSize.y) {
|
||||
if (mSize.y > textHeight) {
|
||||
switch (mVerticalAlignment) {
|
||||
case ALIGN_TOP: {
|
||||
yOff = 0.0f;
|
||||
break;
|
||||
}
|
||||
case ALIGN_BOTTOM: {
|
||||
yOff = mSize.y - textSize.y;
|
||||
yOff = mSize.y - textHeight;
|
||||
break;
|
||||
}
|
||||
case ALIGN_CENTER: {
|
||||
yOff = (mSize.y - textSize.y) / 2.0f;
|
||||
yOff = (mSize.y - textHeight) / 2.0f;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -275,8 +276,9 @@ void TextComponent::render(const glm::mat4& parentTrans)
|
|||
}
|
||||
}
|
||||
else {
|
||||
// If height is smaller than the font height, then always center vertically.
|
||||
yOff = (mSize.y - textSize.y) / 2.0f;
|
||||
// If height is smaller than the font height, then centering is done in
|
||||
// Font::buildTextCache()
|
||||
yOffDebugOverlay = (mSize.y - textHeight) / 2.0f;
|
||||
}
|
||||
|
||||
// Draw the overall textbox area. If we're inside a vertical scrollable container then
|
||||
|
@ -286,7 +288,7 @@ void TextComponent::render(const glm::mat4& parentTrans)
|
|||
mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33);
|
||||
}
|
||||
|
||||
trans = glm::translate(trans, glm::vec3 {0.0f, yOff, 0.0f});
|
||||
trans = glm::translate(trans, glm::vec3 {0.0f, std::round(yOff), 0.0f});
|
||||
mRenderer->setMatrix(trans);
|
||||
|
||||
if (Settings::getInstance()->getBool("DebugText")) {
|
||||
|
@ -295,14 +297,14 @@ void TextComponent::render(const glm::mat4& parentTrans)
|
|||
if (mScrollOffset1 <= mTextCache->metrics.size.x) {
|
||||
const float width {mTextCache->metrics.size.x - mScrollOffset1};
|
||||
mRenderer->drawRect(
|
||||
mScrollOffset1 + relativeScaleOffset, 0.0f,
|
||||
mScrollOffset1 + relativeScaleOffset, yOffDebugOverlay,
|
||||
width > mSize.x * mRelativeScale ? mSize.x * mRelativeScale : width,
|
||||
mTextCache->metrics.size.y, 0x00000033, 0x00000033);
|
||||
}
|
||||
}
|
||||
else if (mHorizontalScrolling && secondPass) {
|
||||
if ((mSize.x * mRelativeScale) - -mScrollOffset2 > 0.0f) {
|
||||
mRenderer->drawRect(relativeScaleOffset, 0.0f,
|
||||
mRenderer->drawRect(relativeScaleOffset, yOffDebugOverlay,
|
||||
(mSize.x * mRelativeScale) - -mScrollOffset2,
|
||||
mTextCache->metrics.size.y, 0x00000033, 0x00000033);
|
||||
}
|
||||
|
@ -310,19 +312,19 @@ void TextComponent::render(const glm::mat4& parentTrans)
|
|||
else {
|
||||
switch (mHorizontalAlignment) {
|
||||
case ALIGN_LEFT: {
|
||||
mRenderer->drawRect(0.0f, 0.0f, mTextCache->metrics.size.x,
|
||||
mRenderer->drawRect(0.0f, yOffDebugOverlay, mTextCache->metrics.size.x,
|
||||
mTextCache->metrics.size.y, 0x00000033, 0x00000033);
|
||||
break;
|
||||
}
|
||||
case ALIGN_CENTER: {
|
||||
mRenderer->drawRect((mSize.x - mTextCache->metrics.size.x) / 2.0f, 0.0f,
|
||||
mTextCache->metrics.size.x,
|
||||
mTextCache->metrics.size.y, 0x00000033, 0x00000033);
|
||||
mRenderer->drawRect((mSize.x - mTextCache->metrics.size.x) / 2.0f,
|
||||
yOffDebugOverlay, mTextCache->metrics.size.x,
|
||||
mTextCache->metrics.size.y, 0x000033, 0x00000033);
|
||||
break;
|
||||
}
|
||||
case ALIGN_RIGHT: {
|
||||
mRenderer->drawRect(mSize.x - mTextCache->metrics.size.x, 0.0f,
|
||||
mTextCache->metrics.size.x,
|
||||
mRenderer->drawRect(mSize.x - mTextCache->metrics.size.x,
|
||||
yOffDebugOverlay, mTextCache->metrics.size.x,
|
||||
mTextCache->metrics.size.y, 0x00000033, 0x00000033);
|
||||
break;
|
||||
}
|
||||
|
@ -467,10 +469,13 @@ void TextComponent::onTextChanged()
|
|||
lineHeight = mFont->loadGlyphs(text + "\n") * mLineSpacing;
|
||||
|
||||
const bool isMultiline {mAutoCalcExtent.y == 1 || mSize.y * mRelativeScale > lineHeight};
|
||||
float offsetY {0.0f};
|
||||
|
||||
if (mHorizontalScrolling) {
|
||||
if (lineHeight > mSize.y)
|
||||
offsetY = (mSize.y - lineHeight) / 2.0f;
|
||||
mTextCache = std::shared_ptr<TextCache>(
|
||||
font->buildTextCache(text, 0.0f, 0.0f, mColor, mLineSpacing));
|
||||
font->buildTextCache(text, 0.0f, offsetY, mColor, mLineSpacing));
|
||||
}
|
||||
else if (isMultiline && !isScrollable) {
|
||||
const std::string wrappedText {
|
||||
|
@ -482,9 +487,12 @@ void TextComponent::onTextChanged()
|
|||
mHorizontalAlignment, mLineSpacing, mNoTopMargin));
|
||||
}
|
||||
else {
|
||||
mTextCache = std::shared_ptr<TextCache>(font->buildTextCache(
|
||||
font->wrapText(text, mSize.x, 0.0f, mLineSpacing, isMultiline), glm::vec2 {0.0f, 0.0f},
|
||||
mColor, mSize.x, mHorizontalAlignment, mLineSpacing, mNoTopMargin));
|
||||
if (!isMultiline && lineHeight > mSize.y)
|
||||
offsetY = (mSize.y - lineHeight) / 2.0f;
|
||||
mTextCache = std::shared_ptr<TextCache>(
|
||||
font->buildTextCache(font->wrapText(text, mSize.x, 0.0f, mLineSpacing, isMultiline),
|
||||
glm::vec2 {0.0f, offsetY}, mColor, mSize.x, mHorizontalAlignment,
|
||||
mLineSpacing, mNoTopMargin));
|
||||
}
|
||||
|
||||
if (mAutoCalcExtent.y)
|
||||
|
@ -754,7 +762,7 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
if (properties & LINE_SPACING && elem->has("lineSpacing"))
|
||||
setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
|
||||
|
||||
setFont(Font::getFromTheme(elem, properties, mFont, maxHeight, false));
|
||||
setFont(Font::getFromTheme(elem, properties, mFont, maxHeight));
|
||||
|
||||
// We need to do this after setting the font as the scroll speed is calculated from its size.
|
||||
if (mHorizontalScrolling)
|
||||
|
|
|
@ -1664,8 +1664,8 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
List::mTierList = IList<CarouselEntry, T>::LIST_SCROLL_STYLE_MEDIUM;
|
||||
|
||||
// Ccale the font size with the itemScale property value.
|
||||
mFont = Font::getFromTheme(elem, properties, mFont, 0.0f, false,
|
||||
(mItemScale >= 1.0f ? mItemScale : 1.0f));
|
||||
mFont =
|
||||
Font::getFromTheme(elem, properties, mFont, 0.0f, (mItemScale >= 1.0f ? mItemScale : 1.0f));
|
||||
|
||||
if (elem->has("textRelativeScale"))
|
||||
mTextRelativeScale = glm::clamp(elem->get<float>("textRelativeScale"), 0.2f, 1.0f);
|
||||
|
|
|
@ -1344,7 +1344,7 @@ void GridComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
if (elem->has("unfocusedItemDimming"))
|
||||
mUnfocusedItemDimming = glm::clamp(elem->get<float>("unfocusedItemDimming"), 0.0f, 1.0f);
|
||||
|
||||
mFont = Font::getFromTheme(elem, properties, mFont, 0.0f, (mItemScale > 1.0f));
|
||||
mFont = Font::getFromTheme(elem, properties, mFont);
|
||||
|
||||
if (elem->has("textRelativeScale"))
|
||||
mTextRelativeScale = glm::clamp(elem->get<float>("textRelativeScale"), 0.2f, 1.0f);
|
||||
|
|
|
@ -403,7 +403,7 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
|
|||
// Render text.
|
||||
glm::mat4 drawTrans {trans};
|
||||
|
||||
drawTrans = glm::translate(drawTrans, offset);
|
||||
drawTrans = glm::translate(drawTrans, glm::round(offset));
|
||||
mRenderer->setMatrix(drawTrans);
|
||||
|
||||
if (i == mCursor && backgroundColor != 0x00000000) {
|
||||
|
@ -503,7 +503,7 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
|||
glm::clamp(elem->get<float>("textHorizontalScrollGap"), 0.1f, 5.0f);
|
||||
}
|
||||
|
||||
mFont = Font::getFromTheme(elem, properties, mFont, 0.0f, false);
|
||||
mFont = Font::getFromTheme(elem, properties, mFont);
|
||||
|
||||
if (properties & ALIGNMENT) {
|
||||
if (elem->has("horizontalAlignment")) {
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
#include "utils/PlatformUtil.h"
|
||||
#include "utils/StringUtil.h"
|
||||
|
||||
Font::Font(float size, const std::string& path, const bool linearMagnify)
|
||||
Font::Font(float size, const std::string& path)
|
||||
: mRenderer {Renderer::getInstance()}
|
||||
, mPath(path)
|
||||
, mFontSize {size}
|
||||
, mLinearMagnify {linearMagnify}
|
||||
, mLetterHeight {0.0f}
|
||||
, mMaxGlyphHeight {static_cast<int>(std::round(size))}
|
||||
{
|
||||
|
@ -46,8 +45,7 @@ Font::~Font()
|
|||
{
|
||||
unload(ResourceManager::getInstance());
|
||||
|
||||
auto fontEntry =
|
||||
sFontMap.find(std::tuple<float, std::string, bool>(mFontSize, mPath, mLinearMagnify));
|
||||
auto fontEntry = sFontMap.find(std::tuple<float, std::string>(mFontSize, mPath));
|
||||
|
||||
if (fontEntry != sFontMap.cend())
|
||||
sFontMap.erase(fontEntry);
|
||||
|
@ -58,11 +56,11 @@ Font::~Font()
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> Font::get(float size, const std::string& path, const bool linearMagnify)
|
||||
std::shared_ptr<Font> Font::get(float size, const std::string& path)
|
||||
{
|
||||
const std::string canonicalPath {Utils::FileSystem::getCanonicalPath(path)};
|
||||
const std::tuple<float, std::string, bool> def {
|
||||
size, canonicalPath.empty() ? getDefaultPath() : canonicalPath, linearMagnify};
|
||||
const std::tuple<float, std::string> def {size, canonicalPath.empty() ? getDefaultPath() :
|
||||
canonicalPath};
|
||||
|
||||
auto foundFont = sFontMap.find(def);
|
||||
if (foundFont != sFontMap.cend()) {
|
||||
|
@ -70,7 +68,7 @@ std::shared_ptr<Font> Font::get(float size, const std::string& path, const bool
|
|||
return foundFont->second.lock();
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> font {new Font(std::get<0>(def), std::get<1>(def), std::get<2>(def))};
|
||||
std::shared_ptr<Font> font {new Font(std::get<0>(def), std::get<1>(def))};
|
||||
sFontMap[def] = std::weak_ptr<Font>(font);
|
||||
ResourceManager::getInstance().addReloadable(font);
|
||||
return font;
|
||||
|
@ -139,8 +137,8 @@ TextCache* Font::buildTextCache(const std::string& text,
|
|||
float lineSpacing,
|
||||
bool noTopMargin)
|
||||
{
|
||||
float x {offset[0] + (xLen != 0 ? getNewlineStartOffset(text, 0, xLen, alignment) : 0)};
|
||||
float yTop {0.0f};
|
||||
float x {offset.x + (xLen != 0 ? getNewlineStartOffset(text, 0, xLen, alignment) : 0)};
|
||||
int yTop {0};
|
||||
float yBot {0.0f};
|
||||
|
||||
if (noTopMargin) {
|
||||
|
@ -148,14 +146,11 @@ TextCache* Font::buildTextCache(const std::string& text,
|
|||
yBot = getHeight(1.5);
|
||||
}
|
||||
else {
|
||||
// TODO: This is lacking some precision which is especially visible at higher resolutions
|
||||
// like 4K where the text is not always placed entirely correctly vertically. Try to find
|
||||
// a way to improve on this.
|
||||
yTop = getGlyph('S')->bearing.y;
|
||||
yBot = getHeight(lineSpacing);
|
||||
}
|
||||
|
||||
float y {offset[1] + (yBot + yTop) / 2.0f};
|
||||
float y {offset.y + ((yBot + yTop) / 2.0f)};
|
||||
|
||||
// Vertices by texture.
|
||||
std::map<FontTexture*, std::vector<Renderer::Vertex>> vertMap;
|
||||
|
@ -312,7 +307,7 @@ std::string Font::wrapText(const std::string& text,
|
|||
|
||||
Glyph* glyph {getGlyph(charID)};
|
||||
if (glyph != nullptr) {
|
||||
charWidth = glyph->advance.x;
|
||||
charWidth = static_cast<float>(glyph->advance.x);
|
||||
byteCount = cursor - i;
|
||||
}
|
||||
else {
|
||||
|
@ -435,7 +430,6 @@ std::shared_ptr<Font> Font::getFromTheme(const ThemeData::ThemeElement* elem,
|
|||
unsigned int properties,
|
||||
const std::shared_ptr<Font>& orig,
|
||||
const float maxHeight,
|
||||
const bool linearMagnify,
|
||||
const float sizeMultiplier,
|
||||
const bool fontSizeDimmed)
|
||||
{
|
||||
|
@ -475,7 +469,7 @@ std::shared_ptr<Font> Font::getFromTheme(const ThemeData::ThemeElement* elem,
|
|||
path = getDefaultPath();
|
||||
}
|
||||
|
||||
return get(size, path, linearMagnify);
|
||||
return get(size, path);
|
||||
}
|
||||
|
||||
size_t Font::getMemUsage() const
|
||||
|
@ -538,14 +532,13 @@ std::vector<std::string> Font::getFallbackFontPaths()
|
|||
return fontPaths;
|
||||
}
|
||||
|
||||
Font::FontTexture::FontTexture(const int mFontSize, const bool linearMagnifyArg)
|
||||
Font::FontTexture::FontTexture(const int mFontSize)
|
||||
{
|
||||
textureId = 0;
|
||||
rowHeight = 0;
|
||||
writePos = glm::ivec2 {0, 0};
|
||||
linearMagnify = linearMagnifyArg;
|
||||
writePos = glm::ivec2 {1, 1};
|
||||
|
||||
// Set the texture to a reasonable size, if we run out of space for adding glyphs then
|
||||
// Set the texture atlas to a reasonable size, if we run out of space for adding glyphs then
|
||||
// more textures will be created dynamically.
|
||||
textureSize = glm::ivec2 {mFontSize * 6, mFontSize * 6};
|
||||
}
|
||||
|
@ -556,24 +549,24 @@ Font::FontTexture::~FontTexture()
|
|||
deinitTexture();
|
||||
}
|
||||
|
||||
bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out)
|
||||
bool Font::FontTexture::findEmpty(const glm::ivec2& size, glm::ivec2& cursorOut)
|
||||
{
|
||||
if (size.x >= textureSize.x || size.y >= textureSize.y)
|
||||
if (size.x > textureSize.x || size.y > textureSize.y)
|
||||
return false;
|
||||
|
||||
if (writePos.x + size.x >= textureSize.x &&
|
||||
if (writePos.x + size.x + 1 > textureSize.x &&
|
||||
writePos.y + rowHeight + size.y + 1 < textureSize.y) {
|
||||
// Row is full, but the glyph should fit on the next row so move the cursor there.
|
||||
// Leave 1 pixel of space between glyphs so that pixels from adjacent glyphs will
|
||||
// not get sampled during scaling which would lead to edge artifacts.
|
||||
writePos = glm::ivec2 {0, writePos.y + rowHeight + 1};
|
||||
// Leave 1 pixel of space between glyphs so that pixels from adjacent glyphs will not
|
||||
// get sampled during scaling and interpolation, which would lead to edge artifacts.
|
||||
writePos = glm::ivec2 {1, writePos.y + rowHeight + 1};
|
||||
rowHeight = 0;
|
||||
}
|
||||
|
||||
if (writePos.x + size.x >= textureSize.x || writePos.y + size.y >= textureSize.y)
|
||||
if (writePos.x + size.x + 1 > textureSize.x || writePos.y + size.y + 1 > textureSize.y)
|
||||
return false; // No it still won't fit.
|
||||
|
||||
cursor_out = writePos;
|
||||
cursorOut = writePos;
|
||||
// Leave 1 pixel of space between glyphs.
|
||||
writePos.x += size.x + 1;
|
||||
|
||||
|
@ -590,9 +583,9 @@ void Font::FontTexture::initTexture()
|
|||
// glyphs will not be visible. That would otherwise lead to edge artifacts as these pixels
|
||||
// would get sampled during scaling.
|
||||
std::vector<uint8_t> texture(textureSize.x * textureSize.y * 4, 0);
|
||||
textureId = Renderer::getInstance()->createTexture(0, Renderer::TextureType::RED, true,
|
||||
linearMagnify, false, false, textureSize.x,
|
||||
textureSize.y, &texture[0]);
|
||||
textureId =
|
||||
Renderer::getInstance()->createTexture(0, Renderer::TextureType::RED, true, true, false,
|
||||
false, textureSize.x, textureSize.y, &texture[0]);
|
||||
}
|
||||
|
||||
void Font::FontTexture::deinitTexture()
|
||||
|
@ -669,28 +662,26 @@ void Font::unloadTextures()
|
|||
}
|
||||
|
||||
void Font::getTextureForNewGlyph(const glm::ivec2& glyphSize,
|
||||
FontTexture*& tex_out,
|
||||
glm::ivec2& cursor_out)
|
||||
FontTexture*& texOut,
|
||||
glm::ivec2& cursorOut)
|
||||
{
|
||||
if (mTextures.size()) {
|
||||
// Check if the most recent texture has space available for the glyph.
|
||||
tex_out = mTextures.back().get();
|
||||
texOut = mTextures.back().get();
|
||||
|
||||
// Will this one work?
|
||||
if (tex_out->findEmpty(glyphSize, cursor_out))
|
||||
if (texOut->findEmpty(glyphSize, cursorOut))
|
||||
return; // Yes.
|
||||
}
|
||||
|
||||
mTextures.emplace_back(
|
||||
std::make_unique<FontTexture>(static_cast<int>(std::round(mFontSize)), mLinearMagnify));
|
||||
tex_out = mTextures.back().get();
|
||||
tex_out->initTexture();
|
||||
mTextures.emplace_back(std::make_unique<FontTexture>(static_cast<int>(std::round(mFontSize))));
|
||||
texOut = mTextures.back().get();
|
||||
texOut->initTexture();
|
||||
|
||||
bool ok {tex_out->findEmpty(glyphSize, cursor_out)};
|
||||
if (!ok) {
|
||||
if (!texOut->findEmpty(glyphSize, cursorOut)) {
|
||||
LOG(LogError) << "Glyph too big to fit on a new texture (glyph size > "
|
||||
<< tex_out->textureSize.x << ", " << tex_out->textureSize.y << ")";
|
||||
tex_out = nullptr;
|
||||
<< texOut->textureSize.x << ", " << texOut->textureSize.y << ")";
|
||||
texOut = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -770,15 +761,13 @@ Font::Glyph* Font::getGlyph(const unsigned int id)
|
|||
Glyph& glyph {mGlyphMap[id]};
|
||||
|
||||
glyph.texture = tex;
|
||||
glyph.texPos = glm::vec2 {cursor.x / static_cast<float>(tex->textureSize.x),
|
||||
cursor.y / static_cast<float>(tex->textureSize.y)};
|
||||
glyph.texSize = glm::vec2 {glyphSize.x / static_cast<float>(tex->textureSize.x),
|
||||
glyphSize.y / static_cast<float>(tex->textureSize.y)};
|
||||
glyph.advance = glm::vec2 {static_cast<float>(glyphSlot->metrics.horiAdvance) / 64.0f,
|
||||
static_cast<float>(glyphSlot->metrics.vertAdvance) / 64.0f};
|
||||
glyph.bearing = glm::vec2 {static_cast<float>(glyphSlot->metrics.horiBearingX) / 64.0f,
|
||||
static_cast<float>(glyphSlot->metrics.horiBearingY) / 64.0f};
|
||||
glyph.rows = glyphSlot->bitmap.rows;
|
||||
glyph.texPos = {cursor.x / static_cast<float>(tex->textureSize.x),
|
||||
cursor.y / static_cast<float>(tex->textureSize.y)};
|
||||
glyph.texSize = {glyphSize.x / static_cast<float>(tex->textureSize.x),
|
||||
glyphSize.y / static_cast<float>(tex->textureSize.y)};
|
||||
glyph.advance = {glyphSlot->metrics.horiAdvance >> 6, glyphSlot->metrics.vertAdvance >> 6};
|
||||
glyph.bearing = {glyphSlot->metrics.horiBearingX >> 6, glyphSlot->metrics.horiBearingY >> 6};
|
||||
glyph.rows = glyphSize.y;
|
||||
|
||||
// Upload glyph bitmap to texture.
|
||||
mRenderer->updateTexture(tex->textureId, 0, Renderer::TextureType::RED, cursor.x, cursor.y,
|
||||
|
|
|
@ -38,9 +38,7 @@ class Font : public IReloadable
|
|||
{
|
||||
public:
|
||||
virtual ~Font();
|
||||
static std::shared_ptr<Font> get(float size,
|
||||
const std::string& path = getDefaultPath(),
|
||||
const bool linearMagnify = false);
|
||||
static std::shared_ptr<Font> get(float size, const std::string& path = getDefaultPath());
|
||||
static float getMiniFont()
|
||||
{
|
||||
static float sMiniFont {0.030f *
|
||||
|
@ -133,7 +131,6 @@ public:
|
|||
unsigned int properties,
|
||||
const std::shared_ptr<Font>& orig,
|
||||
const float maxHeight = 0.0f,
|
||||
const bool linearMagnify = false,
|
||||
const float sizeMultiplier = 1.0f,
|
||||
const bool fontSizeDimmed = false);
|
||||
|
||||
|
@ -143,7 +140,7 @@ public:
|
|||
static size_t getTotalMemUsage();
|
||||
|
||||
private:
|
||||
Font(float size, const std::string& path, const bool linearMagnify);
|
||||
Font(float size, const std::string& path);
|
||||
static void initLibrary();
|
||||
|
||||
struct FontTexture {
|
||||
|
@ -151,11 +148,10 @@ private:
|
|||
glm::ivec2 textureSize;
|
||||
glm::ivec2 writePos;
|
||||
int rowHeight;
|
||||
bool linearMagnify;
|
||||
|
||||
FontTexture(const int mFontSize, const bool linearMagnifyArg);
|
||||
FontTexture(const int mFontSize);
|
||||
~FontTexture();
|
||||
bool findEmpty(const glm::ivec2& size, glm::ivec2& cursor_out);
|
||||
bool findEmpty(const glm::ivec2& size, glm::ivec2& cursorOut);
|
||||
|
||||
// You must call initTexture() after creating a FontTexture to get a textureId.
|
||||
// Initializes the OpenGL texture according to this FontTexture's settings,
|
||||
|
@ -178,8 +174,8 @@ private:
|
|||
FontTexture* texture;
|
||||
glm::vec2 texPos;
|
||||
glm::vec2 texSize; // In texels.
|
||||
glm::vec2 advance;
|
||||
glm::vec2 bearing;
|
||||
glm::ivec2 advance;
|
||||
glm::ivec2 bearing;
|
||||
int rows;
|
||||
};
|
||||
|
||||
|
@ -188,8 +184,8 @@ private:
|
|||
void unloadTextures();
|
||||
|
||||
void getTextureForNewGlyph(const glm::ivec2& glyphSize,
|
||||
FontTexture*& tex_out,
|
||||
glm::ivec2& cursor_out);
|
||||
FontTexture*& texOut,
|
||||
glm::ivec2& cursorOut);
|
||||
|
||||
std::vector<std::string> getFallbackFontPaths();
|
||||
FT_Face getFaceForChar(unsigned int id);
|
||||
|
@ -203,7 +199,7 @@ private:
|
|||
void clearFaceCache() { mFaceCache.clear(); }
|
||||
|
||||
static inline FT_Library sLibrary {nullptr};
|
||||
static inline std::map<std::tuple<float, std::string, bool>, std::weak_ptr<Font>> sFontMap;
|
||||
static inline std::map<std::tuple<float, std::string>, std::weak_ptr<Font>> sFontMap;
|
||||
|
||||
Renderer* mRenderer;
|
||||
std::vector<std::unique_ptr<FontTexture>> mTextures;
|
||||
|
@ -212,7 +208,6 @@ private:
|
|||
|
||||
const std::string mPath;
|
||||
float mFontSize;
|
||||
const bool mLinearMagnify;
|
||||
float mLetterHeight;
|
||||
int mMaxGlyphHeight;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue