From 07ed9971c95a1d1312f8d389d310902a95e8657c Mon Sep 17 00:00:00 2001 From: Kenneth Russel Date: Sun, 11 Feb 2007 05:16:38 +0000 Subject: Added RenderDelegate mechanism to TextRenderer to provide more control where desired over the rendered text bitmap. Added CustomText demo to demonstrate its usage. git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@1128 232f8b59-042b-4e1e-8c03-345bb8c30851 --- .../com/sun/opengl/util/j2d/TextRenderer.java | 122 +++++++++++++++++---- 1 file changed, 103 insertions(+), 19 deletions(-) diff --git a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java index 3528773b3..c4d2ee6df 100755 --- a/src/classes/com/sun/opengl/util/j2d/TextRenderer.java +++ b/src/classes/com/sun/opengl/util/j2d/TextRenderer.java @@ -109,11 +109,11 @@ public class TextRenderer { private RectanglePacker packer; private boolean haveMaxSize; + private RenderDelegate renderDelegate; private TextureRenderer cachedBackingStore; private Graphics2D cachedGraphics; private FontRenderContext cachedFontRenderContext; private Map/**/ stringLocations = new HashMap/**/(); - private static final Color TRANSPARENT_BLACK = new Color(0.0f, 0.0f, 0.0f, 0.0f); // Support tokenization of space-separated words // NOTE: not exposing this at the present time as we aren't @@ -161,12 +161,48 @@ public class TextRenderer { void clearUsed() { used = false; } } + /** Class supporting more full control over the process of rendering + the bitmapped text. Allows customization of whether the backing + store text bitmap is full-color or intensity only, the size of + each individual rendered text rectangle, and the contents of + each individual rendered text string. The default implementation + of this interface uses an intensity-only texture, a + closely-cropped rectangle around the text, and renders text + using the color white, which is modulated by the set color + during the rendering process. */ + public static interface RenderDelegate { + /** Indicates whether the backing store of this TextRenderer + should be intensity-only (the default) or full-color. */ + public boolean intensityOnly(); + + /** Computes the bounds of the given text string relative to the + origin. */ + public Rectangle2D getBounds(String str, + Font font, + FontRenderContext frc); + + /** Render the passed String at the designated location using the + supplied Graphics2D instance. The surrounding region will + already have been cleared to the RGB color (0, 0, 0) with zero + alpha. The initial drawing context of the passed Graphics2D + will be set to use AlphaComposite.Src, the color white, the + Font specified in the TextRenderer's constructor, and the + rendering hints specified in the TextRenderer constructor. + Changes made by the end user may be visible in successive + calls to this method, but are not guaranteed to be preserved. + Implementors of this method should reset the Graphics2D's + state to that desired each time this method is called, in + particular those states which are not the defaults. */ + public void draw(Graphics2D graphics, String str, int x, int y); + } + // Debugging purposes only private boolean debugged; /** Creates a new TextRenderer with the given font, using no - antialiasing or fractional metrics. Equivalent to - TextRenderer(font, false, false). + antialiasing or fractional metrics, and the default + RenderDelegate. Equivalent to TextRenderer(font, false, + false). @param font the font to render with */ @@ -174,10 +210,12 @@ public class TextRenderer { this(font, false, false); } - /** Creates a new TextRenderer with the given Font and specified - font properties. The antialiased and - useFractionalMetrics flags provide control over the - same properties at the Java 2D level. + /** Creates a new TextRenderer with the given Font, specified font + properties, and default RenderDelegate. The + antialiased and useFractionalMetrics + flags provide control over the same properties at the Java 2D + level. Equivalent to TextRenderer(font, antialiased, + useFractionalMetrics, null). @param font the font to render with @param antialiased whether to use antialiased fonts @@ -187,6 +225,27 @@ public class TextRenderer { public TextRenderer(Font font, boolean antialiased, boolean useFractionalMetrics) { + this(font, antialiased, useFractionalMetrics, null); + } + + /** Creates a new TextRenderer with the given Font, specified font + properties, and given RenderDelegate. The + antialiased and useFractionalMetrics + flags provide control over the same properties at the Java 2D + level. The renderDelegate provides more control + over the text rendered. + + @param font the font to render with + @param antialiased whether to use antialiased fonts + @param useFractionalMetrics whether to use fractional font + metrics at the Java 2D level + @param renderDelegate the render delegate to use to draw the + text's bitmap, or null to use the default one + */ + public TextRenderer(Font font, + boolean antialiased, + boolean useFractionalMetrics, + RenderDelegate renderDelegate) { this.font = font; this.antialiased = antialiased; this.useFractionalMetrics = useFractionalMetrics; @@ -194,6 +253,11 @@ public class TextRenderer { // FIXME: consider adjusting the size based on font size // (it will already automatically resize if necessary) packer = new RectanglePacker(new Manager(), 256, 256); + + if (renderDelegate == null) { + renderDelegate = new DefaultRenderDelegate(); + } + this.renderDelegate = renderDelegate; } /** Returns the bounding rectangle of the given String, assuming it @@ -223,11 +287,9 @@ public class TextRenderer { r.w(), r.h()); } - FontRenderContext frc = getFontRenderContext(); - GlyphVector gv = font.createGlyphVector(frc, str); // Must return a Rectangle compatible with the layout algorithm -- // must be idempotent - return normalize(gv.getPixelBounds(frc, 0, 0)); + return normalize(renderDelegate.getBounds(str, font, getFontRenderContext())); } /** Returns the Font this renderer is using. */ @@ -362,9 +424,9 @@ public class TextRenderer { if (rect == null) { // Rasterize this string and place it on the backing store Graphics2D g = getGraphics2D(); - FontRenderContext frc = getFontRenderContext(); - GlyphVector gv = font.createGlyphVector(frc, curStr); - Rectangle2D bbox = normalize(gv.getPixelBounds(frc, 0, 0)); + Rectangle2D bbox = + normalize(renderDelegate.getBounds(curStr, font, + getFontRenderContext())); Point origin = new Point((int) -bbox.getMinX(), (int) -bbox.getMinY()); rect = new Rect(0, 0, @@ -383,11 +445,11 @@ public class TextRenderer { int strx = rect.x() + origin.x; int stry = rect.y() + origin.y; // Clear out the area we're going to draw into - g.setColor(TRANSPARENT_BLACK); + g.setComposite(AlphaComposite.Clear); g.fillRect(rect.x(), rect.y(), rect.w(), rect.h()); - g.setColor(Color.WHITE); + g.setComposite(AlphaComposite.Src); // Draw the string - g.drawString(curStr, strx, stry); + renderDelegate.draw(g, curStr, strx, stry); // Sync to the OpenGL texture getBackingStore().sync(rect.x(), rect.y(), rect.w(), rect.h()); } @@ -599,9 +661,9 @@ public class TextRenderer { if (DEBUG) { Graphics2D g = getGraphics2D(); - g.setColor(TRANSPARENT_BLACK); + g.setComposite(AlphaComposite.Clear); g.fillRect(r.x(), r.y(), r.w(), r.h()); - g.setColor(Color.WHITE); + g.setComposite(AlphaComposite.Src); } } @@ -627,7 +689,12 @@ public class TextRenderer { // whether we're likely to need to support a full RGBA backing // store (i.e., non-default Paint, foreground color, etc.), but // for now, let's just be more efficient - TextureRenderer renderer = TextureRenderer.createAlphaOnlyRenderer(w, h); + TextureRenderer renderer; + if (renderDelegate.intensityOnly()) { + renderer = TextureRenderer.createAlphaOnlyRenderer(w, h); + } else { + renderer = new TextureRenderer(w, h, true); + } if (DEBUG) { System.err.println(" TextRenderer allocating backing store " + w + " x " + h); } @@ -713,6 +780,23 @@ public class TextRenderer { } } + class DefaultRenderDelegate implements RenderDelegate { + public boolean intensityOnly() { + return true; + } + + public Rectangle2D getBounds(String str, + Font font, + FontRenderContext frc) { + GlyphVector gv = font.createGlyphVector(frc, str); + return gv.getPixelBounds(frc, 0, 0); + } + + public void draw(Graphics2D graphics, String str, int x, int y) { + graphics.drawString(str, x, y); + } + } + //---------------------------------------------------------------------- // Debugging functionality // -- cgit v1.2.3