📄 text3dretained.java
字号:
/* * $RCSfile: Text3DRetained.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.8 $ * $Date: 2007/04/12 17:34:07 $ * $State: Exp $ */package javax.media.j3d;import javax.vecmath.*;import java.awt.font.*;import java.awt.*;import java.awt.geom.Rectangle2D;import java.util.ArrayList;/** * Implements Text3D class. */class Text3DRetained extends GeometryRetained { /** * Packaged scope variables needed for implementation */ Font3D font3D = null; String string = null; Point3f position = new Point3f(0.0f, 0.0f, 0.0f); int alignment = Text3D.ALIGN_FIRST, path = Text3D.PATH_RIGHT; float charSpacing = 0.0f; int numChars = 0; static final int targetThreads = (J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_GEOMETRY | J3dThread.UPDATE_RENDER); /** * The temporary transforms for this Text3D */ Transform3D[] charTransforms = new Transform3D[0]; /** * A cached list of geometry arrays for the current settings */ GeometryArrayRetained[] geometryList = new GeometryArrayRetained[0]; GlyphVector[] glyphVecs = new GlyphVector[0]; /** * Bounding box data for this text string. */ Point3d lower = new Point3d(); Point3d upper = new Point3d(); /** * An Array list used for messages */ ArrayList newGeometryAtomList = new ArrayList(); ArrayList oldGeometryAtomList = new ArrayList(); /** * temporary model view matrix for immediate mode only */ Transform3D vpcToEc; Transform3D drawTransform; Text3DRetained(){ this.geoType = GEO_TYPE_TEXT3D; } synchronized void computeBoundingBox() { Point3d l = new Point3d(); Point3d u = new Point3d(); Vector3f location = new Vector3f(this.position); int i, k=0, numTotal=0; double width = 0, height = 0; Rectangle2D bounds; //Reset bounds data l.set(location); u.set(location); if (numChars != 0) { // Set loop counters based on path type if (path == Text3D.PATH_RIGHT || path == Text3D.PATH_UP) { k = 0; numTotal = numChars + 1; } else if (path == Text3D.PATH_LEFT || path == Text3D.PATH_DOWN) { k = 1; numTotal = numChars; // Reset bounds to bounding box if first character bounds = glyphVecs[0].getVisualBounds(); u.x += bounds.getWidth(); u.y += bounds.getHeight(); } for (i=1; i<numTotal; i++, k++) { width = glyphVecs[k].getLogicalBounds().getWidth(); bounds = glyphVecs[k].getVisualBounds(); // 'switch' could be outside loop with little hacking, width += charSpacing; height = bounds.getHeight(); switch (this.path) { case Text3D.PATH_RIGHT: u.x += (width); if (u.y < (height + location.y)) { u.y = location.y + height; } break; case Text3D.PATH_LEFT: l.x -= (width); if (u.y < ( height + location.y)) { u.y = location.y + height; } break; case Text3D.PATH_UP: u.y += height; if (u.x < (bounds.getWidth() + location.x)) { u.x = location.x + bounds.getWidth(); } break; case Text3D.PATH_DOWN: l.y -= height; if (u.x < (bounds.getWidth() + location.x)) { u.x = location.x + bounds.getWidth(); } break; } } // Handle string alignment. ALIGN_FIRST is handled by default if (alignment != Text3D.ALIGN_FIRST) { double cx = (u.x - l.x); double cy = (u.y - l.y); if (alignment == Text3D.ALIGN_CENTER) { cx *= .5; cy *= .5; } switch (path) { case Text3D.PATH_RIGHT: l.x -= cx; u.x -= cx; break; case Text3D.PATH_LEFT: l.x += cx; u.x += cx; break; case Text3D.PATH_UP: l.y -= cy; u.y -= cy; break; case Text3D.PATH_DOWN: l.y += cy; u.y += cy; break; } } } l.z = 0.0f; if ((font3D == null) || (font3D.fontExtrusion == null)) { u.z = l.z; } else { u.z = l.z + font3D.fontExtrusion.length; } } void update() {} /** * Returns the Font3D objects used by this Text3D NodeComponent object. * * @return the Font3D object of this Text3D node - null if no Font3D * has been associated with this node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final Font3D getFont3D() { return this.font3D; } /** * Sets the Font3D object used by this Text3D NodeComponent object. * * @param font3d the Font3D object to associate with this Text3D node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final void setFont3D(Font3D font3d) { geomLock.getLock(); this.font3D = font3d; updateCharacterData(); geomLock.unLock(); sendDataChangedMessage(); } /** * Copies the character string used in the construction of the * Text3D node into the supplied parameter. * * @return a copy of the String object in this Text3D node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final String getString() { return this.string; } /** * Copies the character string from the supplied parameter into Tex3D * node. * * @param string the String object to recieve the Text3D node's string. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final void setString(String string) { geomLock.getLock(); this.string = string; if (string == null) { numChars = 0; } else { numChars = string.length(); } updateCharacterData(); geomLock.unLock(); sendDataChangedMessage(); } /** * Copies the node's <code>position</code> field into the supplied * parameter. The <code>position</code> is used to determine the * initial placement of the Text3D string. The position, combined with * the path and alignment control how the text is displayed. * * @param position the point to position the text. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @see #getAlignment * @see #getPath */ final void getPosition(Point3f position) { position.set(this.position); } /** * Sets the node's <code>position</code> field to the supplied * parameter. The <code>position</code> is used to determine the * initial placement of the Text3D string. The position, combined with * the path and alignment control how the text is displayed. * * @param position the point to position the text. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @see #getAlignment * @see #getPath */ final void setPosition(Point3f position) { geomLock.getLock(); this.position.set(position); updateTransformData(); geomLock.unLock(); sendTransformChangedMessage(); } /** * Retrieves the text alignment policy for this Text3D NodeComponent * object. The <code>alignment</code> is used to specify how * glyphs in the string are placed in relation to the * <code>position</code> field. Valid values for this field * are: * <UL> * <LI> ALIGN_CENTER - the center of the string is placed on the * <code>position</code> point. * <LI> ALIGN_FIRST - the first character of the string is placed on * the <code>position</code> point. * <LI> ALIGN_LAST - the last character of the string is placed on the * <code>position</code> point. * </UL> * The default value of this field is <code>ALIGN_FIRST</code>. * * @return the current alingment policy for this node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @see #getPosition */ final int getAlignment() { return alignment; } /** * Sets the text alignment policy for this Text3D NodeComponent * object. The <code>alignment</code> is used to specify how * glyphs in the string are placed in relation to the * <code>position</code> field. Valid values for this field * are: * <UL> * <LI> ALIGN_CENTER - the center of the string is placed on the * <code>position</code> point. * <LI> ALIGN_FIRST - the first character of the string is placed on * the <code>position</code> point. * <LI> ALIGN_LAST - the last character of the string is placed on the * <code>position</code> point. * </UL> * The default value of this field is <code>ALIGN_FIRST</code>. * * @return the current alingment policy for this node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @see #getPosition */ final void setAlignment(int alignment) { geomLock.getLock(); this.alignment = alignment; updateTransformData(); geomLock.unLock(); sendTransformChangedMessage(); } /** * Retrieves the node's <code>path</code> field. This field * is used to specify how succeeding * glyphs in the string are placed in relation to the previous glyph. * Valid values for this field are: * <UL> * <LI> PATH_LEFT: - succeeding glyphs are placed to the left of the * current glyph. * <LI> PATH_RIGHT: - succeeding glyphs are placed to the right of the * current glyph. * <LI> PATH_UP: - succeeding glyphs are placed above the current glyph. * <LI> PATH_DOWN: - succeeding glyphs are placed below the current glyph. * </UL> * The default value of this field is <code>PATH_RIGHT</code>. * * @return the current alingment policy for this node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final int getPath() { return this.path; } /** * Sets the node's <code>path</code> field. This field * is used to specify how succeeding * glyphs in the string are placed in relation to the previous glyph. * Valid values for this field are: * <UL> * <LI> PATH_LEFT - succeeding glyphs are placed to the left of the * current glyph. * <LI> PATH_RIGHT - succeeding glyphs are placed to the right of the * current glyph. * <LI> PATH_UP - succeeding glyphs are placed above the current glyph. * <LI> PATH_DOWN - succeeding glyphs are placed below the current glyph. * </UL> * The default value of this field is <code>PATH_RIGHT</code>. * * @param path the value to set the path to. * * @return the current alingment policy for this node. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final void setPath(int path) { this.path = path; updateTransformData(); sendTransformChangedMessage(); } /** * Retrieves the 3D bounding box that encloses this Text3D object. * * @param bounds the object to copy the bounding information to. * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph * * @see BoundingBox */ final void getBoundingBox(BoundingBox bounds) { synchronized (this) { bounds.setLower(lower); bounds.setUpper(upper); } } /** * Retrieves the character spacing used to construct the Text3D string. * This spacing is in addition to the regular spacing between glyphs as * defined in the Font object. 1.0 in this space is measured as the * width of the largest glyph in the 2D Font. The default value is * 0.0. * * @return the current character spacing value * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final float getCharacterSpacing() { return charSpacing; } /** * Sets the character spacing used hwne constructing the Text3D string. * This spacing is in addition to the regular spacing between glyphs as * defined in the Font object. 1.0 in this space is measured as the * width of the largest glyph in the 2D Font. The default value is * 0.0. * * @param characterSpacing the new character spacing value * * @exception CapabilityNotSetException if appropriate capability is * not set and this object is part of live or compiled scene graph */ final void setCharacterSpacing(float characterSpacing) { geomLock.getLock(); this.charSpacing = characterSpacing; updateTransformData(); geomLock.unLock(); sendTransformChangedMessage(); } final void sendDataChangedMessage() { J3dMessage[] m; int i, j, k, kk, numMessages; int gSize; ArrayList shapeList, gaList; Shape3DRetained s; GeometryAtom[] newGeometryAtoms; ArrayList tiArrList = new ArrayList(); ArrayList newCtArrArrList = new ArrayList(); synchronized(liveStateLock) { if (source.isLive()) { synchronized (universeList) { numMessages = universeList.size(); m = new J3dMessage[numMessages]; for (i=0; i<numMessages; i++) { m[i] = new J3dMessage(); m[i].type = J3dMessage.TEXT3D_DATA_CHANGED; m[i].threads = targetThreads; shapeList = (ArrayList)userLists.get(i); newGeometryAtomList.clear(); oldGeometryAtomList.clear(); for (j=0; j<shapeList.size(); j++) { s = (Shape3DRetained)shapeList.get(j); if (s.boundsAutoCompute) { // update combine bounds of mirrorShape3Ds. So we need to // use its bounds and not localBounds. // bounds is actually a reference to // mirrorShape3D.source.localBounds. // XXXX : Should only need to update distinct localBounds. s.getCombineBounds((BoundingBox)s.bounds); } gSize = s.geometryList.size(); GeometryAtom oldGA = Shape3DRetained.getGeomAtom(s); GeometryAtom newGA = new GeometryAtom(); int geometryCnt = 0; for(k = 0; k<gSize; k++) { GeometryRetained geomRetained = (GeometryRetained) s.geometryList.get(k); if(geomRetained != null) { Text3DRetained tempT3d = (Text3DRetained)geomRetained; geometryCnt += tempT3d.numChars;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -