diff options
author | Sven Gothel <[email protected]> | 2014-02-27 23:56:13 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-02-27 23:56:13 +0100 |
commit | 67ec86e539a3db0d06e5cc3550db453589594384 (patch) | |
tree | 66d006ff20407cb6bfc16fb288a5d4665df077cf | |
parent | 2cafc01f08f9ab05748be6eeb82c417de38b31f7 (diff) |
Bug 801: Graph TextRenderer Cleanup Part-4: Text[Render->Region]Util API: Better separation of cached and uncached regions
-rw-r--r-- | src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java (renamed from src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderUtil.java) | 83 | ||||
-rw-r--r-- | src/jogl/classes/com/jogamp/graph/font/Font.java | 6 | ||||
-rw-r--r-- | src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java | 43 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java | 47 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java | 6 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java | 31 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java | 8 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java | 7 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java | 2 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java | 12 | ||||
-rw-r--r-- | src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java | 12 |
11 files changed, 136 insertions, 121 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java index 944050a14..e7ed335ec 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderUtil.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java @@ -30,7 +30,6 @@ package com.jogamp.graph.curve.opengl; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; -import java.util.List; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLException; @@ -41,47 +40,36 @@ import com.jogamp.graph.curve.OutlineShape; import com.jogamp.graph.curve.Region; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.Font.Glyph; -import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; /** - * - * FIXME: Add VBO Vertex Factory for drawString3D ! - * + * Text {@link GLRegion} Utility Class */ -public class TextRenderUtil { +public class TextRegionUtil { public final RegionRenderer renderer; - public TextRenderUtil(final RegionRenderer renderer) { + public TextRegionUtil(final RegionRenderer renderer) { this.renderer = renderer; } /** - * Generate a Region to represent this Object. - * <p> - * Each glyph is cached and reused. - * </p> - * - * @param renderModes bit-field of modes, e.g. {@link Region#VARIABLE_CURVE_WEIGHT_BIT}, {@link Region#VBAA_RENDERING_BIT} + * Add the string in 3D space w.r.t. the font and pixelSize at the end of the {@link GLRegion}. + * @param region the {@link GLRegion} sink * @param vertexFactory vertex impl factory {@link Factory} * @param font the target {@link Font} * @param str string text * @param pixelSize */ - public static GLRegion createRegion(final int renderModes, final Factory<? extends Vertex> vertexFactory, - final Font font, final CharSequence str, final int pixelSize) { + public static void addStringToRegion(final GLRegion region, final Factory<? extends Vertex> vertexFactory, + final Font font, final CharSequence str, final int pixelSize) { final int charCount = str.length(); - final GLRegion region = GLRegion.create(renderModes); // region.setFlipped(true); final Font.Metrics metrics = font.getMetrics(); + final float lineHeight = font.getLineHeight(pixelSize); - final float lineGap = metrics.getLineGap(pixelSize) ; - final float ascent = metrics.getAscent(pixelSize) ; - final float descent = metrics.getDescent(pixelSize) ; - final float advanceY = lineGap - descent + ascent; final float scale = metrics.getScale(pixelSize); final AffineTransform transform = new AffineTransform(vertexFactory); final AffineTransform t = new AffineTransform(vertexFactory); @@ -92,7 +80,7 @@ public class TextRenderUtil { for(int i=0; i< charCount; i++) { final char character = str.charAt(i); if( '\n' == character ) { - y += advanceY; + y -= lineHeight; advanceTotal = 0; } else if (character == ' ') { advanceTotal += font.getAdvanceWidth(Glyph.ID_SPACE, pixelSize); @@ -114,37 +102,41 @@ public class TextRenderUtil { advanceTotal += glyph.getAdvance(pixelSize, true); } } - return region; } /** - * Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated + * Render the string in 3D space w.r.t. the font and pixelSize + * using a cached {@link GLRegion} for reuse. + * <p> + * Cached {@link GLRegion}s will be destroyed w/ {@link #clear(GL2ES2)} or to free memory. + * </p> * @param gl the current GL state * @param font {@link Font} to be used * @param str text to be rendered * @param pixelSize font size - * @param texWidth desired texture width for multipass-rendering. + * @param texSize desired texture width for multipass-rendering. * The actual used texture-width is written back when mp rendering is enabled, otherwise the store is untouched. * @throws Exception if TextRenderer not initialized */ public void drawString3D(final GL2ES2 gl, - final Font font, final CharSequence str, final int pixelSize, final int[/*1*/] texSize) { - if(!renderer.isInitialized()){ + final Font font, final CharSequence str, final int pixelSize, + final int[/*1*/] texSize) { + if( !renderer.isInitialized() ) { throw new GLException("TextRendererImpl01: not initialized!"); } final RenderState rs = renderer.getRenderState(); GLRegion region = getCachedRegion(font, str, pixelSize); if(null == region) { - region = createRegion(renderer.getRenderModes(), rs.getVertexFactory(), font, str, pixelSize); + region = GLRegion.create(renderer.getRenderModes()); + addStringToRegion(region, rs.getVertexFactory(), font, str, pixelSize); addCachedRegion(gl, font, str, pixelSize, region); } region.draw(gl, renderer, texSize); } /** - * Render the String in 3D space wrt to the font provided at the position provided - * the outlines will be generated, if not yet generated + * Render the string in 3D space w.r.t. the font and pixelSize + * using a temporary {@link GLRegion}, which will be destroyed afterwards. * @param gl the current GL state * @param font {@link Font} to be used * @param str text to be rendered @@ -154,27 +146,22 @@ public class TextRenderUtil { * @throws Exception if TextRenderer not initialized */ public static void drawString3D(final RegionRenderer renderer, final GL2ES2 gl, - final Font font, final CharSequence str, final int fontSize, final int[/*1*/] texSize) { + final Font font, final CharSequence str, final int fontSize, + final int[/*1*/] texSize) { if(!renderer.isInitialized()){ throw new GLException("TextRendererImpl01: not initialized!"); } final RenderState rs = renderer.getRenderState(); - GLRegion region = createRegion(renderer.getRenderModes(), rs.getVertexFactory(), font, str, fontSize); + final GLRegion region = GLRegion.create(renderer.getRenderModes()); + addStringToRegion(region, rs.getVertexFactory(), font, str, fontSize); region.draw(gl, renderer, texSize); + region.destroy(gl, renderer); } - /** FIXME - public void flushCache(GL2ES2 gl) { - Iterator<GlyphString> iterator = stringCacheMap.values().iterator(); - while(iterator.hasNext()){ - GlyphString glyphString = iterator.next(); - glyphString.destroy(gl, rs); - } - stringCacheMap.clear(); - stringCacheArray.clear(); - } */ - - public void destroy(GL2ES2 gl) { + /** + * Clear all cached {@link GLRegions}. + */ + public void clear(GL2ES2 gl) { // fluchCache(gl) already called final Iterator<GLRegion> iterator = stringCacheMap.values().iterator(); while(iterator.hasNext()){ @@ -252,9 +239,11 @@ public class TextRenderUtil { protected final void removeCachedRegion(GL2ES2 gl, int idx) { final String key = stringCacheArray.remove(idx); - final GLRegion region = stringCacheMap.remove(key); - if(null != region) { - region.destroy(gl, renderer); + if( null != key ) { + final GLRegion region = stringCacheMap.remove(key); + if(null != region) { + region.destroy(gl, renderer); + } } } diff --git a/src/jogl/classes/com/jogamp/graph/font/Font.java b/src/jogl/classes/com/jogamp/graph/font/Font.java index afffe0654..122015218 100644 --- a/src/jogl/classes/com/jogamp/graph/font/Font.java +++ b/src/jogl/classes/com/jogamp/graph/font/Font.java @@ -73,6 +73,9 @@ public interface Font { /** * Glyph for font + * + * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6cmap.html + * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6glyf.html */ public interface Glyph { // reserved special glyph IDs @@ -103,11 +106,12 @@ public interface Font { public StringBuilder getAllNames(StringBuilder string, String separator); - public float getAdvanceWidth(int i, float pixelSize); + public float getAdvanceWidth(int glyphID, float pixelSize); public Metrics getMetrics(); public Glyph getGlyph(char symbol); public int getNumGlyphs(); + public float getLineHeight(float pixelSize); public float getStringWidth(CharSequence string, float pixelSize); public float getStringHeight(CharSequence string, float pixelSize); public AABBox getStringBounds(CharSequence string, float pixelSize); diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java index 81c06cd83..8dd9ce4d7 100644 --- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java +++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java @@ -166,8 +166,8 @@ class TypecastFont implements Font { } @Override - public float getAdvanceWidth(int i, float pixelSize) { - return font.getHmtxTable().getAdvanceWidth(i) * metrics.getScale(pixelSize); + public float getAdvanceWidth(int glyphID, float pixelSize) { + return font.getHmtxTable().getAdvanceWidth(glyphID) * metrics.getScale(pixelSize); } @Override @@ -197,7 +197,7 @@ class TypecastFont implements Font { if(null == glyph) { throw new RuntimeException("Could not retrieve glyph for symbol: <"+symbol+"> "+(int)symbol+" -> glyph id "+code); } - final OutlineShape shape = TypecastRenderer.buildShape(glyph, vertexFactory); + final OutlineShape shape = TypecastRenderer.buildShape(symbol, glyph, vertexFactory); result = new TypecastGlyph(this, symbol, code, glyph.getBBox(), glyph.getAdvanceWidth(), shape); if(DEBUG) { System.err.println("New glyph: " + (int)symbol + " ( " + symbol +" ) -> " + code + ", contours " + glyph.getPointCount() + ": " + shape); @@ -222,12 +222,21 @@ class TypecastFont implements Font { } @Override + public float getLineHeight(float pixelSize) { + final Metrics metrics = getMetrics(); + final float lineGap = metrics.getLineGap(pixelSize) ; // negative value! + final float ascent = metrics.getAscent(pixelSize) ; // negative value! + final float descent = metrics.getDescent(pixelSize) ; // positive value! + final float advanceY = lineGap - descent + ascent; // negative value! + return -advanceY; + } + + @Override public float getStringWidth(CharSequence string, float pixelSize) { float width = 0; final int len = string.length(); - for (int i=0; i< len; i++) - { - char character = string.charAt(i); + for (int i=0; i< len; i++) { + final char character = string.charAt(i); if (character == '\n') { width = 0; } else { @@ -235,7 +244,6 @@ class TypecastFont implements Font { width += glyph.getAdvance(pixelSize, false); } } - return (int)(width + 0.5f); } @@ -243,12 +251,10 @@ class TypecastFont implements Font { public float getStringHeight(CharSequence string, float pixelSize) { int height = 0; - for (int i=0; i<string.length(); i++) - { - char character = string.charAt(i); - if (character != ' ') - { - Glyph glyph = getGlyph(character); + for (int i=0; i<string.length(); i++) { + final char character = string.charAt(i); + if (character != ' ') { + final Glyph glyph = getGlyph(character); AABBox bbox = glyph.getBBox(pixelSize); height = (int)Math.ceil(Math.max(bbox.getHeight(), height)); } @@ -261,11 +267,8 @@ class TypecastFont implements Font { if (string == null) { return new AABBox(); } - final Metrics metrics = getMetrics(); - final float lineGap = metrics.getLineGap(pixelSize); - final float ascent = metrics.getAscent(pixelSize); - final float descent = metrics.getDescent(pixelSize); - final float advanceY = lineGap - descent + ascent; + final float lineHeight = getLineHeight(pixelSize); + float totalHeight = 0; float totalWidth = 0; float curLineWidth = 0; @@ -274,14 +277,14 @@ class TypecastFont implements Font { if (character == '\n') { totalWidth = Math.max(curLineWidth, totalWidth); curLineWidth = 0; - totalHeight -= advanceY; + totalHeight += lineHeight; continue; } Glyph glyph = getGlyph(character); curLineWidth += glyph.getAdvance(pixelSize, true); } if (curLineWidth > 0) { - totalHeight -= advanceY; + totalHeight += lineHeight; totalWidth = Math.max(curLineWidth, totalWidth); } return new AABBox(0, 0, 0, totalWidth, totalHeight,0); diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index 7e151945c..909e90456 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -49,7 +49,6 @@ import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import com.jogamp.common.os.Platform; -import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; @@ -66,6 +65,7 @@ public class TestTextRendererNEWT00 extends UITestCase { static final boolean DEBUG = false; static final boolean TRACE = false; static long duration = 100; // ms + static boolean waitStartEnd = false; static final int[] texSize = new int[] { 0 }; static final int fontSize = 24; @@ -87,6 +87,8 @@ public class TestTextRendererNEWT00 extends UITestCase { if(args[i].equals("-time")) { i++; duration = atoi(args[i]); + } else if(args[i].equals("-wait")) { + waitStartEnd = true; } } String tstname = TestTextRendererNEWT00.class.getName(); @@ -128,9 +130,12 @@ public class TestTextRendererNEWT00 extends UITestCase { caps.setNumSamples(4); System.err.println("Requested: "+caps); - GLWindow window = createWindow("text-vbaa0-msaa1", caps, 800, 400); + GLWindow window = createWindow("text-vbaa0-msaa1", caps, 1024, 640); window.display(); System.err.println("Chosen: "+window.getChosenGLCapabilities()); + if( waitStartEnd ) { + UITestCase.waitForKey("Start"); + } final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory()); final TextRendererGLEL textGLListener = new TextRendererGLEL(rs); @@ -156,10 +161,23 @@ public class TestTextRendererNEWT00 extends UITestCase { anim.setUpdateFPSFrames(60, null); sleep(); anim.stop(); + if( waitStartEnd ) { + UITestCase.waitForKey("Stop"); + } destroyWindow(window); } int screenshot_num = 0; + static final String textX2 = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec sapien tellus. \n"+ + "Ut purus odio, rhoncus sit amet commodo eget, ullamcorper vel urna. Mauris ultricies \n"+ + "quam iaculis urna cursus ornare. Nullam ut felis a ante ultrices ultricies nec a elit. \n"+ + "In hac habitasse platea dictumst. Vivamus et mi a quam lacinia pharetra at venenatis est.\n"+ + "Morbi quis bibendum nibh. Donec lectus orci, sagittis in consequat nec, volutpat nec nisi.\n"+ + "Donec ut dolor et nulla tristique varius. In nulla magna, fermentum id tempus quis, semper \n"+ + "in lorem. Maecenas in ipsum ac justo scelerisque sollicitudin. Quisque sit amet neque lorem,\n" + + "------- End of Story ;-) ---------\n"; + private final class TextRendererGLEL extends TextRendererGLELBase { private final GLReadBufferUtil screenshot; private long t0; @@ -222,22 +240,23 @@ public class TestTextRendererNEWT00 extends UITestCase { final long t1 = Platform.currentTimeMillis(); - final String text1 = String.format("%03.3f/%03.3f s, vsync %d, elapsed %4.4f s", + final String text1 = String.format("%03.1f/%03.1f fps, vsync %d, elapsed %4.1f s", lfps, tfps, gl.getSwapInterval(), (t1-t0)/1000.0); - int row = 0; if( false ) { - renderString(drawable, "112", 0, row++, 0, 0, -1000); - // renderString(drawable, getFontInfo(), 0, row++, 0, 0, -1000); + renderString(drawable, textX2, 0, 0, 0, 0, -1000, true); + // renderString(drawable, "0", 0, 0, 0, 0, -1000); + // renderString(drawable, getFontInfo(), 0, 0, 0, -1000); } else { - renderString(drawable, getFontInfo(), 0, row++, 0, 0, -1000); - renderString(drawable, "012345678901234567890123456789", 0, row++, 0, 0, -1000); - renderString(drawable, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, row++, 0, 0, -1000); - renderString(drawable, "Hello World", 0, row++, 0, 0, -1000); - renderString(drawable, "4567890123456", 4, row++, 0, 0, -1000); - renderString(drawable, "I like JogAmp", 4, row++, 0, 0, -1000); - renderString(drawable, "Hello World", 0, row++, 0, 0, -1000); - renderString(drawable, text1, 0, row++, 0, 0, -1000); + renderString(drawable, getFontInfo(), 0, 0, 0, 0, -1000, true); + renderString(drawable, "012345678901234567890123456789", 0, 0, 0, -1000, true); + renderString(drawable, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, 0, 0, -1000, true); + renderString(drawable, "Hello World", 0, 0, 0, -1000, true); + renderString(drawable, "4567890123456", 4, 0, 0, -1000, true); + renderString(drawable, "I like JogAmp", 4, 0, 0, -1000, true); + renderString(drawable, "Hello World", 0, 0, 0, -1000, true); + renderString(drawable, textX2, 0, 0, 0, -1000, true); + renderString(drawable, text1, 0, 0, 0, -1000, false); // no-cache } } }; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java index 2a349b2de..ac59eb10b 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT10.java @@ -43,7 +43,7 @@ import org.junit.runners.MethodSorters; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.curve.opengl.TextRenderUtil; +import com.jogamp.graph.curve.opengl.TextRegionUtil; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; @@ -140,7 +140,7 @@ public class TestTextRendererNEWT10 extends UITestCase { final RenderState rs = RenderState.createRenderState(new ShaderState(), SVertex.factory()); final RegionRenderer renderer = RegionRenderer.create(rs, 0); - final TextRenderUtil textRenderUtil = new TextRenderUtil(renderer); + final TextRegionUtil textRenderUtil = new TextRegionUtil(renderer); // init gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); @@ -179,7 +179,7 @@ public class TestTextRendererNEWT10 extends UITestCase { int lastRow = -1; - void renderString(GLDrawable drawable, GL2ES2 gl, TextRenderUtil textRenderUtil, String text, int column, int row, int z0) { + void renderString(GLDrawable drawable, GL2ES2 gl, TextRegionUtil textRenderUtil, String text, int column, int row, int z0) { final int height = drawable.getHeight(); int dx = 0; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java index da1fb5515..6b955b0db 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TextRendererGLELBase.java @@ -34,13 +34,13 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLEventListener; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.curve.opengl.TextRenderUtil; +import com.jogamp.graph.curve.opengl.TextRegionUtil; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.graph.geom.SVertex; -import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; @@ -63,7 +63,7 @@ public abstract class TextRendererGLELBase implements GLEventListener { protected PMVMatrix usrPMVMatrix = null; protected RenderState rs = null; protected RegionRenderer renderer = null; - protected TextRenderUtil textRenderUtil = null; + protected TextRegionUtil textRenderUtil = null; /** font size in pixels, default is 24 */ protected int fontSize = 24; @@ -93,7 +93,7 @@ public abstract class TextRendererGLELBase implements GLEventListener { public void setFlipVerticalInGLOrientation(boolean v) { flipVerticalInGLOrientation=v; } public final RegionRenderer getRenderer() { return renderer; } - public final TextRenderUtil getTextRenderUtil() { return textRenderUtil; } + public final TextRegionUtil getTextRenderUtil() { return textRenderUtil; } @Override public void init(GLAutoDrawable drawable) { @@ -103,7 +103,7 @@ public abstract class TextRendererGLELBase implements GLEventListener { this.rs = RenderState.createRenderState(new ShaderState(), SVertex.factory(), usrPMVMatrix); } this.renderer = RegionRenderer.create(rs, usrRenderModes); - this.textRenderUtil = new TextRenderUtil(renderer); + this.textRenderUtil = new TextRegionUtil(renderer); if( 0 == usrRenderModes ) { texSizeScale = 0; } @@ -149,13 +149,12 @@ public abstract class TextRendererGLELBase implements GLEventListener { int lastRow = -1; - public void renderString(GLAutoDrawable drawable, String text, int column, float tx, float ty, float tz) { + public void renderString(GLAutoDrawable drawable, String text, int column, float tx, float ty, float tz, boolean cacheRegion) { final int row = lastRow + 1; - renderString(drawable, text, column, row, tx, ty, tz); - lastRow = row; + renderString(drawable, text, column, row, tx, ty, tz, cacheRegion); } - public void renderString(GLAutoDrawable drawable, String text, int column, int row, float tx, float ty, float tz) { + public void renderString(GLAutoDrawable drawable, String text, int column, int row, float tx, float ty, float tz, boolean cacheRegion) { if( null != renderer ) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -168,10 +167,10 @@ public abstract class TextRendererGLELBase implements GLEventListener { final int height = drawable.getHeight(); dy = height-ty; } - - final AABBox textBox = font.getStringBounds(text, fontSize); + final int newLineCount = text.length() - text.replace("\n", "").length(); + final float lineHeight = font.getLineHeight(fontSize); dx += pixelScale * font.getAdvanceWidth('X', fontSize) * column; - dy -= pixelScale * (int)textBox.getHeight() * ( row + 1 ); + dy -= pixelScale * lineHeight * ( row + 1 ); final ShaderState st = rs.getShaderState(); final PMVMatrix pmvMatrix = rs.pmvMatrix(); @@ -191,14 +190,18 @@ public abstract class TextRendererGLELBase implements GLEventListener { pmvMatrix.glScalef(pixelScale, pixelScale, 1f); } renderer.updateMatrix(gl); - textRenderUtil.drawString3D(gl, font, text, fontSize, texSize); + if( cacheRegion ) { + textRenderUtil.drawString3D(gl, font, text, fontSize, texSize); + } else { + TextRegionUtil.drawString3D(renderer, gl, font, text, fontSize, texSize); + } st.useProgram(gl, false); gl.glDisable(GL2ES2.GL_BLEND); if( !exclusivePMVMatrix ) { pmvMatrix.glPopMatrix(); } - lastRow = -1; + lastRow = row + newLineCount; } } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java index 3fbe5b816..2bd4f0019 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPUTextRendererListenerBase01.java @@ -37,7 +37,7 @@ import javax.media.opengl.GLException; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.curve.opengl.TextRenderUtil; +import com.jogamp.graph.curve.opengl.TextRegionUtil; import com.jogamp.graph.font.Font; import com.jogamp.graph.font.FontFactory; import com.jogamp.newt.event.KeyEvent; @@ -62,7 +62,7 @@ import com.jogamp.opengl.math.geom.AABBox; * - i: live input text input (CR ends it, backspace supported) */ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerBase01 { - public final TextRenderUtil textRenderUtil; + public final TextRegionUtil textRenderUtil; int fontSet = FontFactory.UBUNTU; Font font; @@ -103,7 +103,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB public GPUTextRendererListenerBase01(RenderState rs, int renderModes, boolean debug, boolean trace) { super(RegionRenderer.create(rs, renderModes), renderModes, debug, trace); - this.textRenderUtil = new TextRenderUtil(this.getRenderer()); + this.textRenderUtil = new TextRegionUtil(this.getRenderer()); try { this.font = FontFactory.get(fontSet).getDefault(); dumpFontNames(); @@ -165,7 +165,7 @@ public abstract class GPUTextRendererListenerBase01 extends GPURendererListenerB final int fpsSp = fpsS.indexOf('.'); renderer.resetModelview(null); renderer.translate(gl, fontSizeFixed, fontSizeFixed, -6000); - textRenderUtil.drawString3D(gl, font, fpsS.substring(0, fpsSp+2)+" fps", fontSizeFixed*3, getTexSize()); + TextRegionUtil.drawString3D(renderer, gl, font, fpsS.substring(0, fpsSp+2)+" fps", fontSizeFixed*3, getTexSize()); // no cache! } int dx = width-(int)fontNameBox.getWidth()-2 ; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java index 4ce732ef7..18e119441 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/Label.java @@ -31,7 +31,7 @@ import javax.media.opengl.GL2ES2; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; -import com.jogamp.graph.curve.opengl.TextRenderUtil; +import com.jogamp.graph.curve.opengl.TextRegionUtil; import com.jogamp.graph.font.Font; import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.geom.Vertex.Factory; @@ -96,8 +96,9 @@ public abstract class Label extends UIShape implements UITextShape { @Override protected void createShape(RegionRenderer renderer) { clearImpl(null, null); - glyphRegion = TextRenderUtil.createRegion(renderer.getRenderModes(), renderer.getRenderState().getVertexFactory(), - font, text, size); + glyphRegion = GLRegion.create(renderer.getRenderModes()); + TextRegionUtil.addStringToRegion(glyphRegion, renderer.getRenderState().getVertexFactory(), + font, text, size); } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java index 43f8b89bd..910c62eae 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/GLReadBuffer00Base.java @@ -72,7 +72,7 @@ public abstract class GLReadBuffer00Base extends UITestCase { final String text = String.format("Frame %04d (%03d): %04dx%04d", frameNo, userCounter, drawable.getWidth(), drawable.getHeight()); System.err.println("TextRendererGLEL.display: "+text); if( null != renderer ) { - renderString(drawable, text, 0 /* col */, 0 /* row */, 0, 0, -1); + renderString(drawable, text, 0 /* col */, 0 /* row */, 0, 0, -1, false); } else { System.err.println(text); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java index b148ebabd..61c4244fb 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieCube.java @@ -215,9 +215,7 @@ public class MovieCube implements GLEventListener { "; underlineSize "+underlineSize+" "+(pixelScale*underlineSize)+ "; yoff "+yoff1+", yoff2 "+yoff2); */ - // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions! - // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", - final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); @@ -227,10 +225,10 @@ public class MovieCube implements GLEventListener { mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec()); final String text4 = mPlayer.getURI().getRawPath(); if( displayOSD && null != renderer ) { - renderString(drawable, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff); - renderString(drawable, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff); - renderString(drawable, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff); - renderString(drawable, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff); + renderString(drawable, text1, 1 /* col */, -1 /* row */, -1+z_diff, yoff1, 1f+z_diff, false); + renderString(drawable, text2, 1 /* col */, 0 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); + renderString(drawable, text3, 1 /* col */, 1 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); + renderString(drawable, text4, 1 /* col */, 2 /* row */, -1+z_diff, yoff2, 1f+z_diff, true); } } }; private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index 787dbab78..22fa63b37 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -158,9 +158,7 @@ public class MovieSimple implements GLEventListener { final float aspect = (float)mPlayer.getWidth() / (float)mPlayer.getHeight(); - // FIXME: Graph TextRenderer does not scale well, i.e. text update per 1/10s cause too much recompute of regions! - // final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", - final String text1 = String.format("%03.0f/%03.0f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", + final String text1 = String.format("%03.1f/%03.1f s, %s (%01.2fx, vol %01.2f), a %01.2f, fps %02.1f -> %02.1f / %02.1f, v-sync %d", pts, mPlayer.getDuration() / 1000f, mPlayer.getState().toString().toLowerCase(), mPlayer.getPlaySpeed(), mPlayer.getAudioVolume(), aspect, mPlayer.getFramerate(), lfps, tfps, swapIntervalSet); @@ -170,10 +168,10 @@ public class MovieSimple implements GLEventListener { mPlayer.getVID(), mPlayer.getVideoBitrate()/1000, mPlayer.getVideoCodec()); final String text4 = mPlayer.getURI().getRawPath(); if( displayOSD && null != renderer ) { - renderString(drawable, text1, 1 /* col */, 1 /* row */, 0, 0, -1); - renderString(drawable, text2, 1 /* col */, -4 /* row */, 0, height, -1); - renderString(drawable, text3, 1 /* col */, -3 /* row */, 0, height, -1); - renderString(drawable, text4, 1 /* col */, -2 /* row */, 0, height, -1); + renderString(drawable, text1, 1 /* col */, 1 /* row */, 0, 0, -1, false); + renderString(drawable, text2, 1 /* col */, -4 /* row */, 0, height, -1, true); + renderString(drawable, text3, 1 /* col */, -3 /* row */, 0, height, -1, true); + renderString(drawable, text4, 1 /* col */, -2 /* row */, 0, height, -1, true); } } }; private final InfoTextRendererGLELBase textRendererGLEL = new InfoTextRendererGLELBase(); |