View Javadoc
1   /*
2    * Klasa ze źródła java 3d bo text2D z wersji 1.3x działał źle i na forum radzili zrobić takie coś
3    *	@(#)Text2D.java 1.19 03/01/15 17:17:06
4    *
5    * Copyright (c) 1996-2002 Sun Microsystems, Inc. All Rights Reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions
9    * are met:
10   *
11   * - Redistributions of source code must retain the above copyright
12   *   notice, this list of conditions and the following disclaimer.
13   *
14   * - Redistribution in binary form must reproduce the above copyright
15   *   notice, this list of conditions and the following disclaimer in
16   *   the documentation and/or other materials provided with the
17   *   distribution.
18   *
19   * Neither the name of Sun Microsystems, Inc. or the names of
20   * contributors may be used to endorse or promote products derived
21   * from this software without specific prior written permission.
22   *
23   * This software is provided "AS IS," without a warranty of any
24   * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
25   * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
26   * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
27   * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES
28   * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
29   * DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
30   * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
31   * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
32   * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
33   * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE,
34   * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
35   *
36   * You acknowledge that Software is not designed,licensed or intended
37   * for use in the design, construction, operation or maintenance of
38   * any nuclear facility.
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      // This table caches FontMetrics objects to avoid the huge cost
72      // of re-retrieving metrics for a font we've already seen.
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      * Changes text of this Text2D to 'text'. All other
109      * parameters (color, fontName, fontSize, fontStyle
110      * remain the same.
111      * @param text The string to be set.
112      */
113     public void setString(String text){
114     	 this.text = text;
115     	        updateText2D(text, color, fontName, fontSize, fontStyle);
116     	    }
117     /*public void setString(String text){
118 	this.text = text;
119 	
120 	Texture tex = getAppearance().getTexture();
121 	int width = tex.getWidth();
122 	int height = tex.getHeight();	
123 
124         ImageComponent imageComponent = setupImage(text, color, fontName,
125                                           fontSize, fontStyle);
126 	if ((imageComponent.getWidth() == width) &&
127 	    (imageComponent.getHeight() == height)) {
128 	    tex.setImage(0, imageComponent);
129 	} else {
130 	    Texture2D newTex = setupTexture(imageComponent);
131 	    // Copy texture attributes except those related to
132 	    // mipmap since Texture only set base imageComponent. 
133 
134 	    newTex.setBoundaryModeS(tex.getBoundaryModeS());
135 	    newTex.setBoundaryModeT(tex.getBoundaryModeT());
136 	    newTex.setMinFilter(tex.getMinFilter());
137 	    newTex.setMagFilter(tex.getMagFilter());      
138 	    newTex.setEnable(tex.getEnable());
139 	    newTex.setAnisotropicFilterMode(tex.getAnisotropicFilterMode());
140 	    newTex.setAnisotropicFilterDegree(tex.getAnisotropicFilterDegree());
141 	    int pcount = tex.getFilter4FuncPointsCount();
142 	    if (pcount > 0) {
143 		float weights[] = new float[pcount];
144 		tex.getFilter4Func(weights);
145 		newTex.setFilter4Func(weights);
146 	    }
147 	    Color4f c = new Color4f();
148 	    tex.getBoundaryColor(c);
149 	    newTex.setBoundaryColor(c);      
150 	    newTex.setUserData(tex.getUserData());
151 	    getAppearance().setTexture(newTex);
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 	// Need to make width/height powers of 2 because of Java3d texture
239 	// size restrictions
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 	// For now, jdk 1.2 only handles ARGB format, not the RGBA we want
256 	BufferedImage bImage = new BufferedImage(width, height,
257 						 BufferedImage.TYPE_INT_ARGB);
258 	Graphics offscreenGraphics = bImage.createGraphics();
259 
260 	// First, erase the background to the text panel - set alpha to 0
261 	Color myFill = new Color(0f, 0f, 0f, 0f);
262 	offscreenGraphics.setColor(myFill);
263 	offscreenGraphics.fillRect(0, 0, width, height);
264 
265 	// Next, set desired text properties (font, color) and draw String
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