Merge pull request #19157 from hrydgard/android-fix-blurry-fonts

Workaround for blurry text when high contrast text is enabled in Android Accessibility
This commit is contained in:
Henrik Rydgård 2024-05-20 11:07:56 +02:00 committed by GitHub
commit ab598f37f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

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];