/**
* Copyright 2012 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package com.jogamp.opengl.test.junit.graph;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLAnimatorControl;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.GLRunnable;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.jogamp.common.os.Platform;
import com.jogamp.graph.curve.Region;
import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.curve.opengl.RenderState;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontFactory;
import com.jogamp.graph.geom.SVertex;
import com.jogamp.junit.util.JunitTracer;
import com.jogamp.newt.Window;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestTextRendererNEWT00 extends UITestCase {
static final boolean DEBUG = false;
static final boolean TRACE = false;
static long Duration = 2000; // ms
static boolean WaitStartEnd = false;
static boolean TextAnim = false;
static int SceneMSAASamples = 0;
static int GraphVBAASamples = 0;
static int GraphMSAASamples = 0;
static boolean ManualTest = false;
static int SwapInterval = 1;
static String fontFileName = null;
static URL fontURL = null;
static int fontSet = 0;
static int fontFamily = 0;
static int fontStylebits = 0;
static float fontSizeFixed = 14f;
static int atoi(final String a) {
try {
return Integer.parseInt(a);
} catch (final Exception ex) { throw new RuntimeException(ex); }
}
public static void main(final String args[]) throws IOException {
ManualTest = args.length > 0;
for(int i=0; i<args.length; i++) {
if(args[i].equals("-time")) {
i++;
Duration = atoi(args[i]);
} else if(args[i].equals("-fontURL")) {
i++;
fontURL = new URL(args[i]);
} else if(args[i].equals("-fontFile")) {
i++;
fontFileName = args[i];
} else if(args[i].equals("-fontSet")) {
i++;
fontSet = atoi(args[i]);
} else if(args[i].equals("-fontFamily")) {
i++;
fontFamily = atoi(args[i]);
} else if(args[i].equals("-fontStyle")) {
i++;
fontStylebits = atoi(args[i]);
} else if(args[i].equals("-fontSize")) {
i++;
fontSizeFixed = atoi(args[i]);
} else if(args[i].equals("-smsaa")) {
i++;
SceneMSAASamples = atoi(args[i]);
} else if(args[i].equals("-gmsaa")) {
i++;
GraphMSAASamples = atoi(args[i]);
} else if(args[i].equals("-gvbaa")) {
i++;
GraphVBAASamples = atoi(args[i]);
} else if(args[i].equals("-textAnim")) {
TextAnim = true;
} else if(args[i].equals("-vsync")) {
i++;
SwapInterval = MiscUtils.atoi(args[i], SwapInterval);
} else if(args[i].equals("-wait")) {
WaitStartEnd = true;
}
}
System.err.println("Font [set "+fontSet+", family "+fontFamily+", style "+fontStylebits+", size "+fontSizeFixed+"], fontFileName "+fontFileName);
System.err.println("Scene MSAA Samples "+SceneMSAASamples);
System.err.println("Graph MSAA Samples "+GraphMSAASamples);
System.err.println("Graph VBAA Samples "+GraphVBAASamples);
System.err.println("swapInterval "+SwapInterval);
final String tstname = TestTextRendererNEWT00.class.getName();
org.junit.runner.JUnitCore.main(tstname);
}
static void sleep() {
sleep(Duration);
}
static void sleep(final long d) {
try {
System.err.println("** new frame ** (sleep: "+d+"ms)");
Thread.sleep(d);
} catch (final InterruptedException ie) {}
}
static void destroyWindow(final GLWindow window) {
if(null!=window) {
window.destroy();
}
}
static GLWindow createWindow(final String title, final GLCapabilitiesImmutable caps, final int width, final int height) {
Assert.assertNotNull(caps);
final GLWindow window = GLWindow.create(caps);
window.setSize(width, height);
window.setPosition(10, 10);
window.setTitle(title);
Assert.assertNotNull(window);
window.setVisible(true);
return window;
}
@Test
public void test00Manual() throws InterruptedException {
if( ManualTest ) {
testImpl(SceneMSAASamples, GraphMSAASamples, GraphVBAASamples);
}
}
@Test
public void test00SceneNoAA() throws InterruptedException {
if( !ManualTest ) {
testImpl(0, 0, 0);
}
}
@Test
public void test01SceneMSAA04() throws InterruptedException {
if( !ManualTest ) {
testImpl(4, 0, 0);
}
}
@Test
public void test02GraphMSAA04() throws InterruptedException {
if( !ManualTest ) {
testImpl(0, 4, 0);
}
}
@Test
public void test03GraphVBAA04() throws InterruptedException {
if( !ManualTest ) {
testImpl(0, 0, 4);
}
}
public void testImpl(final int sceneMSAASamples, final int graphMSAASamples, final int graphVBAASamples) throws InterruptedException {
final GLProfile glp = GLProfile.get(GLProfile.GL2ES2);
final GLCapabilities caps = new GLCapabilities(glp);
caps.setAlphaBits(4);
if( 0 < sceneMSAASamples ) {
caps.setSampleBuffers(true);
caps.setNumSamples(sceneMSAASamples);
}
System.err.println("Requested: "+caps+", graph[msaaSamples "+graphMSAASamples+", vbaaSamples "+graphVBAASamples+"]");
final GLWindow window = createWindow("text-gvbaa"+graphVBAASamples+"-gmsaa"+graphMSAASamples+"-smsaa"+sceneMSAASamples, caps, 1024, 640);
window.display();
System.err.println("Chosen: "+window.getChosenGLCapabilities());
if( WaitStartEnd ) {
JunitTracer.waitForKey("Start");
}
final RenderState rs = RenderState.createRenderState(SVertex.factory());
final int renderModes, sampleCount;
if( graphVBAASamples > 0 ) {
renderModes = Region.VBAA_RENDERING_BIT;
sampleCount = graphVBAASamples;
} else if ( graphMSAASamples > 0 ) {
renderModes = Region.MSAA_RENDERING_BIT;
sampleCount = graphMSAASamples;
} else {
renderModes = 0;
sampleCount = 0;
}
final TextRendererGLEL textGLListener = new TextRendererGLEL(rs, renderModes, sampleCount);
System.err.println(textGLListener.getFontInfo());
window.addGLEventListener(textGLListener);
final Animator anim = new Animator();
anim.add(window);
anim.start();
anim.setUpdateFPSFrames(60, null);
sleep();
window.invoke(true, new GLRunnable() {
@Override
public boolean run(final GLAutoDrawable drawable) {
try {
textGLListener.printScreen(renderModes, drawable, "./", "TestTextRendererNEWT00-snap"+screenshot_num, false);
screenshot_num++;
} catch (final Exception e) {
e.printStackTrace();
}
return true;
}
});
anim.stop();
if( WaitStartEnd ) {
JunitTracer.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" +
"-------Press H to change text---------\n";
private static final class TextRendererGLEL extends TextRendererGLELBase {
private final GLReadBufferUtil screenshot;
private final GLRegion regionFPS, regionFPSAnim;
final Font font;
final float fontSizeMin, fontSizeMax;
private long t0;
float fontSizeAnim, fontSizeDelta;
float dpiH;
TextRendererGLEL(final RenderState rs, final int renderModes, final int sampleCount) {
super(renderModes, new int[] { sampleCount });
setRendererCallbacks(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
setRenderState(rs);
regionFPS = GLRegion.create(renderModes, null);
regionFPSAnim = GLRegion.create(renderModes, null);
if( null != fontURL ) {
Font _font = null;
try {
_font = FontFactory.get(fontURL.openStream(), true);
} catch (final IOException e) {
e.printStackTrace();
}
font = _font;
} else if( null != fontFileName ) {
Font _font = null;
try {
_font = FontFactory.get(getClass(), fontFileName, false);
} catch (final IOException e) {
e.printStackTrace();
}
font = _font;
} else {
font = getFont(fontSet, fontFamily, fontStylebits);
}
staticRGBAColor[0] = 0.1f;
staticRGBAColor[1] = 0.1f;
staticRGBAColor[2] = 0.1f;
staticRGBAColor[3] = 1.0f;
this.screenshot = new GLReadBufferUtil(false, false);
// fontSizeMin = Math.max(8, fontSizeFixed-5);
fontSizeMin = fontSizeFixed;
fontSizeMax = fontSizeFixed+8;
fontSizeAnim = fontSizeFixed;
fontSizeDelta = 0.01f;
}
@Override
public void init(final GLAutoDrawable drawable) {
super.init(drawable);
drawable.getGL().setSwapInterval(SwapInterval);
t0 = Platform.currentTimeMillis();
final Window win = (Window)drawable.getUpstreamWidget();
final float[] pixelsPerMM = win.getPixelsPerMM(new float[2]);
final float[] dotsPerInch = new float[] { pixelsPerMM[0]*25.4f, pixelsPerMM[1]*25.4f };
dpiH = dotsPerInch[1];
System.err.println(getFontInfo());
System.err.println("fontSize "+fontSizeFixed+", dotsPerMM "+pixelsPerMM[0]+"x"+pixelsPerMM[1]+", dpi "+dotsPerInch[0]+"x"+dotsPerInch[1]+", pixelSize "+font.getPixelSize(fontSizeFixed, dotsPerInch[1] /* dpi display */));
}
@Override
public void dispose(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
screenshot.dispose(gl);
regionFPS.destroy(gl);
regionFPSAnim.destroy(gl);
super.dispose(drawable);
}
public void printScreen(final int renderModes, final GLAutoDrawable drawable, final String dir, final String objName, final boolean exportAlpha) throws GLException, IOException {
final String modeS = Region.getRenderModeString(renderModes);
final String bname = String.format("%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName,
drawable.getChosenGLCapabilities().getNumSamples(),
TestTextRendererNEWT00.fontSizeFixed, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, vbaaSampleCount[0]);
final String filename = dir + bname +".png";
if(screenshot.readPixels(drawable.getGL(), false)) {
screenshot.write(new File(filename));
}
}
String getFontInfo() {
final float unitsPerEM_Inv = font.getMetrics().getScale(1f);
final float unitsPerEM = 1f / unitsPerEM_Inv;
return String.format("Font %s%n %s%nunitsPerEM %f (upem)",
font.getFullFamilyName(null).toString(),
font.getName(Font.NAME_UNIQUNAME),
unitsPerEM);
}
@Override
public void display(final GLAutoDrawable drawable) {
final GL2ES2 gl = drawable.getGL().getGL2ES2();
gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
final GLAnimatorControl anim = drawable.getAnimator();
final float lfps = null != anim ? anim.getLastFPS() : 0f;
final float tfps = null != anim ? anim.getTotalFPS() : 0f;
// Note: MODELVIEW is from [ 0 .. height ]
final long t1 = Platform.currentTimeMillis();
// final float fontSize = TestTextRendererNEWT00.fontSize;
fontSizeAnim += fontSizeDelta;
if( fontSizeMin >= fontSizeAnim || fontSizeAnim >= fontSizeMax ) {
fontSizeDelta *= -1f;
}
final float pixelSize = font.getPixelSize(fontSizeFixed, dpiH);
final float pixelSizeAnim = font.getPixelSize(fontSizeAnim, dpiH);
final String modeS = Region.getRenderModeString(renderModes);
if( false ) {
// renderString(drawable, font, pixelSize, "I - / H P 7 0", 0, 0, 0, 0, -1000f, true);
// renderString(drawable, font, pixelSize, "A M > } ] ", 0, 0, 0, 0, -1000f, true);
// renderString(drawable, font, pixelSize, "M", 0, 0, 0, 0, -1000f, true);
// renderString(drawable, font, pixelSize, "0 6 9 a b O Q A M > } ] ", 0, 0, 0, 0, -1000f, true);
// renderString(drawable, font, pixelSize, "012345678901234567890123456789", 0, 0, 0, -1000, true);
// renderString(drawable, font, pixelSize, textX2, 0, 0, 0, 0, -1000f, true);
// renderString(drawable, font, pixelSize, text1, 0, 0, 0, -1000f, regionFPS); // no-cache
final String text1 = lfps+" / "+tfps+" fps, vsync "+gl.getSwapInterval()+", elapsed "+(t1-t0)/1000.0+
" s, fontSize "+fontSizeFixed+", msaa "+drawable.getChosenGLCapabilities().getNumSamples()+
", "+modeS+"-samples "+vbaaSampleCount[0];
renderString(drawable, font, pixelSize, text1, 0, 0, 0, 0, -1000, regionFPS); // no-cache
} else {
final String text1 = String.format("%03.1f/%03.1f fps, vsync %d, elapsed %4.1f s, fontSize %2.2f, msaa %d, %s-samples %d",
lfps, tfps, gl.getSwapInterval(), (t1-t0)/1000.0, fontSizeFixed,
drawable.getChosenGLCapabilities().getNumSamples(), modeS, vbaaSampleCount[0]);
renderString(drawable, font, pixelSize, getFontInfo(), 0, 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "012345678901234567890123456789", 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "Hello World", 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "4567890123456", 4, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "I like JogAmp", 4, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, "Hello World", 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, textX2, 0, 0, 0, -1000, true);
renderString(drawable, font, pixelSize, text1, 0, 0, 0, -1000, regionFPS); // no-cache
if( TextAnim ) {
renderString(drawable, font, pixelSizeAnim, text1, 0, 0, 0, -1000, regionFPSAnim); // no-cache
}
}
} };
}