feat(renderer): enhance text rendering with visible area clipping and line dimension calculations

This commit is contained in:
extio-de
2025-12-29 19:02:36 +01:00
parent c459767de8
commit d760b60758

View File

@@ -3,6 +3,7 @@ package de.extio.game_engine.renderer.g2d.bo.rendering;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -17,6 +18,8 @@ import de.extio.game_engine.renderer.model.bo.DrawFontRenderingBo;
import de.extio.game_engine.renderer.model.bo.HorizontalAlignment; import de.extio.game_engine.renderer.model.bo.HorizontalAlignment;
import de.extio.game_engine.resource.StaticResource; import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.resource.StaticResourceService; import de.extio.game_engine.resource.StaticResourceService;
import de.extio.game_engine.spatial2.SpatialUtils2;
import de.extio.game_engine.spatial2.model.Area2;
import de.extio.game_engine.spatial2.model.CoordI2; import de.extio.game_engine.spatial2.model.CoordI2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2; import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
import de.extio.game_engine.spatial2.model.MutableCoordI2; import de.extio.game_engine.spatial2.model.MutableCoordI2;
@@ -86,10 +89,35 @@ public class G2DDrawFont extends G2DAbstractRenderingBo implements DrawFontRende
graphics.setColor(this.color == null ? this.rendererData.getThemeManager().getCurrentTheme().getTextNormal().toColor() : this.color.toAwtColor()); graphics.setColor(this.color == null ? this.rendererData.getThemeManager().getCurrentTheme().getTextNormal().toColor() : this.color.toAwtColor());
if (this.text.contains("\n")) { final var lines = this.text.contains("\n") ? this.text.split("\n", -1) : new String[] { this.text };
final var lines = this.text.split("\n", -1); final var lineHeight = getTextDimensions("M", graphics, this.size, 1.0).getY();
final var lineHeight = getTextDimensions("M", graphics, this.size, 1.0).getY(); final CoordI2[] lineDims = new CoordI2[lines.length];
int maxLineWidth = 0;
for (int i = 0; i < lines.length; i++) {
lineDims[i] = G2DDrawFont.getTextDimensions(lines[i], graphics, this.size, 1.0);
if (lineDims[i].getX() > maxLineWidth) {
maxLineWidth = lineDims[i].getX();
}
}
Shape oldClip = null;
Area2 intersection = null;
if (visibleAreaX != 0 || visibleAreaY != 0 || visibleAreaWidth != 0 || visibleAreaHeight != 0) {
final int blockX = (int) (this.x * scaleFactor);
final int blockY = (int) (this.y * scaleFactor);
final int blockW = this.width > 0 ? (int) (this.width * scaleFactor) : (int) Math.round(maxLineWidth * scaleFactor);
final int blockH = (int) Math.round(lineHeight * lines.length * scaleFactor);
final var controlArea = new Area2(ImmutableCoordI2.create(blockX, blockY), ImmutableCoordI2.create(blockW, blockH));
final var visibleArea = new Area2(ImmutableCoordI2.create((int) (this.visibleAreaX * scaleFactor), (int) (this.visibleAreaY * scaleFactor)), ImmutableCoordI2.create((int) (this.visibleAreaWidth * scaleFactor), (int) (this.visibleAreaHeight * scaleFactor)));
intersection = SpatialUtils2.intersectAreas(controlArea, visibleArea);
if (intersection == null) {
return;
}
oldClip = graphics.getClip();
graphics.setClip(intersection.getPosition().getX(), intersection.getPosition().getY(), intersection.getDimension().getX(), intersection.getDimension().getY());
}
try {
for (int i = 0; i < lines.length; i++) { for (int i = 0; i < lines.length; i++) {
final var line = lines[i]; final var line = lines[i];
final var yOffset = this.y + i * lineHeight; final var yOffset = this.y + i * lineHeight;
@@ -100,13 +128,13 @@ public class G2DDrawFont extends G2DAbstractRenderingBo implements DrawFontRende
break; break;
case CENTER: { case CENTER: {
final var textDim = G2DDrawFont.getTextDimensions(line, graphics, this.size, 1.0); final var textDim = lineDims[i];
renderSingleLine(graphics, textDim, scaleFactor, (this.width - textDim.getX()) / 2 + this.x, yOffset, this.size, line); renderSingleLine(graphics, textDim, scaleFactor, (this.width - textDim.getX()) / 2 + this.x, yOffset, this.size, line);
break; break;
} }
case RIGHT: { case RIGHT: {
final var textDim = G2DDrawFont.getTextDimensions(line, graphics, this.size, 1.0); final var textDim = lineDims[i];
renderSingleLine(graphics, textDim, scaleFactor, this.width - textDim.getX() + this.x, yOffset, this.size, line); renderSingleLine(graphics, textDim, scaleFactor, this.width - textDim.getX() + this.x, yOffset, this.size, line);
break; break;
} }
@@ -116,27 +144,8 @@ public class G2DDrawFont extends G2DAbstractRenderingBo implements DrawFontRende
} }
} }
} }
else { finally {
switch (this.alignment) { graphics.setClip(oldClip);
case LEFT:
renderSingleLine(graphics, null, scaleFactor, this.x, this.y, this.size, this.text);
break;
case CENTER: {
final var textDim = G2DDrawFont.getTextDimensions(this.text, graphics, this.size, 1.0);
renderSingleLine(graphics, textDim, scaleFactor, (this.width - textDim.getX()) / 2 + this.x, this.y, this.size, this.text);
break;
}
case RIGHT: {
final var textDim = G2DDrawFont.getTextDimensions(this.text, graphics, this.size, 1.0);
renderSingleLine(graphics, textDim, scaleFactor, this.width - textDim.getX() + this.x, this.y, this.size, this.text);
break;
}
default:
break;
}
} }
} }
@@ -186,7 +195,6 @@ public class G2DDrawFont extends G2DAbstractRenderingBo implements DrawFontRende
renderSingleLine(graphics, textDim_, scaleFactor, x, y, size_, text); renderSingleLine(graphics, textDim_, scaleFactor, x, y, size_, text);
} }
private static void renderSingleLine(final Graphics graphics, final CoordI2 textDim_, final double scaleFactor, final int x, final int y, final int size_, final String text) { private static void renderSingleLine(final Graphics graphics, final CoordI2 textDim_, final double scaleFactor, final int x, final int y, final int size_, final String text) {
if (text == null) { if (text == null) {
return; return;