⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 font3d.java

📁 JAVA3D矩陈的相关类
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* * $RCSfile: Font3D.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.5 $ * $Date: 2007/02/09 17:17:59 $ * $State: Exp $ */package javax.media.j3d;import com.sun.j3d.utils.geometry.*;import com.sun.j3d.internal.FastVector;import java.awt.Font;import java.awt.font.*;import java.awt.geom.Rectangle2D;import java.awt.geom.AffineTransform;import javax.vecmath.*;import java.awt.Shape;import java.awt.geom.PathIterator;import java.util.*;/** * The Font3D object is used to store extruded 2D glyphs.  These * 3D glyphs can then be used to construct Text3D NodeComponent * objects. * <P> * A 3D Font consists of a Java 2D font, a tesellation tolerance, * and an extrusion path.  The extrusion * path creates depth by describing how the edge of a glyph varies * in the Z axis. * <P> * The construction of a Text3D object requires a Font3D object. * The Font3D object describes the style of the text, such as its * depth. The text also needs other classes, such as java.awt.Font and * FontExtrusion. The Font object describes the font name (Helvetica, * Courier, etc.), the font style (bold, Italic, etc.), and point * size. The FontExtrusion object extends Font3D by describing * the extrusion path for the Font3D object (how the edge of the * font glyph varies in the Z axis). *<P> * To ensure correct rendering, the 2D Font object should be created * with the default AffineTransform. The point size of the 2D font will * be used as a rough measure of how fine a tesselation to use when * creating the Font3D object: the larger the point size, in * general, the finer the tesselation. * <P> * Custom 3D fonts as well as methods to store 3D fonts * to disk will be addressed in a future release. * * @see java.awt.Font * @see FontExtrusion * @see Text3D */public class Font3D extends NodeComponent {    Font              font;    double            tessellationTolerance;    FontExtrusion     fontExtrusion;    FontRenderContext frc;    // Used by triangulateGlyphs method to split contour data into islands.    final static float EPS = 0.000001f;    // Map glyph code to GeometryArrayRetained    Hashtable geomHash = new Hashtable(20);    /**     * Constructs a Font3D object from the specified Font and     * FontExtrusion objects, using the default value for the     * tessellation tolerance.  The default value is as follows:     *     * <ul>     * tessellation tolerance : 0.01<br>     * </ul>     * <P>     * The FontExtrusion object contains the extrusion path to use on     * the 2D Font glyphs.  To ensure correct rendering the font must     * be created with the default AffineTransform.  Passing null for     * the FontExtrusion parameter results in no extrusion being done.     *     * @param font the Java 2D font used to create the 3D font object     * @param extrudePath the extrusion path used to describe how     * the edge of the font varies along the Z axis     */    public Font3D(Font font, FontExtrusion extrudePath) {	this(font, 0.01, extrudePath);    }    /**     * Constructs a Font3D object from the specified Font and     * FontExtrusion objects, using the specified tessellation     * tolerance.     * The FontExtrusion object contains the extrusion path to use on     * the 2D Font glyphs.  To ensure correct rendering, the font must     * be created with the default AffineTransform.  Passing null for     * the FontExtrusion parameter results in no extrusion being done.     *     * @param font the Java 2D font used to create the 3D font object.     * @param tessellationTolerance the tessellation tolerance value     * used in tessellating the glyphs of the 2D Font.     * This corresponds to the <code>flatness</code> parameter in     * the <code>java.awt.Shape.getPathIterator</code> method.     * @param extrudePath the extrusion path used to describe how     * the edge of the font varies along the Z axis.     *     * @since Java 3D 1.2     */    public Font3D(Font font,		  double tessellationTolerance,		  FontExtrusion extrudePath) {      this.font = font;      this.tessellationTolerance = tessellationTolerance;      this.fontExtrusion = extrudePath;      this.frc = new FontRenderContext(new AffineTransform(),				       true, true);    }    /**     * Returns the Java 2D Font used to create this Font3D object.     * @return Font object used by this Font3D     */    public Font getFont() {      return this.font;    }    /**     * Returns the tessellation tolerance with which this Font3D was     * created.     * @return the tessellation tolerance used by this Font3D     *     * @since Java 3D 1.2     */    public double getTessellationTolerance() {	return tessellationTolerance;    }    /**     * Copies the FontExtrusion object used to create this Font3D object     * into the specified parameter.     *     * @param extrudePath object that will receive the     * FontExtrusion information for this Font3D object     */    public void getFontExtrusion(FontExtrusion extrudePath) {      extrudePath = this.fontExtrusion;    }    /**     * Returns the 3D bounding box of the specified glyph code.     *     * @param glyphCode the glyphCode from the original 2D Font     * @param bounds the 3D glyph's bounds     */    public void getBoundingBox(int glyphCode, BoundingBox bounds){      int[] gCodes = {glyphCode};      GlyphVector gVec = font.createGlyphVector(frc, gCodes);      Rectangle2D.Float bounds2d = (Rectangle2D.Float)	(((GlyphMetrics)(gVec.getGlyphMetrics(0))).getBounds2D());            Point3d lower = new Point3d(bounds2d.x, bounds2d.y, 0.0);      Point3d upper;      if (fontExtrusion != null) {          upper = new Point3d(bounds2d.x + bounds2d.width,				      bounds2d.y + bounds2d.height,				      fontExtrusion.length);      } else {          upper = new Point3d(bounds2d.x + bounds2d.width,				      bounds2d.y + bounds2d.height,				      0.0);      }      bounds.setLower(lower);      bounds.setUpper(upper);    }    // BY MIK OF CLASSX    /**     * Returns a GeometryArray of a glyph in this Font3D.     *     * @param c character from which to generate a tessellated glyph.     *     * @return a GeometryArray     *     * @since Java 3D 1.4     */    public GeometryArray getGlyphGeometry(char c) {        char code[] = { c };        GlyphVector gv = font.createGlyphVector(frc, code);        // triangulate the glyph        GeometryArrayRetained glyph_gar = triangulateGlyphs(gv, code[0]);        // Assume that triangulateGlyphs returns a triangle array with only coords & normals        // (and without by-ref, interleaved, etc.)        assert glyph_gar instanceof TriangleArrayRetained :            "Font3D: GeometryArray is not an instance of TrangleArray";        assert glyph_gar.getVertexFormat() == (GeometryArray.COORDINATES | GeometryArray.NORMALS) :            "Font3D: Illegal GeometryArray format -- only coordinates and normals expected";        // create a correctly sized TriangleArray        TriangleArray ga = new TriangleArray(glyph_gar.getVertexCount(),glyph_gar.getVertexFormat());                // temp storage for coords, normals        float tmp[] = new float[3];        int vertexCount = ga.getVertexCount();        for(int i=0; i<vertexCount; i++) {            // copy the glyph geometry to the TriangleArray            glyph_gar.getCoordinate(i,tmp);            ga.setCoordinate(i,tmp);            glyph_gar.getNormal(i,tmp);            ga.setNormal(i,tmp);        }        return ga;    }  // Triangulate glyph with 'unicode' if not already done.    GeometryArrayRetained triangulateGlyphs(GlyphVector gv, char c) {	Character ch = new Character(c);	GeometryArrayRetained geo = (GeometryArrayRetained) geomHash.get(ch);	if (geo == null) {	  // Font Y-axis is downwards, so send affine transform to flip it.	    Rectangle2D bnd = gv.getVisualBounds();	    AffineTransform aTran = new AffineTransform();	    double tx = bnd.getX() + 0.5 * bnd.getWidth();	    double ty = bnd.getY() + 0.5 * bnd.getHeight();	    aTran.setToTranslation(-tx, -ty);	    aTran.scale(1.0, -1.0);	    aTran.translate(tx, -ty);	    Shape shape = gv.getOutline();	    PathIterator pIt = shape.getPathIterator(aTran, tessellationTolerance);	    int flag= -1, numContours = 0, numPoints = 0, i, j, k, num=0, vertCnt;	    UnorderList coords = new UnorderList(100, Point3f.class);	    float tmpCoords[] = new float[6];	    float lastX= .0f, lastY= .0f;	    float firstPntx = Float.MAX_VALUE, firstPnty = Float.MAX_VALUE;	    GeometryInfo gi = null;	    NormalGenerator ng = new NormalGenerator();	    FastVector contours = new FastVector(10);	    float maxY = -Float.MAX_VALUE;	    int maxYIndex = 0, beginIdx = 0, endIdx = 0, start = 0;	    	    boolean setMaxY = false;	    while (!pIt.isDone()) {		Point3f vertex = new Point3f();		flag = pIt.currentSegment(tmpCoords);		if (flag == PathIterator.SEG_CLOSE){		    if (num > 0) {			if (setMaxY) {			    // Get Previous point			    beginIdx = start;			    endIdx = numPoints-1;			}			contours.addElement(num);			num = 0;			numContours++;		    }		} else if (flag == PathIterator.SEG_MOVETO){			 vertex.x = tmpCoords[0];			 vertex.y = tmpCoords[1];			 lastX = vertex.x;			 lastY = vertex.y;			 if ((lastX == firstPntx) && (lastY == firstPnty)) {			     pIt.next();			     continue;			 }			 setMaxY = false;			 coords.add(vertex);			 firstPntx = lastX;			 firstPnty = lastY;			 if (num> 0){			     contours.addElement(num);			     num = 0;			     numContours++;			 }			 num++;			 numPoints++;			 // skip checking of first point,			 // since the last point will repeat this.			 start = numPoints ;		} else if (flag == PathIterator.SEG_LINETO){			 vertex.x = tmpCoords[0];			 vertex.y = tmpCoords[1];			 //Check here for duplicate points. Code			 //later in this function can not handle			 //duplicate points.			 if ((vertex.x == lastX) && (vertex.y == lastY)) {			     pIt.next();			     continue;			 }			 if (vertex.y > maxY) {			     maxY = vertex.y;			     maxYIndex = numPoints;			     setMaxY = true;			 }			 lastX = vertex.x;			 lastY = vertex.y;			 coords.add(vertex);			 num++;			 numPoints++;		} 		pIt.next();	    }	    	    // No data(e.g space, control characters)	    // Two point can't form a valid contour	    if (numPoints == 0){	      return null;	    }	    // Determine font winding order use for side triangles	    Point3f p1 = new Point3f(), p2 = new Point3f(), p3 = new Point3f();	    boolean flip_side_orient = true;	    Point3f vertices[] = (Point3f []) coords.toArray(false);	    if (endIdx - beginIdx > 0) {		// must be true unless it is a single line		// define as "MoveTo p1 LineTo p2 Close" which is		// not a valid font definition.				if (maxYIndex == beginIdx) {		    p1.set(vertices[endIdx]);		    		} else {		    p1.set(vertices[maxYIndex-1]);		    		}		p2.set(vertices[maxYIndex]);		    		if (maxYIndex == endIdx) {		    p3.set(vertices[beginIdx]);		} else {		    p3.set(vertices[maxYIndex+1]);		}		if (p3.x != p2.x) {		    if (p1.x != p2.x) {			// Use the one with smallest slope			if (Math.abs((p2.y - p1.y)/(p2.x - p1.x)) >			    Math.abs((p3.y - p2.y)/(p3.x - p2.x))) {			    flip_side_orient = (p3.x > p2.x);			} else {			    flip_side_orient = (p2.x > p1.x);			}		    } else {			flip_side_orient = (p3.x > p2.x);					    }		} else {		    // p1.x != p2.x, otherwise all three		    // point form a straight vertical line with		    // the middle point the highest. This is not a		    // valid font definition.		    flip_side_orient = (p2.x > p1.x);		}	    }	    // Build a Tree of Islands	    int  startIdx = 0;	    IslandsNode islandsTree = new IslandsNode(-1, -1);	    int contourCounts[] = contours.getData();	    for (i= 0;i < contours.getSize(); i++) {		endIdx = startIdx + contourCounts[i];		islandsTree.insert(new IslandsNode(startIdx, endIdx), vertices);		startIdx = endIdx;	    }      	    coords = null;   // Free memory 	    contours = null;	    contourCounts = null;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -