Workaround for blurry text when high contrast text is enabled in Android Accessibility

Unfortunately this breaks emoji, so we only use this if the option is
enabled. Fortunately, we barely use emoji in the UI. They do appear in
RetroAchievemnts sometimes.
This commit is contained in:
Henrik Rydgård 2024-05-20 10:44:36 +02:00
parent 830f3a5fe6
commit 744e3db73c

View File

@ -2,17 +2,21 @@ package org.ppsspp.ppsspp;
import android.content.Context;
import android.graphics.*;
import android.provider.Settings;
import android.util.Log;
import android.view.accessibility.AccessibilityManager;
public class TextRenderer {
private static Paint p;
private static Paint textPaint;
private static Paint bg;
private static Typeface robotoCondensed;
private static final String TAG = "TextRenderer";
private static boolean highContrastFontsEnabled = false;
static {
p = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.WHITE);
textPaint = new Paint(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(Color.WHITE);
bg = new Paint();
bg.setColor(0);
}
@ -21,24 +25,25 @@ public class TextRenderer {
robotoCondensed = Typeface.createFromAsset(ctx.getAssets(), "Roboto-Condensed.ttf");
if (robotoCondensed != null) {
Log.i(TAG, "Successfully loaded Roboto Condensed");
p.setTypeface(robotoCondensed);
textPaint.setTypeface(robotoCondensed);
} else {
Log.e(TAG, "Failed to load Roboto Condensed");
}
highContrastFontsEnabled = Settings.Secure.getInt(ctx.getContentResolver(), "high_text_contrast_enabled", 0) == 1;
}
private static Point measureLine(String string, double textSize) {
int w;
if (string.length() > 0) {
p.setTextSize((float) textSize);
w = (int) p.measureText(string);
textPaint.setTextSize((float) textSize);
w = (int) textPaint.measureText(string);
// 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 + 5) & ~1;
} else {
w = 1;
}
int h = (int) (p.descent() - p.ascent() + 2.0f);
int h = (int) (textPaint.descent() - textPaint.ascent() + 2.0f);
Point p = new Point();
p.x = w;
p.y = h;
@ -53,7 +58,7 @@ public class TextRenderer {
Point sz = measureLine(line, textSize);
total.x = Math.max(sz.x, total.x);
}
total.y = (int) (p.descent() - p.ascent()) * lines.length + 2;
total.y = (int) (textPaint.descent() - textPaint.ascent()) * lines.length + 2;
// Returning a 0 size can create problems when the caller
// uses the measurement to create a texture.
// Also, clamp to a reasonable maximum size.
@ -85,10 +90,26 @@ public class TextRenderer {
String lines[] = string.replaceAll("\\r", "").split("\n");
float y = 1.0f;
Path path = new Path();
for (String line : lines) {
if (line.length() > 0)
canvas.drawText(line, 1, -p.ascent() + y, p);
y += p.descent() - p.ascent();
if (line.length() > 0) {
if (highContrastFontsEnabled) {
// This is a workaround for avoiding "High Contrast Fonts" screwing up our
// single-channel font rendering.
// Unfortunately, emoji do not render on this path.
if (path == null) {
path = new Path();
}
textPaint.getTextPath(line, 0, line.length(), 1, -textPaint.ascent() + y, path);
canvas.drawPath(path, textPaint);
} else {
// Standard text rendering, including emoji. Fine if high contrast fonts are not enabled.
canvas.drawText(line, 1, -textPaint.ascent() + y, textPaint);
}
}
y += textPaint.descent() - textPaint.ascent();
}
int[] pixels = new int[w * h];