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.Point3D;
8 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
9 import eu.svjatoslav.sixth.e3d.gui.TextPointer;
10 import eu.svjatoslav.sixth.e3d.math.Transform;
11 import eu.svjatoslav.sixth.e3d.math.TransformsStack;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.TexturedRectangle;
16 import java.io.BufferedReader;
17 import java.io.IOException;
18 import java.io.StringReader;
20 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.BLACK;
21 import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.WHITE;
23 public class TextCanvas extends TexturedRectangle {
25 // character size in world coordinates
26 public static final int FONT_CHAR_WIDTH = 8;
27 public static final int FONT_CHAR_HEIGHT = 16;
29 // character size on texture
30 public static final int FONT_CHAR_WIDTH_TEXTURE_PIXELS = 16;
31 public static final int FONT_CHAR_HEIGHT_TEXTURE_PIXELS = 32;
34 public static final Font FONT = CanvasCharacter.getFont((int) (FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.066));
35 private static final String GROUP_TEXTURE = "texture";
36 private static final String GROUP_CHARACTERS = "characters";
37 private final TextPointer size;
38 private final TextPointer cursorLocation = new TextPointer();
39 CanvasCharacter[][] lines;
40 private RenderMode renderMode = null;
41 private Color backgroundColor = BLACK;
42 private Color foregroundColor = WHITE;
44 public TextCanvas(final Transform location, final String text,
45 final Color foregroundColor, final Color backgroundColor) {
46 this(location, getTextDimensions(text), foregroundColor,
51 public TextCanvas(final Transform location, final TextPointer dimensions,
52 final Color foregroundColor, final Color backgroundColor) {
54 getRelativityTracker().enableOrientationTracking();
57 final int columns = dimensions.column;
58 final int rows = dimensions.row;
60 this.backgroundColor = backgroundColor;
61 this.foregroundColor = foregroundColor;
63 // initialize underlying textured rectangle
65 columns * FONT_CHAR_WIDTH,
66 rows * FONT_CHAR_HEIGHT,
67 columns * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
68 rows * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
71 getTexture().primaryBitmap.fillColor(backgroundColor);
72 getTexture().resetResampledBitmapCache();
74 setGroupForUngrouped(GROUP_TEXTURE);
76 lines = new CanvasCharacter[rows][];
77 for (int row = 0; row < rows; row++) {
78 lines[row] = new CanvasCharacter[columns];
80 for (int column = 0; column < columns; column++) {
81 final Point3D characterCoordinate = getCharLocation(row, column);
83 final CanvasCharacter character = new CanvasCharacter(
84 characterCoordinate, ' ', foregroundColor,
87 lines[row][column] = character;
92 setGroupForUngrouped(GROUP_CHARACTERS);
94 setRenderMode(RenderMode.TEXTURE);
97 public static TextPointer getTextDimensions(final String text) {
99 final BufferedReader reader = new BufferedReader(new StringReader(text));
107 line = reader.readLine();
108 } catch (IOException e) {
109 throw new RuntimeException(e);
113 return new TextPointer(rows, columns);
116 columns = Math.max(columns, line.length());
121 public void beforeTransformHook(final TransformsStack transformPipe,
122 final RenderingContext context) {
124 final double textRelativeSize = context.width
125 / getRelativityTracker().getDistanceToUser();
127 if (textRelativeSize < 2d) {
128 if (renderMode == RenderMode.CHARACTERS)
129 setRenderMode(RenderMode.TEXTURE);
133 final double piHalf = Math.PI / 2;
135 final double deviation = Math.abs(getRelativityTracker().getAngleXZ()
137 + Math.abs(getRelativityTracker().getAngleYZ() + piHalf);
139 final double maxDeviation = 0.5;
141 if (deviation > maxDeviation) {
142 if (renderMode == RenderMode.CHARACTERS)
143 setRenderMode(RenderMode.TEXTURE);
144 } else if (renderMode == RenderMode.TEXTURE)
145 setRenderMode(RenderMode.CHARACTERS);
148 public void clear() {
149 for (final CanvasCharacter[] line : lines)
150 for (final CanvasCharacter character : line) {
151 character.setValue(' ');
152 character.setBackgroundColor(backgroundColor);
153 character.setForegroundColor(foregroundColor);
156 // set background color
157 getTexture().primaryBitmap.fillColor(backgroundColor);
158 getTexture().resetResampledBitmapCache();
161 private void drawCharToTexture(final int row, final int column,
162 final char character, final Color foreground) {
163 final Graphics2D graphics = getTexture().graphics;
165 getTexture().primaryBitmap.drawRectangle(
166 column * FONT_CHAR_WIDTH_TEXTURE_PIXELS,
167 row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
168 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS) + FONT_CHAR_WIDTH_TEXTURE_PIXELS,
169 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + FONT_CHAR_HEIGHT_TEXTURE_PIXELS,
172 graphics.setFont(FONT);
173 graphics.setColor(foreground.toAwtColor());
175 new char[]{character,}, 0, 1,
176 (column * FONT_CHAR_WIDTH_TEXTURE_PIXELS),
177 (row * FONT_CHAR_HEIGHT_TEXTURE_PIXELS) + (int) (FONT_CHAR_HEIGHT_TEXTURE_PIXELS / 1.23f));
179 getTexture().resetResampledBitmapCache();
182 public Point3D getCharLocation(final int row, final int column) {
183 final Point3D coordinate = topLeft.clone();
185 coordinate.translateY((row * FONT_CHAR_HEIGHT)
186 + (FONT_CHAR_HEIGHT / 3.2));
188 coordinate.translateX((column * FONT_CHAR_WIDTH)
189 + (FONT_CHAR_WIDTH / 2));
194 public TextPointer getSize() {
198 public void locate(final int row, final int column) {
199 cursorLocation.row = row;
200 cursorLocation.column = column;
203 public void print(final String text) {
204 for (final char c : text.toCharArray())
208 public void putChar(final char character) {
209 putChar(cursorLocation, character);
211 cursorLocation.column++;
212 if (cursorLocation.column >= size.column) {
213 cursorLocation.column = 0;
214 cursorLocation.row++;
218 public void putChar(final int row, final int column, final char character) {
219 if ((row >= lines.length) || (row < 0))
222 final CanvasCharacter[] line = lines[row];
224 if ((column >= line.length) || (column < 0))
227 final CanvasCharacter canvasCharacter = line[column];
228 canvasCharacter.setValue(character);
229 canvasCharacter.setBackgroundColor(backgroundColor);
230 canvasCharacter.setForegroundColor(foregroundColor);
231 drawCharToTexture(row, column, character,
235 public void putChar(final TextPointer location, final char character) {
236 putChar(location.row, location.column, character);
239 public void setBackgroundColor(
240 final eu.svjatoslav.sixth.e3d.renderer.raster.Color backgroundColor) {
241 this.backgroundColor = backgroundColor;
244 public void setForegroundColor(
245 final eu.svjatoslav.sixth.e3d.renderer.raster.Color foregroundColor) {
246 this.foregroundColor = foregroundColor;
249 private void setRenderMode(final RenderMode mode) {
250 if (mode == renderMode)
255 hideGroup(GROUP_TEXTURE);
256 showGroup(GROUP_CHARACTERS);
259 hideGroup(GROUP_CHARACTERS);
260 showGroup(GROUP_TEXTURE);
267 public void setText(final String text) {
268 final BufferedReader reader = new BufferedReader(new StringReader(text));
275 line = reader.readLine();
276 } catch (IOException e) {
277 throw new RuntimeException(e);
284 for (final char c : line.toCharArray()) {
285 putChar(row, column, c);
292 public void setTextColor(final Color color) {
293 for (final CanvasCharacter[] line : lines)
294 for (final CanvasCharacter character : line)
295 character.setForegroundColor(color);