2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas;
7 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
8 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
9 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
10 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
14 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon.drawPolygon;
15 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas.FONT_CHAR_HEIGHT;
16 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas.FONT_CHAR_WIDTH;
17 import static java.lang.String.valueOf;
20 * Represents a single character on the text canvas.
22 public class CanvasCharacter extends AbstractCoordinateShape {
24 private static final int MAX_FONT_SIZE = 500;
29 private static final Font[] fonts = new Font[MAX_FONT_SIZE];
32 * The character to be rendered.
37 * The foreground color of the character.
39 private eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor;
42 * The background color of the character.
44 private eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor;
47 * Creates a canvas character at the specified location with given colors.
49 * @param centerLocation the center position in 3D space
50 * @param character the character to render
51 * @param foregroundColor the foreground (text) color
52 * @param backgroundColor the background color
54 public CanvasCharacter(final Point3D centerLocation, final char character,
55 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor,
56 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
58 // There are 5 coordinates: center, upper left, upper right, lower right, lower left
62 this.foregroundColor = foregroundColor;
63 this.backgroundColor = backgroundColor;
66 vertices[0].coordinate = centerLocation;
68 final double halfWidth = FONT_CHAR_WIDTH / 2d;
69 final double halfHeight = FONT_CHAR_HEIGHT / 2d;
72 vertices[1].coordinate = centerLocation.clone().translateX(-halfWidth)
73 .translateY(-halfHeight);
76 vertices[2].coordinate = centerLocation.clone().translateX(halfWidth)
77 .translateY(-halfHeight);
80 vertices[3].coordinate = centerLocation.clone().translateX(halfWidth)
81 .translateY(halfHeight);
84 vertices[4].coordinate = centerLocation.clone().translateX(-halfWidth)
85 .translateY(halfHeight);
89 * Returns a font of the specified size.
91 * If the font of the specified size is already cached, it will be
92 * returned. Otherwise, a new font will be created, cached and returned.
94 * @param size the size of the font
97 public static Font getFont(final int size) {
98 if (fonts[size] != null)
101 final Font font = new Font("Courier", Font.BOLD, size);
107 * Returns the background color of the character.
109 * @return the background color
111 public eu.svjatoslav.sixth.e3d.renderer.raster.Color getBackgroundColor() {
112 return backgroundColor;
116 * Sets the background color of the character.
118 * @param backgroundColor the new background color
120 public void setBackgroundColor(
121 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
122 this.backgroundColor = backgroundColor;
126 * Returns color of the foreground.
130 public eu.svjatoslav.sixth.e3d.renderer.raster.Color getForegroundColor() {
131 return foregroundColor;
135 * Sets color of the foreground.
137 * @param foregroundColor the color
139 public void setForegroundColor(
140 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor) {
141 this.foregroundColor = foregroundColor;
145 * Paints the character on the screen.
147 * @param renderingContext the rendering context
150 public void paint(final RenderingContext renderingContext) {
152 // Draw background rectangle first. It is composed of two triangles.
153 drawPolygon(renderingContext,
154 vertices[1].onScreenCoordinate,
155 vertices[2].onScreenCoordinate,
156 vertices[3].onScreenCoordinate,
157 mouseInteractionController,
160 drawPolygon(renderingContext,
161 vertices[1].onScreenCoordinate,
162 vertices[3].onScreenCoordinate,
163 vertices[4].onScreenCoordinate,
164 mouseInteractionController,
167 final int desiredFontSize = (int) ((renderingContext.width * 4.5) / onScreenZ);
169 // do not render too large characters
170 if (desiredFontSize >= MAX_FONT_SIZE)
173 final Point2D onScreenLocation = vertices[0].onScreenCoordinate;
175 // screen borders check
176 if (onScreenLocation.x < 0)
178 if (onScreenLocation.y < 0)
181 if (onScreenLocation.x > renderingContext.width)
183 if (onScreenLocation.y > renderingContext.height)
186 // check render Y bounds
187 if (onScreenLocation.y + desiredFontSize < renderingContext.renderMinY)
189 if (onScreenLocation.y - desiredFontSize >= renderingContext.renderMaxY)
192 // draw the character
193 final int fontSize = desiredFontSize;
194 final int drawX = (int) onScreenLocation.x - (int) (fontSize / 3.2);
195 final int drawY = (int) onScreenLocation.y + (int) (fontSize / 2.5);
197 renderingContext.executeWithGraphics(g -> {
198 g.setFont(getFont(fontSize));
199 g.setColor(foregroundColor.toAwtColor());
200 g.drawString(valueOf(value), drawX, drawY);
206 * Sets the character value to render.
208 * @param value the new character value
210 public void setValue(final char value) {