1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 package org.sourceforge.jvb3d.Model;
42
43 import java.awt.image.BufferedImage;
44 import java.awt.image.WritableRaster;
45 import java.awt.image.DataBufferInt;
46 import java.awt.Color;
47 import java.awt.Font;
48 import java.awt.FontMetrics;
49 import java.awt.Graphics;
50 import java.awt.Toolkit;
51 import java.util.Hashtable;
52
53 import javax.media.j3d.*;
54 import javax.vecmath.*;
55
56 /***
57 * A Text2D object is a representation of a string as a texture mapped
58 * rectangle. The texture for the rectangle shows the string as rendered in
59 * the specified color with a transparent background. The appearance of the
60 * characters is specified using the font indicated by the font name, size
61 * and style (see java.awt.Font). The approximate height of the rendered
62 * string will be the font size times the rectangle scale factor, which has a
63 * default value of 1/256. For example, a 12 point font will produce
64 * characters that are about 12/256 = 0.047 meters tall. The lower left
65 * corner of the rectangle is located at (0,0,0) with the height
66 * extending along the positive y-axis and the width extending along the
67 * positive x-axis.
68 */
69 public class MyText2D extends Shape3D {
70
71
72
73 private static Hashtable metricsTable = new Hashtable();
74 float rectangleScaleFactor = 1f/256f;
75
76 Color3f color = new Color3f();
77 String fontName;
78 int fontSize, fontStyle;
79 String text;
80
81
82 /***
83 * Creates a Shape3D object which holds a
84 * rectangle that is texture-mapped with an image that has
85 * the specified text written with the specified font
86 * parameters.
87 *
88 * @param text The string to be written into the texture map.
89 * @param color The color of the text string.
90 * @param fontName The name of the Java font to be used for
91 * the text string.
92 * @param fontSize The size of the Java font to be used.
93 * @param fontStyle The style of the Java font to be used.
94 */
95 public MyText2D(String text, Color3f color, String fontName,
96 int fontSize, int fontStyle) {
97
98 this.color.set(color);
99 this.fontName = fontName;
100 this.fontSize = fontSize;
101 this.fontStyle = fontStyle;
102 this.text = text;
103
104 updateText2D(text, color, fontName, fontSize, fontStyle);
105 }
106
107
108
109
110
111
112
113 public void setString(String text){
114 this.text = text;
115 updateText2D(text, color, fontName, fontSize, fontStyle);
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 private void updateText2D(String text, Color3f color, String fontName,
156 int fontSize, int fontStyle) {
157 ImageComponent imageComponent = setupImage(text, color, fontName,
158 fontSize, fontStyle);
159
160 Texture2D t2d = setupTexture(imageComponent);
161
162 QuadArray rect = setupGeometry(imageComponent.getWidth(),
163 imageComponent.getHeight());
164 setGeometry(rect);
165
166 Appearance appearance = setupAppearance(t2d);
167 setAppearance(appearance);
168 }
169
170
171 /***
172 * Sets the scale factor used in converting the image width/height
173 * to width/height values in 3D.
174 *
175 * @param newScaleFactor The new scale factor.
176 */
177 public void setRectangleScaleFactor(float newScaleFactor) {
178 rectangleScaleFactor = newScaleFactor;
179 updateText2D(text, color, fontName, fontSize, fontStyle);
180 }
181
182 /***
183 * Gets the current scale factor being used in converting the image
184 * width/height to width/height values in 3D.
185 *
186 * @return The current scale factor.
187 */
188 public float getRectangleScaleFactor() {
189 return rectangleScaleFactor;
190 }
191
192 /***
193 * Create the ImageComponent and Texture object.
194 */
195 private Texture2D setupTexture(ImageComponent imageComponent) {
196 Texture2D t2d = new Texture2D(Texture2D.BASE_LEVEL,
197 Texture.RGBA,
198 imageComponent.getWidth(),
199 imageComponent.getHeight());
200 t2d.setMinFilter(t2d.BASE_LEVEL_LINEAR);
201 t2d.setMagFilter(t2d.BASE_LEVEL_LINEAR);
202 t2d.setImage(0, imageComponent);
203 t2d.setEnable(true);
204 t2d.setCapability(Texture.ALLOW_IMAGE_WRITE);
205 t2d.setCapability(Texture.ALLOW_SIZE_READ);
206 t2d.setCapability(Texture.ALLOW_ENABLE_READ);
207 t2d.setCapability(Texture.ALLOW_BOUNDARY_MODE_READ);
208 t2d.setCapability(Texture.ALLOW_FILTER_READ);
209 t2d.setCapability(Texture.ALLOW_BOUNDARY_COLOR_READ);
210 t2d.setCapability(Texture.ALLOW_ANISOTROPIC_FILTER_READ);
211 t2d.setCapability(Texture.ALLOW_FILTER4_READ);
212 return t2d;
213 }
214
215 /***
216 * Creates a ImageComponent2D of the correct dimensions for the
217 * given font attributes. Draw the given text into the image in
218 * the given color. The background of the image is transparent
219 * (alpha = 0).
220 */
221 private ImageComponent setupImage(String text, Color3f color,
222 String fontName,
223 int fontSize, int fontStyle) {
224 Toolkit toolkit = Toolkit.getDefaultToolkit();
225 Font font = new java.awt.Font(fontName, fontStyle, fontSize);
226
227 FontMetrics metrics;
228 if ((metrics = (FontMetrics)metricsTable.get(font)) == null) {
229 metrics = toolkit.getFontMetrics(font);
230 metricsTable.put(font, metrics);
231 }
232 int width = metrics.stringWidth(text);
233 int descent = metrics.getMaxDescent();
234 int ascent = metrics.getMaxAscent();
235 int leading = metrics.getLeading();
236 int height = descent + ascent;
237
238
239
240 int pow = 1;
241 for (int i = 1; i < 32; ++i) {
242 pow *= 2;
243 if (width <= pow)
244 break;
245 }
246 width = Math.max (width, pow);
247 pow = 1;
248 for (int i = 1; i < 32; ++i) {
249 pow *= 2;
250 if (height <= pow)
251 break;
252 }
253 height = Math.max (height, pow);
254
255
256 BufferedImage bImage = new BufferedImage(width, height,
257 BufferedImage.TYPE_INT_ARGB);
258 Graphics offscreenGraphics = bImage.createGraphics();
259
260
261 Color myFill = new Color(0f, 0f, 0f, 0f);
262 offscreenGraphics.setColor(myFill);
263 offscreenGraphics.fillRect(0, 0, width, height);
264
265
266 offscreenGraphics.setFont(font);
267 Color myTextColor = new Color(color.x, color.y, color.z, 1f);
268 offscreenGraphics.setColor(myTextColor);
269 offscreenGraphics.drawString(text, 0, height - descent);
270
271 ImageComponent imageComponent =
272 new ImageComponent2D(ImageComponent.FORMAT_RGBA,
273 bImage);
274
275 imageComponent.setCapability(ImageComponent.ALLOW_SIZE_READ);
276
277 return imageComponent;
278 }
279
280 /***
281 * Creates a rectangle of the given width and height and sets up
282 * texture coordinates to map the text image onto the whole surface
283 * of the rectangle (the rectangle is the same size as the text image)
284 */
285 private QuadArray setupGeometry(int width, int height) {
286 float zPosition = 0f;
287 float rectWidth = (float)width * rectangleScaleFactor;
288 float rectHeight = (float)height * rectangleScaleFactor;
289 float[] verts1 = {
290 rectWidth, 0f, zPosition,
291 rectWidth, rectHeight, zPosition,
292 0f, rectHeight, zPosition,
293 0f, 0f, zPosition
294 };
295 float[] texCoords = {
296 0f, -1f,
297 0f, 0f,
298 (-1f), 0f,
299 (-1f), -1f
300 };
301
302 QuadArray rect = new QuadArray(4, QuadArray.COORDINATES |
303 QuadArray.TEXTURE_COORDINATE_2);
304 rect.setCoordinates(0, verts1);
305 rect.setTextureCoordinates(0, 0, texCoords);
306
307 return rect;
308 }
309
310 /***
311 * Creates Appearance for this Shape3D. This sets transparency
312 * for the object (we want the text to be "floating" in space,
313 * so only the text itself should be non-transparent. Also, the
314 * appearance disables lighting for the object; the text will
315 * simply be colored, not lit.
316 */
317 private Appearance setupAppearance(Texture2D t2d) {
318 TransparencyAttributes transp = new TransparencyAttributes();
319 transp.setTransparencyMode(TransparencyAttributes.BLENDED);
320 transp.setTransparency(0f);
321 Appearance appearance = new Appearance();
322 appearance.setTransparencyAttributes(transp);
323 appearance.setTexture(t2d);
324
325 Material m = new Material();
326 m.setLightingEnable(false);
327 appearance.setMaterial(m);
328
329 return appearance;
330 }
331
332 /***
333 * Returns the text string
334 *
335 * @since Java 3D 1.2.1
336 */
337 public String getString() {
338 return text;
339 }
340
341 /***
342 * Returns the color of the text
343 *
344 * @since Java 3D 1.2.1
345 */
346 public Color3f getColor() {
347 return color;
348 }
349
350 /***
351 * Returns the font
352 *
353 * @since Java 3D 1.2.1
354 */
355 public String getFontName() {
356 return fontName;
357 }
358
359 /***
360 * Returns the font size
361 *
362 * @since Java 3D 1.2.1
363 */
364 public int getFontSize() {
365 return fontSize;
366 }
367
368 /***
369 * Returns the font style
370 *
371 * @since Java 3D 1.2.1
372 */
373 public int getFontStyle() {
374 return fontStyle;
375 }
376
377 }
378
379
380
381
382