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;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon;
15 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon.SolidPolygon.drawPolygon;
16 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas.FONT_CHAR_HEIGHT;
17 import static eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.textcanvas.TextCanvas.FONT_CHAR_WIDTH;
18 import static java.lang.String.valueOf;
21 * Represents a single character on the text canvas.
23 public class CanvasCharacter extends AbstractCoordinateShape {
25 private static final int MAX_FONT_SIZE = 500;
30 private static final Font[] fonts = new Font[MAX_FONT_SIZE];
33 * The character to be rendered.
38 * The foreground color of the character.
40 private eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor;
43 * The background color of the character.
45 private eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor;
48 * Creates a canvas character at the specified location with given colors.
50 * @param centerLocation the center position in 3D space
51 * @param character the character to render
52 * @param foregroundColor the foreground (text) color
53 * @param backgroundColor the background color
55 public CanvasCharacter(final Point3D centerLocation, final char character,
56 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor,
57 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
59 // There are 5 coordinates: center, upper left, upper right, lower right, lower left
63 this.foregroundColor = foregroundColor;
64 this.backgroundColor = backgroundColor;
67 coordinates[0].coordinate = centerLocation;
69 final double halfWidth = FONT_CHAR_WIDTH / 2d;
70 final double halfHeight = FONT_CHAR_HEIGHT / 2d;
73 coordinates[1].coordinate = centerLocation.clone().translateX(-halfWidth)
74 .translateY(-halfHeight);
77 coordinates[2].coordinate = centerLocation.clone().translateX(halfWidth)
78 .translateY(-halfHeight);
81 coordinates[3].coordinate = centerLocation.clone().translateX(halfWidth)
82 .translateY(halfHeight);
85 coordinates[4].coordinate = centerLocation.clone().translateX(-halfWidth)
86 .translateY(halfHeight);
90 * Returns a font of the specified size.
92 * If the font of the specified size is already cached, it will be
93 * returned. Otherwise, a new font will be created, cached and returned.
95 * @param size the size of the font
98 public static Font getFont(final int size) {
99 if (fonts[size] != null)
102 final Font font = new Font("Courier", Font.BOLD, size);
108 * Returns the background color of the character.
110 * @return the background color
112 public eu.svjatoslav.sixth.e3d.renderer.raster.Color getBackgroundColor() {
113 return backgroundColor;
117 * Sets the background color of the character.
119 * @param backgroundColor the new background color
121 public void setBackgroundColor(
122 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
123 this.backgroundColor = backgroundColor;
127 * Returns color of the foreground.
131 public eu.svjatoslav.sixth.e3d.renderer.raster.Color getForegroundColor() {
132 return foregroundColor;
136 * Sets color of the foreground.
138 * @param foregroundColor the color
140 public void setForegroundColor(
141 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor) {
142 this.foregroundColor = foregroundColor;
146 * 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 coordinates[1].onScreenCoordinate,
155 coordinates[2].onScreenCoordinate,
156 coordinates[3].onScreenCoordinate,
157 mouseInteractionController,
160 drawPolygon(renderingContext,
161 coordinates[1].onScreenCoordinate,
162 coordinates[3].onScreenCoordinate,
163 coordinates[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 = coordinates[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) {