UI: Support a second texture for just fonts.

Will still allow using fonts between both.
This commit is contained in:
Unknown W. Brackets 2021-10-16 16:47:24 -07:00
parent 593241b50f
commit eb81d5b30b
7 changed files with 91 additions and 36 deletions

View file

@ -14,11 +14,10 @@
#include "Common/Log.h"
#include "Common/StringUtils.h"
DrawBuffer::DrawBuffer() : count_(0), atlas(0) {
DrawBuffer::DrawBuffer() {
verts_ = new Vertex[MAX_VERTS];
fontscalex = 1.0f;
fontscaley = 1.0f;
inited_ = false;
}
DrawBuffer::~DrawBuffer() {
@ -482,7 +481,9 @@ float AtlasWordWrapper::MeasureWidth(const char *str, size_t bytes) {
}
void DrawBuffer::MeasureTextCount(FontID font, const char *text, int count, float *w, float *h) {
const AtlasFont *atlasfont = atlas->getFont(font);
const AtlasFont *atlasfont = fontAtlas_->getFont(font);
if (!atlasfont)
atlasfont = atlas->getFont(font);
if (!atlasfont) {
*w = 0.0f;
*h = 0.0f;
@ -533,7 +534,9 @@ void DrawBuffer::MeasureTextRect(FontID font_id, const char *text, int count, co
std::string toMeasure = std::string(text, count);
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
if (wrap) {
const AtlasFont *font = atlas->getFont(font_id);
const AtlasFont *font = fontAtlas_->getFont(font_id);
if (!font)
font = atlas->getFont(font_id);
if (!font) {
*w = 0.0f;
*h = 0.0f;
@ -582,7 +585,9 @@ void DrawBuffer::DrawTextRect(FontID font, const char *text, float x, float y, f
std::string toDraw = text;
int wrap = align & (FLAG_WRAP_TEXT | FLAG_ELLIPSIZE_TEXT);
const AtlasFont *atlasfont = atlas->getFont(font);
const AtlasFont *atlasfont = fontAtlas_->getFont(font);
if (!atlasfont)
atlasfont = atlas->getFont(font);
if (wrap && atlasfont) {
AtlasWordWrapper wrapper(*atlasfont, fontscalex, toDraw.c_str(), w, wrap);
toDraw = wrapper.Wrapped();
@ -624,7 +629,9 @@ void DrawBuffer::DrawText(FontID font, const char *text, float x, float y, Color
}
}
const AtlasFont *atlasfont = atlas->getFont(font);
const AtlasFont *atlasfont = fontAtlas_->getFont(font);
if (!atlasfont)
atlasfont = atlas->getFont(font);
if (!atlasfont)
return;
unsigned int cval;

View file

@ -110,6 +110,10 @@ public:
atlas = _atlas;
}
const Atlas *GetAtlas() const { return atlas; }
void SetFontAtlas(const Atlas *_atlas) {
fontAtlas_ = _atlas;
}
const Atlas *GetFontAtlas() const { return fontAtlas_; }
bool MeasureImage(ImageID atlas_image, float *w, float *h);
void DrawImage(ImageID atlas_image, float x, float y, float scale, Color color = COLOR(0xFFFFFF), int align = ALIGN_TOPLEFT);
@ -189,18 +193,18 @@ private:
float alpha_ = 1.0f;
std::vector<float> alphaStack_;
Draw::DrawContext *draw_;
Draw::Buffer *vbuf_;
Draw::Pipeline *pipeline_;
Draw::DrawContext *draw_ = nullptr;
Draw::Buffer *vbuf_ = nullptr;
Draw::Pipeline *pipeline_ = nullptr;
Vertex *verts_;
int count_;
const Atlas *atlas;
int count_ = 0;
const Atlas *atlas = nullptr;
const Atlas *fontAtlas_ = nullptr;
bool inited_;
float fontscalex;
float fontscaley;
bool inited_ = false;
float fontscalex = 1.0f;
float fontscaley = 1.0f;
float curZ_ = 0.0f;
};

View file

@ -39,6 +39,11 @@ void UIContext::BeginFrame() {
if (!uitexture_) {
uitexture_ = CreateTextureFromFile(draw_, "ui_atlas.zim", ImageFileType::ZIM, false);
_dbg_assert_msg_(uitexture_, "Failed to load ui_atlas.zim.\n\nPlace it in the directory \"assets\" under your PPSSPP directory.");
if (!fontTexture_) {
fontTexture_ = CreateTextureFromFile(draw_, "font_atlas.zim", ImageFileType::ZIM, false);
if (!fontTexture_)
WARN_LOG(SYSTEM, "Failed to load font_atlas.zim");
}
}
uidrawbufferTop_->SetCurZ(0.0f);
uidrawbuffer_->SetCurZ(0.0f);
@ -70,6 +75,14 @@ void UIContext::RebindTexture() const {
draw_->BindTexture(0, uitexture_->GetTexture());
}
void UIContext::BindFontTexture() const {
// Fall back to the UI texture, in case they have an old atlas.
if (fontTexture_)
draw_->BindTexture(0, fontTexture_->GetTexture());
else if (uitexture_)
draw_->BindTexture(0, uitexture_->GetTexture());
}
void UIContext::Flush() {
if (uidrawbuffer_) {
uidrawbuffer_->Flush();
@ -190,14 +203,22 @@ void UIContext::MeasureTextRect(const UI::FontStyle &style, float scaleX, float
void UIContext::DrawText(const char *str, float x, float y, uint32_t color, int align) {
if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) {
// Use the font texture if this font is in that texture instead.
bool useFontTexture = Draw()->GetFontAtlas()->getFont(fontStyle_->atlasFont) != nullptr;
if (useFontTexture) {
Flush();
BindFontTexture();
}
float sizeFactor = (float)fontStyle_->sizePts / 24.0f;
Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor);
Draw()->DrawText(fontStyle_->atlasFont, str, x, y, color, align);
if (useFontTexture)
Flush();
} else {
textDrawer_->SetFontScale(fontScaleX_, fontScaleY_);
textDrawer_->DrawString(*Draw(), str, x, y, color, align);
RebindTexture();
}
RebindTexture();
}
void UIContext::DrawTextShadow(const char *str, float x, float y, uint32_t color, int align) {
@ -208,17 +229,25 @@ void UIContext::DrawTextShadow(const char *str, float x, float y, uint32_t color
void UIContext::DrawTextRect(const char *str, const Bounds &bounds, uint32_t color, int align) {
if (!textDrawer_ || (align & FLAG_DYNAMIC_ASCII)) {
// Use the font texture if this font is in that texture instead.
bool useFontTexture = Draw()->GetFontAtlas()->getFont(fontStyle_->atlasFont) != nullptr;
if (useFontTexture) {
Flush();
BindFontTexture();
}
float sizeFactor = (float)fontStyle_->sizePts / 24.0f;
Draw()->SetFontScale(fontScaleX_ * sizeFactor, fontScaleY_ * sizeFactor);
Draw()->DrawTextRect(fontStyle_->atlasFont, str, bounds.x, bounds.y, bounds.w, bounds.h, color, align);
if (useFontTexture)
Flush();
} else {
textDrawer_->SetFontScale(fontScaleX_, fontScaleY_);
Bounds rounded = bounds;
rounded.x = floorf(rounded.x);
rounded.y = floorf(rounded.y);
textDrawer_->DrawStringRect(*Draw(), str, rounded, color, align);
RebindTexture();
}
RebindTexture();
}
void UIContext::DrawTextShadowRect(const char *str, const Bounds &bounds, uint32_t color, int align) {

View file

@ -59,6 +59,7 @@ public:
void Flush();
void RebindTexture() const;
void BindFontTexture() const;
// TODO: Support transformed bounds using stencil
void PushScissor(const Bounds &bounds);
@ -112,6 +113,7 @@ private:
Draw::Pipeline *ui_pipeline_ = nullptr;
Draw::Pipeline *ui_pipeline_notex_ = nullptr;
std::unique_ptr<ManagedTexture> uitexture_;
std::unique_ptr<ManagedTexture> fontTexture_;
DrawBuffer *uidrawbuffer_ = nullptr;
DrawBuffer *uidrawbufferTop_ = nullptr;

View file

@ -77,15 +77,14 @@ struct Style {
};
struct FontStyle {
FontStyle() : atlasFont(0), sizePts(0), flags(0) {}
FontStyle(const char *name, int size) : atlasFont(0), fontName(name), sizePts(size), flags(0) {}
FontStyle(FontID atlasFnt, const char *name, int size) : atlasFont(atlasFnt), fontName(name), sizePts(size), flags(0) {}
FontStyle() {}
FontStyle(FontID atlasFnt, const char *name, int size) : atlasFont(atlasFnt), fontName(name), sizePts(size) {}
FontID atlasFont;
FontID atlasFont{ nullptr };
// For native fonts:
std::string fontName;
int sizePts;
int flags;
int sizePts = 0;
int flags = 0;
};

View file

@ -1154,6 +1154,8 @@ static void DrawCrashDump(UIContext *ctx) {
sysName.c_str(), sysVersion, GetCompilerABI()
);
if (ctx->Draw()->GetFontAtlas()->getFont(ubuntu24))
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(.7f, .7f);
ctx->Draw()->DrawTextShadow(ubuntu24, statbuf, x, y, 0xFFFFFFFF);
y += 140;
@ -1205,6 +1207,8 @@ BREAK
CheatsInEffect() ? "Y" : "N", HLEPlugins::HasEnabled() ? "Y" : "N");
ctx->Draw()->DrawTextShadow(ubuntu24, statbuf, x, y, 0xFFFFFFFF);
ctx->Flush();
ctx->RebindTexture();
}
static void DrawAudioDebugStats(DrawBuffer *draw2d, const Bounds &bounds) {

View file

@ -132,8 +132,8 @@
// The new UI framework, for initialization
static UI::Theme ui_theme;
Atlas g_ui_atlas;
static Atlas g_ui_atlas;
static Atlas g_font_atlas;
#if PPSSPP_ARCH(ARM) && defined(__ANDROID__)
#include "../../android/jni/ArmEmitterTest.h"
@ -900,6 +900,22 @@ static void UIThemeInit() {
void RenderOverlays(UIContext *dc, void *userdata);
bool CreateGlobalPipelines();
static void LoadAtlasMetadata(Atlas &metadata, const char *filename, bool required) {
size_t atlas_data_size = 0;
if (!metadata.IsMetadataLoaded()) {
const uint8_t *atlas_data = VFSReadFile(filename, &atlas_data_size);
bool load_success = atlas_data != nullptr && metadata.Load(atlas_data, atlas_data_size);
if (!load_success) {
if (required)
ERROR_LOG(G3D, "Failed to load %s - graphics will be broken", filename);
else
WARN_LOG(G3D, "Failed to load %s", filename);
// Stumble along with broken visuals instead of dying...
}
delete[] atlas_data;
}
}
bool NativeInitGraphics(GraphicsContext *graphicsContext) {
INFO_LOG(SYSTEM, "NativeInitGraphics");
@ -914,20 +930,14 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
return false;
}
// Load the atlas.
size_t atlas_data_size = 0;
if (!g_ui_atlas.IsMetadataLoaded()) {
const uint8_t *atlas_data = VFSReadFile("ui_atlas.meta", &atlas_data_size);
bool load_success = atlas_data != nullptr && g_ui_atlas.Load(atlas_data, atlas_data_size);
if (!load_success) {
ERROR_LOG(G3D, "Failed to load ui_atlas.meta - graphics will be broken.");
// Stumble along with broken visuals instead of dying.
}
delete[] atlas_data;
}
// Load any missing atlas.
LoadAtlasMetadata(g_ui_atlas, "ui_atlas.meta", true);
LoadAtlasMetadata(g_font_atlas, "font_atlas.meta", g_ui_atlas.num_fonts == 0);
ui_draw2d.SetAtlas(&g_ui_atlas);
ui_draw2d.SetFontAtlas(&g_font_atlas);
ui_draw2d_front.SetAtlas(&g_ui_atlas);
ui_draw2d_front.SetFontAtlas(&g_font_atlas);
UIThemeInit();