It works!

This commit is contained in:
Henrik Rydgård committed 2017-06-05 23:09:12 +02:00
1 parent 0bf92a4fa2
commit 0d3d642371
9 files changed
+89 -76

No files matched your search

+1 -1
View File
@@ -676,7 +676,7 @@ void GameSettingsScreen::CreateViews() {
systemSettings->Add(new ItemHeader(sy->T("General")));
#ifdef __ANDROID__
#if PPSSPP_PLATFORM(ANDROID)
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
static const char *screenRotation[] = {"Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed"};
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager()));
+3 -3
View File
@@ -345,16 +345,16 @@ NewLanguageScreen::NewLanguageScreen(const std::string &title) : ListPopupScreen
continue;
}
#ifndef _WIN32
// ar_AE only works on Windows.
#if !(defined(USING_QT_UI) || PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID))
if (tempLangs[i].name.find("ar_AE") != std::string::npos) {
continue;
}
// Farsi also only works on Windows.
if (tempLangs[i].name.find("fa_IR") != std::string::npos) {
continue;
}
#endif
FileInfo lang = tempLangs[i];
langs_.push_back(lang);
+2 -2
View File
@@ -659,7 +659,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
// JavaEGL
extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, jobject obj) {
// Need to get the local JNI env for the graphics thread. Used later in draw_text_android.
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_4);
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6);
if (res != JNI_OK) {
ELOG("GetEnv failed: %d", res);
}
@@ -1031,7 +1031,7 @@ extern "C" bool JNICALL Java_org_ppsspp_ppsspp_NativeActivity_runEGLRenderLoop(J
ANativeWindow *wnd = ANativeWindow_fromSurface(env, _surf);
// Need to get the local JNI env for the graphics thread. Used later in draw_text_android.
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_4);
int res = javaVM->GetEnv((void **)&jniEnvGraphics, JNI_VERSION_1_6);
if (res != JNI_OK) {
ELOG("GetEnv failed: %d", res);
}
+2 -1
View File
@@ -8,5 +8,6 @@
extern JNIEnv *jniEnvMain;
extern JNIEnv *jniEnvGraphics;
extern JavaVM *javaVM;
#endif
#endif
+38 -35
View File
@@ -4,43 +4,46 @@ import android.graphics.*;
import java.nio.ByteBuffer;
public class TextRenderer {
public static int measureText(String string, float textSize) {
Paint p;
p = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect bound = new Rect();
p.setTextSize(textSize);
p.getTextBounds(string, 0, string.length(), bound);
return (bound.width() << 16) | bound.height();
}
public static short[] renderText(String string, float textSize) {
Paint p;
p = new Paint(Paint.ANTI_ALIAS_FLAG);
Rect bound = new Rect();
p.setTextSize(textSize);
p.getTextBounds(string, 0, string.length(), bound);
float baseline = -p.ascent();
Bitmap bmp = Bitmap.createBitmap(bound.width(), bound.height(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(bmp);
private static Paint p;
private static Paint bg;
static {
p = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.WHITE);
canvas.drawText(string, 0, baseline, p);
bg = new Paint();
bg.setColor(Color.BLACK);
}
public static int measureText(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 = bound.height();
// 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;
h += 2;
return (w << 16) | h;
}
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 = bound.height();
// 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;
h += 2;
int bufSize = bmp.getRowBytes() * bmp.getHeight() * 2; // 2 = sizeof(ARGB_4444)
ByteBuffer buf = ByteBuffer.allocate(bufSize);
bmp.copyPixelsFromBuffer(buf);
byte[] bytes = buf.array();
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);
p.setColor(Color.WHITE);
canvas.drawText(string, 1, -bound.top + 1, p);
// Output array size must match return value of measureText
short[] output = new short[bound.width() * bound.height()];
// 16-bit pixels but stored as bytes.
for (int y = 0; y < bound.height(); y++) {
int srcOffset = y * bmp.getRowBytes();
int dstOffset = y * bound.width();
for (int x = 0; x < bound.width(); x++) {
int val = bytes[srcOffset + x * 2];
output[dstOffset + x] = (short)val;
}
}
return output;
int [] pixels = new int[w * h];
bmp.getPixels(pixels, 0, w, 0, 0, w, h);
return pixels;
}
}
+3 -1
View File
@@ -35,9 +35,11 @@ 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;
}
@@ -55,4 +57,4 @@ TextDrawer *TextDrawer::Create(Draw::DrawContext *draw) {
drawer = nullptr;
}
return drawer;
}
}
+37 -30
View File
@@ -9,6 +9,7 @@
#include "gfx_es2/draw_text_android.h"
#include "android/jni/app-android.h"
#include <assert.h>
#if PPSSPP_PLATFORM(ANDROID)
@@ -17,20 +18,25 @@
TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) {
env_ = jniEnvGraphics;
const char *textRendererClassName = "org/ppsspp/ppsspp/TextRenderer";
cls_textRenderer = env_->FindClass(textRendererClassName);
jclass localClass = env_->FindClass(textRendererClassName);
cls_textRenderer = reinterpret_cast<jclass>(env_->NewGlobalRef(localClass));
ILOG("cls_textRender: %p", cls_textRenderer);
if (cls_textRenderer) {
method_measureText = env_->GetStaticMethodID(cls_textRenderer, "measureText", "(Ljava/lang/String;F)I");
method_measureText = env_->GetStaticMethodID(cls_textRenderer, "measureText", "(Ljava/lang/String;D)I");
ILOG("method_measureText: %p", method_measureText);
method_renderText = env_->GetStaticMethodID(cls_textRenderer, "renderText", "(Ljava/lang/String;F)[S");
method_renderText = env_->GetStaticMethodID(cls_textRenderer, "renderText", "(Ljava/lang/String;D)[I");
ILOG("method_renderText: %p", method_renderText);
} else {
ELOG("Failed to find class: %s", textRendererClassName);
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.
// At worst we leak one ref...
// env_->DeleteGlobalRef(cls_textRenderer);
ClearCache();
}
@@ -50,9 +56,10 @@ uint32_t TextDrawerAndroid::SetFont(const char *fontName, int size, int flags) {
return fontHash;
}
curSize_ = size;
curSize_ = (float)((6 + size) / dpiScale_) * 96.0f / 72.f;
AndroidFontEntry entry;
entry.size = curSize_;
fontMap_[fontHash] = entry;
fontHash_ = fontHash;
return fontHash;
@@ -62,7 +69,7 @@ void TextDrawerAndroid::SetFont(uint32_t fontHandle) {
uint32_t fontHash = fontHandle;
auto iter = fontMap_.find(fontHash);
if (iter != fontMap_.end()) {
curSize_ = iter->second.size;
curSize_ = iter->second.size / dpiScale_;
}
}
@@ -74,9 +81,9 @@ void TextDrawerAndroid::MeasureString(const char *str, size_t len, float *w, flo
std::string stdstring(str, len);
jstring jstr = env_->NewStringUTF(stdstring.c_str());
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, curSize_);
*w = (size >> 16) * fontScaleX_;
*h = (size & 0xFFFF) * fontScaleY_;
env_->DeleteLocalRef(jstr);
*w = (size >> 16) * fontScaleX_ * dpiScale_;
*h = (size & 0xFFFF) * fontScaleY_ * dpiScale_;
}
void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bounds &bounds, float *w, float *h, int align) {
@@ -88,15 +95,18 @@ void TextDrawerAndroid::MeasureStringRect(const char *str, size_t len, const Bou
jstring jstr = env_->NewStringUTF(toMeasure.c_str());
uint32_t size = env_->CallStaticIntMethod(cls_textRenderer, method_measureText, jstr, curSize_);
*w = (size >> 16) * fontScaleX_;
*h = (size & 0xFFFF) * fontScaleY_;
env_->DeleteLocalRef(jstr);
*w = (size >> 16) * fontScaleX_ * dpiScale_;
*h = (size & 0xFFFF) * fontScaleY_ * dpiScale_;
}
void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, float y, uint32_t color, int align) {
using namespace Draw;
if (!strlen(str))
return;
JNIEnv *env;
int result = javaVM->GetEnv((void **)&env, JNI_VERSION_1_6);
assert(env == env_);
uint32_t stringHash = hash::Fletcher((const uint8_t *)str, strlen(str));
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
@@ -112,10 +122,12 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
draw_->BindTexture(0, entry->texture);
} else {
jstring jstr = env_->NewStringUTF(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) * fontScaleX_;
int imageHeight = (size & 0xFFFF) * fontScaleY_;
jshortArray imageData = (jshortArray)env_->CallStaticObjectMethod(cls_textRenderer, method_renderText, jstr, curSize_);
int imageWidth = (size >> 16);
int imageHeight = (size & 0xFFFF);
jintArray imageData = (jintArray)env_->CallStaticObjectMethod(cls_textRenderer, method_renderText, jstr, curSize_);
env_->DeleteLocalRef(jstr);
entry = new TextStringEntry();
@@ -132,23 +144,25 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
desc.mipLevels = 1;
uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight];
jshort* jimage = env_->GetShortArrayElements(imageData, nullptr);
jint* jimage = env_->GetIntArrayElements(imageData, nullptr);
int arraySize = env_->GetArrayLength(imageData);
assert(arraySize == imageWidth * imageHeight);
for (int x = 0; x < entry->bmWidth; x++) {
for (int y = 0; y < entry->bmHeight; y++) {
int v = jimage[imageWidth * y + x];
v = (v << 4) | v;
v = (v << 8) | v;
bitmapData[entry->bmWidth * y + x] = v;
uint32_t v = jimage[imageWidth * y + x];
v = 0xFFF0 | ((v >> 12) & 0xF); // Just grab some bits from the green channel.
bitmapData[entry->bmWidth * y + x] = (uint16_t)v;
}
}
env_->ReleaseShortArrayElements(imageData, jimage, 0);
env_->ReleaseIntArrayElements(imageData, jimage, 0);
desc.initData.push_back((uint8_t *)bitmapData);
entry->texture = draw_->CreateTexture(desc);
delete[] bitmapData;
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
draw_->BindTexture(0, entry->texture);
}
float w = entry->bmWidth * fontScaleX_;
float h = entry->bmHeight * fontScaleY_;
float w = entry->bmWidth * fontScaleX_ * dpiScale_;
float h = entry->bmHeight * fontScaleY_ * dpiScale_;
DrawBuffer::DoAlign(align, &x, &y, &w, &h);
target.DrawTexRect(x, y, x + w, y + h, 0.0f, 0.0f, 1.0f, 1.0f, color);
target.Flush(true);
@@ -160,7 +174,7 @@ void TextDrawerAndroid::ClearCache() {
iter.second->texture->Release();
}
cache_.clear();
sizeCache_.clear();
fontMap_.clear();
}
void TextDrawerAndroid::DrawStringRect(DrawBuffer &target, const char *str, const Bounds &bounds, uint32_t color, int align) {
@@ -191,6 +205,7 @@ 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");
dpiScale_ = newDpiScale;
ClearCache();
RecreateFonts();
@@ -207,14 +222,6 @@ void TextDrawerAndroid::OncePerFrame() {
iter++;
}
}
for (auto iter = sizeCache_.begin(); iter != sizeCache_.end(); ) {
if (frameCount_ - iter->second->lastUsedFrame > 100) {
sizeCache_.erase(iter++);
} else {
iter++;
}
}
}
}
+2 -3
View File
@@ -37,7 +37,7 @@ protected:
jclass cls_textRenderer;
jmethodID method_measureText;
jmethodID method_renderText;
float curSize_;
double curSize_;
uint32_t fontHash_;
@@ -45,7 +45,6 @@ protected:
// The key is the CityHash of the string xor the fontHash_.
std::map<uint32_t, std::unique_ptr<TextStringEntry>> cache_;
std::map<uint32_t, std::unique_ptr<TextMeasureEntry>> sizeCache_;
};
#endif
#endif
+1
View File
@@ -675,6 +675,7 @@ OpenGLTexture::OpenGLTexture(const TextureDesc &desc) {
type_ = desc.type;
target_ = TypeToTarget(desc.type);
canWrap_ = isPowerOf2(width_) && isPowerOf2(height_);
mipLevels_ = desc.mipLevels;
if (!desc.initData.size())
return;