Antialiasing and fill fixes
Build and Test j3270 / Build JAR & Run Tests (push) Successful in 1m8s

This commit is contained in:
2026-08-25 15:48:36 +00:00
parent dbe0cdaa89
commit 36b93df986
7 changed files with 760 additions and 148 deletions
@@ -1,6 +1,7 @@
package org.pubvm.j3270.ui;
import org.lib3270j.Telnet3270Client;
import org.lib3270j.graphics.GocaConstants;
import org.lib3270j.screen.ExtendedAttribute;
import org.lib3270j.screen.ScreenBuffer;
@@ -905,6 +906,63 @@ public class TerminalPanel extends JPanel {
public void setClient(Telnet3270Client client) {
this.client = client;
if (client != null) {
setupGraphicsPlaneRenderer();
updateCellSize();
}
}
private void setupGraphicsPlaneRenderer() {
if (client != null && client.getGraphicsPlane() != null) {
client.getGraphicsPlane().setTextRenderer((plane, x, y, text, colorArgb, cw, ch, dir, angle) -> {
int[] rgb = plane.getRgbBuffer();
int pw = plane.getCanvasWidth();
int ph = plane.getCanvasHeight();
if (rgb == null || pw <= 0 || ph <= 0) return;
java.awt.image.BufferedImage img = new java.awt.image.BufferedImage(
pw, ph, java.awt.image.BufferedImage.TYPE_INT_ARGB
);
img.setRGB(0, 0, pw, ph, rgb, 0, pw);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
int fontSize = (int) Math.round(ch * 0.95);
if (fontSize < 10) fontSize = 10;
Font f = (boldTerminalFont != null ? boldTerminalFont : terminalFont).deriveFont((float) fontSize);
g2.setFont(f);
FontMetrics fm = g2.getFontMetrics();
int ascent = fm.getAscent();
g2.setColor(new Color(colorArgb, true));
double curX = x;
double curY = y;
for (int i = 0; i < text.length(); i++) {
String s = text.substring(i, i + 1);
int charW = fm.stringWidth(s);
int drawX = (int) Math.round(curX + Math.max(0, (cw - charW) / 2.0));
int drawY = (int) Math.round(curY + ascent + Math.max(0, (ch - fm.getHeight()) / 2.0));
g2.drawString(s, drawX, drawY);
switch (dir) {
case GocaConstants.CD_TB: curY += ch; break;
case GocaConstants.CD_RL: curX -= cw; break;
case GocaConstants.CD_BT: curY -= ch; break;
case GocaConstants.CD_LR:
case GocaConstants.CD_DEFAULT:
default:
curX += cw;
break;
}
}
g2.dispose();
img.getRGB(0, 0, pw, ph, rgb, 0, pw);
});
}
}
@Override
@@ -931,9 +989,12 @@ public class TerminalPanel extends JPanel {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
// Clear entire panel with background color
g2.setColor(bgColor);
@@ -962,7 +1023,11 @@ public class TerminalPanel extends JPanel {
cachedGraphicsImage.setRGB(0, 0, gWidth, gHeight, rgb, 0, gWidth);
lastGraphicsUpdateCount = currentUpdateCount;
}
g2.drawImage(cachedGraphicsImage, ox, oy, gridW, gridH, null);
if (gWidth == gridW && gHeight == gridH) {
g2.drawImage(cachedGraphicsImage, ox, oy, null);
} else {
g2.drawImage(cachedGraphicsImage, ox, oy, gridW, gridH, null);
}
}
}