summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/classes/com/sun/opengl/util/j2d/TextRenderer.java143
-rwxr-xr-xsrc/classes/com/sun/opengl/util/j2d/TextureRenderer.java177
2 files changed, 230 insertions, 90 deletions
diff --git a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
index 7f47c011a..0ad84c90c 100755
--- a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
+++ b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java
@@ -262,26 +262,23 @@ public class TextRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
public void beginRendering(int width, int height) throws GLException {
- if (DEBUG && !debugged) {
- debug();
- }
+ beginRendering(true, width, height);
+ }
- getBackingStore().beginOrthoRendering(width, height);
- GL gl = GLU.getCurrentGL();
+ /** Begins rendering of 2D text in 3D with this {@link TextRenderer
+ TextRenderer} into the current OpenGL drawable. Assumes the end
+ user is responsible for setting up the modelview and projection
+ matrices, and will render text using the {@link #draw3D draw3D}
+ method. This method pushes some OpenGL state bits, binds and
+ enables the internal OpenGL texture object, sets the texture
+ environment mode to GL_MODULATE, and changes the current color
+ to the last color set with this TextRenderer via {@link
+ #setColor setColor}.
- if (!haveMaxSize) {
- // Query OpenGL for the maximum texture size and set it in the
- // RectanglePacker to keep it from expanding too large
- int[] sz = new int[1];
- gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0);
- packer.setMaxSize(sz[0], sz[0]);
- haveMaxSize = true;
- }
-
- // Change texture environment mode to MODULATE
- gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
- // Change text color to last saved
- gl.glColor4f(r, g, b, a);
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void begin3DRendering() throws GLException {
+ beginRendering(false, 0, 0);
}
/** Changes the current color of this TextRenderer to the supplied
@@ -320,6 +317,23 @@ public class TextRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
public void draw(String str, int x, int y) throws GLException {
+ draw3D(str, x, y, 0, 1);
+ }
+
+ /** Draws the supplied String at the desired 3D location using the
+ renderer's current color. The baseline of the leftmost character
+ is placed at position (x, y, z) in the current coordinate system.
+
+ @param str the string to draw
+ @param x the x coordinate at which to draw
+ @param y the y coordinate at which to draw
+ @param z the z coordinate at which to draw
+ @param scaleFactor a uniform scale factor applied to the width and height of the drawn rectangle
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void draw3D(String str,
+ float x, float y, float z,
+ float scaleFactor) {
// Split up the string into space-separated pieces
tokenize(str);
int xOffset = 0;
@@ -369,33 +383,39 @@ public class TextRenderer {
TextData data = (TextData) rect.getUserData();
data.markUsed();
- // Align the leftmost point of the baseline to the (x, y) coordinate requested
- renderer.drawOrthoRect(x - data.origin().x + xOffset,
- y - (rect.h() - data.origin().y),
- rect.x(),
- renderer.getHeight() - rect.y() - rect.h(),
- rect.w(), rect.h());
- xOffset += rect.w();
+ // Align the leftmost point of the baseline to the (x, y, z) coordinate requested
+ renderer.draw3DRect(x - scaleFactor * (data.origin().x + xOffset),
+ y - scaleFactor * ((rect.h() - data.origin().y)),
+ z,
+ rect.x(),
+ renderer.getHeight() - rect.y() - rect.h(),
+ rect.w(), rect.h(),
+ scaleFactor);
+ xOffset += rect.w() * scaleFactor;
}
- xOffset += getSpaceWidth();
+ xOffset += getSpaceWidth() * scaleFactor;
}
}
/** Ends a render cycle with this {@link TextRenderer TextRenderer}.
Restores the projection and modelview matrices as well as
- several OpenGL state bits.
+ several OpenGL state bits. Should be paired with {@link
+ #beginRendering beginRendering}.
@throws GLException If an OpenGL context is not current when this method is called
*/
public void endRendering() throws GLException {
- getBackingStore().endOrthoRendering();
- if (++numRenderCycles >= CYCLES_PER_FLUSH) {
- numRenderCycles = 0;
- if (DEBUG) {
- System.err.println("Clearing unused entries in endRendering()");
- }
- clearUnusedEntries();
- }
+ endRendering(true);
+ }
+
+ /** Ends a 3D render cycle with this {@link TextRenderer TextRenderer}.
+ Restores several OpenGL state bits. Should be paired with {@link
+ #begin3DRendering begin3DRendering}.
+
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void end3DRendering() throws GLException {
+ endRendering(false);
}
/** Disposes of all resources this TextRenderer is using. It is not
@@ -416,10 +436,13 @@ public class TextRenderer {
//
private static Rectangle2D normalize(Rectangle2D src) {
- return new Rectangle2D.Double((int) Math.floor(src.getMinX()),
- (int) Math.floor(src.getMinY()),
- (int) Math.ceil(src.getWidth()),
- (int) Math.ceil(src.getHeight()));
+ // Give ourselves a one-pixel boundary around each string in order
+ // to prevent bleeding of nearby Strings due to the fact that we
+ // use linear filtering
+ return new Rectangle2D.Double((int) Math.floor(src.getMinX() - 1),
+ (int) Math.floor(src.getMinY() - 1),
+ (int) Math.ceil(src.getWidth() + 2),
+ (int) Math.ceil(src.getHeight()) + 2);
}
private TextureRenderer getBackingStore() {
@@ -454,6 +477,48 @@ public class TextRenderer {
return cachedGraphics;
}
+ private void beginRendering(boolean ortho, int width, int height) {
+ if (DEBUG && !debugged) {
+ debug();
+ }
+
+ if (ortho) {
+ getBackingStore().beginOrthoRendering(width, height);
+ } else {
+ getBackingStore().begin3DRendering();
+ }
+ GL gl = GLU.getCurrentGL();
+
+ if (!haveMaxSize) {
+ // Query OpenGL for the maximum texture size and set it in the
+ // RectanglePacker to keep it from expanding too large
+ int[] sz = new int[1];
+ gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0);
+ packer.setMaxSize(sz[0], sz[0]);
+ haveMaxSize = true;
+ }
+
+ // Change texture environment mode to MODULATE
+ gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
+ // Change text color to last saved
+ gl.glColor4f(r, g, b, a);
+ }
+
+ private void endRendering(boolean ortho) throws GLException {
+ if (ortho) {
+ getBackingStore().endOrthoRendering();
+ } else {
+ getBackingStore().end3DRendering();
+ }
+ if (++numRenderCycles >= CYCLES_PER_FLUSH) {
+ numRenderCycles = 0;
+ if (DEBUG) {
+ System.err.println("Clearing unused entries in endRendering()");
+ }
+ clearUnusedEntries();
+ }
+ }
+
private int getSpaceWidth() {
if (spaceWidth < 0) {
Graphics2D g = getGraphics2D();
diff --git a/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
index 976806db3..3670d3c51 100755
--- a/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
+++ b/src/classes/com/sun/opengl/util/j2d/TextureRenderer.java
@@ -274,13 +274,14 @@ public class TextureRenderer {
/** Convenience method which assists in rendering portions of the
OpenGL texture to the screen, if the application intends to draw
- them as a flat overlay on to the screen. Sets up the viewing
- matrices, for orthographic rendering where the coordinates go
+ them as a flat overlay on to the screen. Pushes OpenGL state
+ bits (GL_ENABLE_BIT, GL_DEPTH_BUFFER_BIT and GL_TRANSFORM_BIT);
+ disables the depth test, back-face culling, and lighting;
+ enables the texture in this renderer; and sets up the viewing
+ matrices for orthographic rendering where the coordinates go
from (0, 0) at the lower left to (width, height) at the upper
- right; disables the depth test and lighting; and enables the
- texture in this renderer. {@link #endOrthoRendering} must be
- used in conjunction with this method to restore all OpenGL
- states.
+ right. {@link #endOrthoRendering} must be used in conjunction
+ with this method to restore all OpenGL states.
@param width the width of the current on-screen OpenGL drawable
@param height the height of the current on-screen OpenGL drawable
@@ -288,37 +289,24 @@ public class TextureRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
public void beginOrthoRendering(int width, int height) throws GLException {
- GL gl = GLU.getCurrentGL();
- gl.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT);
- gl.glDisable(GL.GL_DEPTH_TEST);
- gl.glDisable(GL.GL_CULL_FACE);
- gl.glDisable(GL.GL_LIGHTING);
- gl.glMatrixMode(GL.GL_PROJECTION);
- gl.glPushMatrix();
- gl.glLoadIdentity();
- glu.gluOrtho2D(0, width, 0, height);
- gl.glMatrixMode(GL.GL_MODELVIEW);
- gl.glPushMatrix();
- gl.glLoadIdentity();
- gl.glMatrixMode(GL.GL_TEXTURE);
- gl.glPushMatrix();
- gl.glLoadIdentity();
- gl.glEnable(GL.GL_BLEND);
- gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
- Texture texture = getTexture();
- texture.enable();
- texture.bind();
- gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
- if (smoothingChanged) {
- smoothingChanged = false;
- if (smoothing) {
- texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
- texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
- } else {
- texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
- texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
- }
- }
+ beginRendering(true, width, height);
+ }
+
+ /** Convenience method which assists in rendering portions of the
+ OpenGL texture to the screen as 2D quads in 3D space. Pushes
+ OpenGL state (GL_ENABLE_BIT); disables lighting; and enables the
+ texture in this renderer. Unlike {@link #beginOrthoRendering
+ beginOrthoRendering}, does not modify the depth test, back-face
+ culling, lighting, or the modelview or projection matrices. The
+ user is responsible for setting up the view matrices for correct
+ results of {@link #draw3DRect draw3DRect}. {@link
+ #end3DRendering} must be used in conjunction with this method to
+ restore all OpenGL states.
+
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void begin3DRendering() throws GLException {
+ beginRendering(false, 0, 0);
}
/** Draws an orthographically projected rectangle containing all of
@@ -360,6 +348,38 @@ public class TextureRenderer {
public void drawOrthoRect(int screenx, int screeny,
int texturex, int texturey,
int width, int height) throws GLException {
+ draw3DRect(screenx, screeny, 0, texturex, texturey, width, height, 1);
+ }
+
+ /** Draws a rectangle of the underlying texture to the specified 3D
+ location. In the current coordinate system, the lower left
+ corner of the rectangle is placed at (x, y, z), and the upper
+ right corner is placed at (x + width * scaleFactor, y + height *
+ scaleFactor, z). The lower left corner of the sub-rectangle of
+ the texture is (texturex, texturey) and the upper right corner
+ is (texturex + width, texturey + height). For back-face culling
+ purposes, the rectangle is drawn with counterclockwise
+ orientation of the vertices when viewed from the front.
+
+ @param x the x coordinate at which to draw the rectangle
+ @param y the y coordinate at which to draw the rectangle
+ @param z the z coordinate at which to draw the rectangle
+ @param texturex the x coordinate of the pixel in the texture of
+ the lower left portion of the rectangle to draw
+ @param texturey the y coordinate of the pixel in the texture
+ (relative to lower left) of the lower left portion of the
+ rectangle to draw
+ @param width the width in texels of the rectangle to draw
+ @param height the height in texels of the rectangle to draw
+ @param scaleFactor the scale factor to apply (multiplicatively)
+ to the size of the drawn rectangle
+
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void draw3DRect(float x, float y, float z,
+ int texturex, int texturey,
+ int width, int height,
+ float scaleFactor) throws GLException {
GL gl = GLU.getCurrentGL();
Texture texture = getTexture();
TextureCoords coords = texture.getSubImageTexCoords(texturex, texturey,
@@ -367,13 +387,13 @@ public class TextureRenderer {
texturey + height);
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(coords.left(), coords.bottom());
- gl.glVertex3f(screenx, screeny, 0);
+ gl.glVertex3f(x, y, z);
gl.glTexCoord2f(coords.right(), coords.bottom());
- gl.glVertex3f(screenx + width, screeny, 0);
+ gl.glVertex3f(x + width * scaleFactor, y, z);
gl.glTexCoord2f(coords.right(), coords.top());
- gl.glVertex3f(screenx + width, screeny + height, 0);
+ gl.glVertex3f(x + width * scaleFactor, y + height * scaleFactor, z);
gl.glTexCoord2f(coords.left(), coords.top());
- gl.glVertex3f(screenx, screeny + height, 0);
+ gl.glVertex3f(x, y + height * scaleFactor, z);
gl.glEnd();
}
@@ -386,22 +406,77 @@ public class TextureRenderer {
@throws GLException If an OpenGL context is not current when this method is called
*/
public void endOrthoRendering() throws GLException {
- GL gl = GLU.getCurrentGL();
- Texture texture = getTexture();
- texture.disable();
- gl.glMatrixMode(GL.GL_PROJECTION);
- gl.glPopMatrix();
- gl.glMatrixMode(GL.GL_MODELVIEW);
- gl.glPopMatrix();
- gl.glMatrixMode(GL.GL_TEXTURE);
- gl.glPopMatrix();
- gl.glPopAttrib();
+ endRendering(true);
+ }
+
+ /** Convenience method which assists in rendering portions of the
+ OpenGL texture to the screen as 2D quads in 3D space. Must be
+ used if {@link #begin3DRendering} is used to set up the
+ rendering stage for this overlay.
+
+ @throws GLException If an OpenGL context is not current when this method is called
+ */
+ public void end3DRendering() throws GLException {
+ endRendering(false);
}
//----------------------------------------------------------------------
// Internals only below this point
//
+ private void beginRendering(boolean ortho, int width, int height) {
+ GL gl = GLU.getCurrentGL();
+ int attribBits =
+ GL.GL_ENABLE_BIT | (ortho ? (GL.GL_DEPTH_BUFFER_BIT | GL.GL_TRANSFORM_BIT) : 0);
+ gl.glPushAttrib(attribBits);
+ gl.glDisable(GL.GL_LIGHTING);
+ if (ortho) {
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ gl.glDisable(GL.GL_CULL_FACE);
+ gl.glMatrixMode(GL.GL_PROJECTION);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ glu.gluOrtho2D(0, width, 0, height);
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPushMatrix();
+ gl.glLoadIdentity();
+ }
+ gl.glEnable(GL.GL_BLEND);
+ gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+ Texture texture = getTexture();
+ texture.enable();
+ texture.bind();
+ gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
+ if (smoothingChanged) {
+ smoothingChanged = false;
+ if (smoothing) {
+ texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
+ texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
+ } else {
+ texture.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
+ texture.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
+ }
+ }
+ }
+
+ private void endRendering(boolean ortho) {
+ GL gl = GLU.getCurrentGL();
+ Texture texture = getTexture();
+ texture.disable();
+ if (ortho) {
+ gl.glMatrixMode(GL.GL_PROJECTION);
+ gl.glPopMatrix();
+ gl.glMatrixMode(GL.GL_MODELVIEW);
+ gl.glPopMatrix();
+ gl.glMatrixMode(GL.GL_TEXTURE);
+ gl.glPopMatrix();
+ }
+ gl.glPopAttrib();
+ }
+
private void init(int width, int height) {
// Discard previous BufferedImage if any
if (image != null) {