mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Address comments, make things closer to the Win32 code. Things work better.
This commit is contained in:
parent
62c747bc00
commit
3a640ff8aa
11 changed files with 125 additions and 61 deletions
|
@ -345,6 +345,8 @@ NewLanguageScreen::NewLanguageScreen(const std::string &title) : ListPopupScreen
|
|||
continue;
|
||||
}
|
||||
|
||||
// We only support Arabic on platforms where we have support for the native text rendering
|
||||
// APIs, as proper Arabic support is way too difficult to implement ourselves.
|
||||
#if !(defined(USING_QT_UI) || PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID))
|
||||
if (tempLangs[i].name.find("ar_AE") != std::string::npos) {
|
||||
continue;
|
||||
|
|
|
@ -1110,6 +1110,7 @@ retry:
|
|||
graphicsContext = nullptr;
|
||||
renderLoopRunning = false;
|
||||
WLOG("Render loop function exited.");
|
||||
jniEnvGraphics = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ public class TextRenderer {
|
|||
bg = new Paint();
|
||||
bg.setColor(Color.BLACK);
|
||||
}
|
||||
public static int measureText(String string, double textSize) {
|
||||
private static Point measure(String string, double textSize) {
|
||||
Rect bound = new Rect();
|
||||
p.setTextSize((float)textSize);
|
||||
p.getTextBounds(string, 0, string.length(), bound);
|
||||
|
@ -20,20 +20,22 @@ public class TextRenderer {
|
|||
int h = (int)(p.descent() - p.ascent() + 2.0f);
|
||||
// Round width up to even already here to avoid annoyances from odd-width 16-bit textures which
|
||||
// OpenGL does not like - each line must be 4-byte aligned
|
||||
w = (w + 3) & ~1;
|
||||
return (w << 16) | h;
|
||||
w = (w + 5) & ~1;
|
||||
Point p = new Point();
|
||||
p.x = w;
|
||||
p.y = h;
|
||||
return p;
|
||||
}
|
||||
public static int measureText(String string, double textSize) {
|
||||
Point s = measure(string, textSize);
|
||||
return (s.x << 16) | s.y;
|
||||
}
|
||||
public static int[] renderText(String string, double textSize) {
|
||||
Rect bound = new Rect();
|
||||
p.setTextSize((float)textSize);
|
||||
p.getTextBounds(string, 0, string.length(), bound);
|
||||
int w = bound.width();
|
||||
int h = (int)(p.descent() - p.ascent() + 2.0f);
|
||||
// Round width up to even already here to avoid annoyances from odd-width 16-bit textures which
|
||||
// OpenGL does not like - each line must be 4-byte aligned
|
||||
w = (w + 3) & ~1;
|
||||
Point s = measure(string, textSize);
|
||||
|
||||
int w = s.x;
|
||||
int h = s.y;
|
||||
|
||||
float baseline = -p.ascent();
|
||||
Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bmp);
|
||||
canvas.drawRect(0.0f, 0.0f, w, h, bg);
|
||||
|
|
|
@ -75,7 +75,7 @@ LOCAL_SRC_FILES :=\
|
|||
gfx_es2/draw_buffer.cpp.arm \
|
||||
gfx_es2/draw_text.cpp.arm \
|
||||
gfx_es2/draw_text_android.cpp.arm \
|
||||
gfx/GLStateCache.cpp.arm \
|
||||
gfx/GLStateCache.cpp.arm \
|
||||
gfx/gl_debug_log.cpp \
|
||||
gfx/gl_lost_manager.cpp \
|
||||
gfx/texture_atlas.cpp \
|
||||
|
|
|
@ -35,11 +35,9 @@ void TextDrawer::SetFontScale(float xscale, float yscale) {
|
|||
|
||||
float TextDrawer::CalculateDPIScale() {
|
||||
float scale = g_dpi_scale;
|
||||
#if !PPSSPP_PLATFORM(ANDROID)
|
||||
if (scale >= 1.0f) {
|
||||
scale = 1.0f;
|
||||
}
|
||||
#endif
|
||||
return scale;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ protected:
|
|||
|
||||
Draw::DrawContext *draw_;
|
||||
virtual void ClearCache() = 0;
|
||||
virtual void RecreateFonts() = 0; // On DPI change
|
||||
void WrapString(std::string &out, const char *str, float maxWidth);
|
||||
|
||||
int frameCount_;
|
||||
|
|
|
@ -29,12 +29,11 @@ TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw)
|
|||
} else {
|
||||
ELOG("Failed to find class: '%s'", textRendererClassName);
|
||||
}
|
||||
curSize_ = 12;
|
||||
dpiScale_ = 1.0f;
|
||||
}
|
||||
|
||||
TextDrawerAndroid::~TextDrawerAndroid() {
|
||||
// Not sure why we can't do this but it crashes.
|
||||
// Not sure why we can't do this but it crashes. Likely some deeper threading issue.
|
||||
// At worst we leak one ref...
|
||||
// env_->DeleteGlobalRef(cls_textRenderer);
|
||||
ClearCache();
|
||||
|
@ -45,8 +44,9 @@ bool TextDrawerAndroid::IsReady() const {
|
|||
}
|
||||
|
||||
uint32_t TextDrawerAndroid::SetFont(const char *fontName, int size, int flags) {
|
||||
// We will only use the default font
|
||||
uint32_t fontHash = 0; //hash::Fletcher((const uint8_t *)fontName, strlen(fontName));
|
||||
// We will only use the default font but just for consistency let's still involve
|
||||
// the font name.
|
||||
uint32_t fontHash = hash::Fletcher((const uint8_t *)fontName, strlen(fontName));
|
||||
fontHash ^= size;
|
||||
fontHash ^= flags << 10;
|
||||
|
||||
|
@ -56,10 +56,9 @@ uint32_t TextDrawerAndroid::SetFont(const char *fontName, int size, int flags) {
|
|||
return fontHash;
|
||||
}
|
||||
|
||||
curSize_ = (float)((6 + size) / dpiScale_) * 96.0f / 72.f;
|
||||
// Just chose a factor that looks good, don't know what unit size is in anyway.
|
||||
AndroidFontEntry entry;
|
||||
entry.size = curSize_;
|
||||
|
||||
entry.size = (float)(size * 1.4f) / dpiScale_;
|
||||
fontMap_[fontHash] = entry;
|
||||
fontHash_ = fontHash;
|
||||
return fontHash;
|
||||
|
@ -69,7 +68,9 @@ void TextDrawerAndroid::SetFont(uint32_t fontHandle) {
|
|||
uint32_t fontHash = fontHandle;
|
||||
auto iter = fontMap_.find(fontHash);
|
||||
if (iter != fontMap_.end()) {
|
||||
curSize_ = iter->second.size / dpiScale_;
|
||||
fontHash_ = fontHandle;
|
||||
} else {
|
||||
ELOG("Invalid font handle %08x", fontHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,31 +78,85 @@ std::string TextDrawerAndroid::NormalizeString(std::string str) {
|
|||
return ReplaceAll(str, "&&", "&");
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::RecreateFonts() {
|
||||
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, float *h) {
|
||||
std::string text(NormalizeString(std::string(str, len)));
|
||||
jstring jstr = env_->NewStringUTF(text.c_str());
|
||||
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, curSize_);
|
||||
env_->DeleteLocalRef(jstr);
|
||||
*w = (size >> 16) * fontScaleX_ * dpiScale_;
|
||||
*h = (size & 0xFFFF) * fontScaleY_ * dpiScale_;
|
||||
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, len);
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
float scaledSize = 14;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
scaledSize = iter->second.size;
|
||||
} else {
|
||||
ELOG("Missing font");
|
||||
}
|
||||
std::string text(NormalizeString(std::string(str, len)));
|
||||
jstring jstr = env_->NewStringUTF(text.c_str());
|
||||
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, scaledSize);
|
||||
env_->DeleteLocalRef(jstr);
|
||||
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = (size >> 16);
|
||||
entry->height = (size & 0xFFFF);
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
*w = entry->width * fontScaleX_ * dpiScale_;
|
||||
*h = entry->height * fontScaleY_ * dpiScale_;
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bounds &bounds, float *w, float *h, int align) {
|
||||
std::string toMeasure(NormalizeString(std::string(str, len)));
|
||||
double scaledSize = 14;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
scaledSize = iter->second.size;
|
||||
} else {
|
||||
ELOG("Missing font");
|
||||
}
|
||||
|
||||
std::string toMeasure = std::string(str, len);
|
||||
if (align & FLAG_WRAP_TEXT) {
|
||||
bool rotated = (align & (ROTATE_90DEG_LEFT | ROTATE_90DEG_RIGHT)) != 0;
|
||||
WrapString(toMeasure, toMeasure.c_str(), rotated ? bounds.h : bounds.w);
|
||||
}
|
||||
|
||||
jstring jstr = env_->NewStringUTF(toMeasure.c_str());
|
||||
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, curSize_);
|
||||
env_->DeleteLocalRef(jstr);
|
||||
*w = (size >> 16) * fontScaleX_ * dpiScale_;
|
||||
*h = (size & 0xFFFF) * fontScaleY_ * dpiScale_;
|
||||
std::vector<std::string> lines;
|
||||
SplitString(toMeasure, '\n', lines);
|
||||
float total_w = 0.0f;
|
||||
float total_h = 0.0f;
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
uint32_t stringHash = hash::Fletcher((const uint8_t *)&lines[i][0], lines[i].length());
|
||||
uint32_t entryHash = stringHash ^ fontHash_;
|
||||
|
||||
TextMeasureEntry *entry;
|
||||
auto iter = sizeCache_.find(entryHash);
|
||||
if (iter != sizeCache_.end()) {
|
||||
entry = iter->second.get();
|
||||
} else {
|
||||
std::string text(NormalizeString(lines[i]));
|
||||
jstring jstr = env_->NewStringUTF(text.c_str());
|
||||
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, scaledSize);
|
||||
env_->DeleteLocalRef(jstr);
|
||||
int sizecx = size >> 16;
|
||||
int sizecy = size & 0xFFFF;
|
||||
entry = new TextMeasureEntry();
|
||||
entry->width = sizecx;
|
||||
entry->height = sizecy;
|
||||
sizeCache_[entryHash] = std::unique_ptr<TextMeasureEntry>(entry);
|
||||
}
|
||||
entry->lastUsedFrame = frameCount_;
|
||||
|
||||
if (total_w < entry->width * fontScaleX_) {
|
||||
total_w = entry->width * fontScaleX_;
|
||||
}
|
||||
total_h += entry->height * fontScaleY_;
|
||||
}
|
||||
*w = total_w * dpiScale_;
|
||||
*h = total_h * dpiScale_;
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) {
|
||||
|
@ -126,13 +181,19 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
|
|||
entry->lastUsedFrame = frameCount_;
|
||||
draw_->BindTexture(0, entry->texture);
|
||||
} else {
|
||||
double size;
|
||||
auto iter = fontMap_.find(fontHash_);
|
||||
if (iter != fontMap_.end()) {
|
||||
size = iter->second.size;
|
||||
} else {
|
||||
ELOG("Missing font");
|
||||
}
|
||||
|
||||
jstring jstr = env_->NewStringUTF(text.c_str());
|
||||
int len = (int)env_->GetStringUTFLength(jstr);
|
||||
ILOG("UTF len: %d", len);
|
||||
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, curSize_);
|
||||
int imageWidth = (size >> 16);
|
||||
int imageHeight = (size & 0xFFFF);
|
||||
jintArray imageData = (jintArray)env_->CallStaticObjectMethod(cls_textRenderer, method_renderText, jstr, curSize_);
|
||||
uint32_t textSize = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, size);
|
||||
int imageWidth = (textSize >> 16);
|
||||
int imageHeight = (textSize & 0xFFFF);
|
||||
jintArray imageData = (jintArray)env_->CallStaticObjectMethod(cls_textRenderer, method_renderText, jstr, size);
|
||||
env_->DeleteLocalRef(jstr);
|
||||
|
||||
entry = new TextStringEntry();
|
||||
|
@ -179,7 +240,7 @@ void TextDrawerAndroid::ClearCache() {
|
|||
iter.second->texture->Release();
|
||||
}
|
||||
cache_.clear();
|
||||
fontMap_.clear();
|
||||
sizeCache_.clear();
|
||||
}
|
||||
|
||||
void TextDrawerAndroid::DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align) {
|
||||
|
@ -210,10 +271,10 @@ void TextDrawerAndroid::OncePerFrame() {
|
|||
// If DPI changed (small-mode, future proper monitor DPI support), drop everything.
|
||||
float newDpiScale = CalculateDPIScale();
|
||||
if (newDpiScale != dpiScale_) {
|
||||
ILOG("Scale changed - recreating fonts");
|
||||
ILOG("Scale changed - wiping cache");
|
||||
dpiScale_ = newDpiScale;
|
||||
ClearCache();
|
||||
RecreateFonts();
|
||||
fontMap_.clear(); // size is precomputed using dpiScale_.
|
||||
}
|
||||
|
||||
// Drop old strings. Use a prime number to reduce clashing with other rhythms
|
||||
|
@ -227,6 +288,14 @@ void TextDrawerAndroid::OncePerFrame() {
|
|||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
|
||||
if (frameCount_ - iter->second->lastUsedFrame > 100) {
|
||||
sizeCache_.erase(iter++);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <jni.h>
|
||||
|
||||
struct AndroidFontEntry {
|
||||
float size;
|
||||
double size;
|
||||
};
|
||||
|
||||
class TextDrawerAndroid : public TextDrawer {
|
||||
|
@ -30,7 +30,6 @@ public:
|
|||
|
||||
protected:
|
||||
void ClearCache() override;
|
||||
void RecreateFonts() override; // On DPI change
|
||||
|
||||
private:
|
||||
std::string NormalizeString(std::string str);
|
||||
|
@ -40,14 +39,14 @@ private:
|
|||
jclass cls_textRenderer;
|
||||
jmethodID method_measureText;
|
||||
jmethodID method_renderText;
|
||||
double curSize_;
|
||||
|
||||
uint32_t fontHash_;
|
||||
uint32_t fontHash_; // Just the size.
|
||||
|
||||
std::map<uint32_t, AndroidFontEntry> fontMap_;
|
||||
|
||||
// The key is the CityHash of the string xor the fontHash_.
|
||||
// The key is the CityHash of the string xor the fontHash_ (though the fontHash_ is just the size).
|
||||
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
|
||||
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <QtGui/QFontMetrics>
|
||||
#include <QtOpenGL/QGLWidget>
|
||||
|
||||
|
||||
TextDrawerQt::TextDrawerQt(Draw::DrawContext *draw) : TextDrawer(draw) {
|
||||
}
|
||||
|
||||
|
@ -46,10 +45,6 @@ void TextDrawerQt::SetFont(uint32_t fontHandle) {
|
|||
|
||||
}
|
||||
|
||||
void TextDrawerQt::RecreateFonts() {
|
||||
|
||||
}
|
||||
|
||||
void TextDrawerQt::MeasureString(const char *str, size_t len, float *w, float *h) {
|
||||
QFont* font = fontMap_.find(fontHash_)->second;
|
||||
QFontMetrics fm(*font);
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
|
||||
protected:
|
||||
void ClearCache() override;
|
||||
void RecreateFonts() override; // On DPI change
|
||||
|
||||
uint32_t fontHash_;
|
||||
std::map<uint32_t, QFont *> fontMap_;
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
|
||||
protected:
|
||||
void ClearCache() override;
|
||||
void RecreateFonts() override; // On DPI change
|
||||
void RecreateFonts(); // On DPI change
|
||||
|
||||
TextDrawerContext *ctx_;
|
||||
std::map<uint32_t, std::unique_ptr<TextDrawerFontContext>> fontMap_;
|
||||
|
|
Loading…
Add table
Reference in a new issue