JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
TestTextRendererNEWT01.java
Go to the documentation of this file.
1/**
2 * Copyright 2011-2024 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.opengl.test.junit.graph;
29
30import java.io.File;
31import java.io.IOException;
32import java.util.Locale;
33
34import com.jogamp.opengl.GL;
35import com.jogamp.opengl.GL2ES2;
36import com.jogamp.opengl.GLCapabilities;
37import com.jogamp.opengl.GLDrawable;
38import com.jogamp.opengl.GLException;
39import com.jogamp.opengl.GLProfile;
40
41import org.junit.Assert;
42import org.junit.BeforeClass;
43import org.junit.Test;
44import org.junit.FixMethodOrder;
45import org.junit.runners.MethodSorters;
46
47import com.jogamp.common.util.IOUtil;
48import com.jogamp.graph.curve.Region;
49import com.jogamp.graph.curve.opengl.RenderState;
50import com.jogamp.graph.curve.opengl.RegionRenderer;
51import com.jogamp.graph.curve.opengl.TextRegionUtil;
52import com.jogamp.graph.font.Font;
53import com.jogamp.graph.font.FontFactory;
54import com.jogamp.graph.font.FontScale;
55import com.jogamp.graph.font.FontSet;
56import com.jogamp.math.geom.AABBox;
57import com.jogamp.math.util.PMVMatrix4f;
58import com.jogamp.opengl.test.junit.util.MiscUtils;
59import com.jogamp.opengl.test.junit.util.NEWTGLContext;
60import com.jogamp.opengl.test.junit.util.UITestCase;
61import com.jogamp.opengl.util.GLReadBufferUtil;
62
63
64/**
65 * TestTextRendererNEWT01 Variant
66 * - No listener, all straight forward
67 * - Type Rendering via TextRegionUtil, multiple
68 */
69@FixMethodOrder(MethodSorters.NAME_ASCENDING)
70public class TestTextRendererNEWT01 extends UITestCase {
71 static final boolean DEBUG = false;
72 static final boolean TRACE = false;
73 static long duration = 100; // ms
74 static boolean forceES2 = false;
75 static boolean forceGL3 = false;
76 static boolean mainRun = false;
77 static boolean useMSAA = true;
78 static int win_width = 1024;
79 static int win_height = 640;
80
81 static Font font;
82 static float fontSize = 24; // in pixel
83 static String customStr = null;
84
85 @BeforeClass
86 public static void setup() throws IOException {
87 if( null == font ) {
89 }
90 }
91
92 static int atoi(final String a) {
93 try {
94 return Integer.parseInt(a);
95 } catch (final Exception ex) { throw new RuntimeException(ex); }
96 }
97
98 public static void main(final String args[]) throws IOException {
99 mainRun = true;
100 for(int i=0; i<args.length; i++) {
101 if(args[i].equals("-time")) {
102 i++;
103 duration = atoi(args[i]);
104 } else if(args[i].equals("-width")) {
105 i++;
106 win_width = atoi(args[i]);
107 } else if(args[i].equals("-height")) {
108 i++;
109 win_height = atoi(args[i]);
110 } else if(args[i].equals("-noMSAA")) {
111 useMSAA = false;
112 } else if(args[i].equals("-es2")) {
113 forceES2 = true;
114 } else if(args[i].equals("-gl3")) {
115 forceGL3 = true;
116 } else if(args[i].equals("-font")) {
117 i++;
118 font = FontFactory.get(IOUtil.getResource(args[i], TestTextRendererNEWT01.class.getClassLoader(), TestTextRendererNEWT01.class).getInputStream(), true);
119 } else if(args[i].equals("-fontSize")) {
120 i++;
121 fontSize = MiscUtils.atof(args[i], fontSize);
122 } else if(args[i].equals("-text")) {
123 i++;
124 customStr = args[i];
125 }
126 }
127 final String tstname = TestTextRendererNEWT01.class.getName();
128 org.junit.runner.JUnitCore.main(tstname);
129 }
130
131 static void sleep() {
132 try {
133 System.err.println("** new frame ** (sleep: "+duration+"ms)");
134 Thread.sleep(duration);
135 } catch (final InterruptedException ie) {}
136 }
137
138 @Test
139 public void test00TextRendererNONE00() throws InterruptedException, GLException, IOException {
140 testTextRendererImpl(0, 0);
141 }
142
143 @Test
144 public void test01TextRendererMSAA04() throws InterruptedException, GLException, IOException {
145 testTextRendererImpl(0, 4);
146 }
147
148 @Test
149 public void test02TextRendererVBAA04() throws InterruptedException, GLException, IOException {
150 testTextRendererImpl(Region.VBAA_RENDERING_BIT, 4);
151 }
152
153 void testTextRendererImpl(final int renderModes, final int sampleCount) throws InterruptedException, GLException, IOException {
154 final GLProfile glp;
155 if(forceGL3) {
156 glp = GLProfile.get(GLProfile.GL3);
157 } else if(forceES2) {
159 } else {
160 glp = GLProfile.getGL2ES2();
161 }
162
163 final GLCapabilities caps = new GLCapabilities( glp );
164 caps.setAlphaBits(4);
165 if( 0 < sampleCount && !Region.isVBAA(renderModes) ) {
166 caps.setSampleBuffers(true);
167 caps.setNumSamples(sampleCount);
168 }
169 System.err.println("Requested: "+caps);
170 System.err.println("Requested: "+Region.getRenderModeString(renderModes));
171
172 final NEWTGLContext.WindowContext winctx = NEWTGLContext.createWindow(caps, win_width, win_height, true);
173 final GLDrawable drawable = winctx.context.getGLDrawable();
174 final GL2ES2 gl = winctx.context.getGL().getGL2ES2();
175
176 Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError());
177
178 System.err.println("Chosen: "+winctx.window.getChosenCapabilities());
179
180 final RegionRenderer renderer = RegionRenderer.create(RegionRenderer.defaultBlendEnable, RegionRenderer.defaultBlendDisable);
181 renderer.setHintBits(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED);
182 final TextRegionUtil textRenderUtil = new TextRegionUtil(renderModes);
183
184 // init
185 gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
186 renderer.init(gl);
187 renderer.setColorStatic(0.1f, 0.1f, 0.1f, 1.0f);
188 screenshot = new GLReadBufferUtil(false, false);
189
190 // reshape
191 gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight());
192
193 // renderer.reshapePerspective(gl, 45.0f, drawable.getWidth(), drawable.getHeight(), 0.1f, 1000.0f);
194 renderer.reshapeOrtho(drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0.1f, 1000.0f);
195 final int z0 = -1000;
196
197 final int[] sampleCountIO = { sampleCount };
198 // display
199 gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
200 if( null == customStr ) {
201 {
202 final float[] pixelsPerMM = winctx.window.getPixelsPerMM(new float[2]);
203 final float[] dpi = FontScale.ppmmToPPI(pixelsPerMM, new float[2]);
204 final float mmSize = fontSize / pixelsPerMM[1];
205 final int unitsPerEM = font.getMetrics().getUnitsPerEM();
206 String txt = String.format("Resolution dpiV %.2f, %.2f px/mm", dpi[1], pixelsPerMM[1]);
207 renderString(drawable, gl, renderer, textRenderUtil, txt, 0, 0, z0, sampleCountIO);
208 txt = String.format("Font %s, unitsPerEM %d, size %.2f px %2f mm", font.getFullFamilyName(), unitsPerEM, fontSize, mmSize);
209 renderString(drawable, gl, renderer, textRenderUtil, txt, 0, -1, z0, sampleCountIO);
210 }
211 renderString(drawable, gl, renderer, textRenderUtil, "012345678901234567890123456789", 0, -1, z0, sampleCountIO);
212 renderString(drawable, gl, renderer, textRenderUtil, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 0, -1, z0, sampleCountIO);
213 renderString(drawable, gl, renderer, textRenderUtil, "Hello World", 0, -1, z0, sampleCountIO);
214 renderString(drawable, gl, renderer, textRenderUtil, "4567890123456", 4, -1, z0,sampleCountIO);
215 renderString(drawable, gl, renderer, textRenderUtil, "I like JogAmp", 4, -1, z0, sampleCountIO);
216
217 int c = 0;
218 renderString(drawable, gl, renderer, textRenderUtil, "GlueGen", c++, -1, z0, sampleCountIO);
219 renderString(drawable, gl, renderer, textRenderUtil, "JOAL", c++, -1, z0, sampleCountIO);
220 renderString(drawable, gl, renderer, textRenderUtil, "JOGL", c++, -1, z0, sampleCountIO);
221 renderString(drawable, gl, renderer, textRenderUtil, "JOCL", c++, -1, z0, sampleCountIO);
222 } else {
223 renderString(drawable, gl, renderer, textRenderUtil, customStr, 0, 0, z0, sampleCountIO);
224 }
225 gl.glFinish();
226 printScreen(renderModes, drawable, gl, false, sampleCount);
227 drawable.swapBuffers();
228
229 sleep();
230
231 // dispose
232 screenshot.dispose(gl);
233 renderer.destroy(gl);
234
235 NEWTGLContext.destroyWindow(winctx);
236 }
237
238 private GLReadBufferUtil screenshot;
239 int lastRow = -1;
240
241 void renderString(final GLDrawable drawable, final GL2ES2 gl, final RegionRenderer renderer, final TextRegionUtil textRenderUtil, final String text,
242 final int column, int row, final int z0, final int[] sampleCount)
243 {
244 final int height = drawable.getSurfaceHeight();
245
246 float dx = 0;
247 float dy = height;
248 if(0>row) {
249 row = lastRow + 1;
250 }
251 final AABBox textBox = font.getMetricBounds(text); // em-size
252 dx += fontSize * font.getAdvanceWidth( font.getGlyphID( 'X' ) ) * column;
253 dy -= fontSize * textBox.getHeight() * ( row + 1 );
254
255 final PMVMatrix4f pmv = renderer.getMatrix();
256 pmv.loadMvIdentity();
257 pmv.translateMv(dx, dy, z0);
258 pmv.scaleMv(fontSize, fontSize, 1.0f);
259 textRenderUtil.drawString3D(gl, renderer, font, text, null);
260
261 lastRow = row;
262 }
263
264 private int screenshot_num = 0;
265
266 public void printScreen(final int renderModes, final GLDrawable drawable, final GL gl, final boolean exportAlpha, final int sampleCount) throws GLException, IOException {
267 final String dir = "./";
268 final String objName = getSimpleTestName(".")+"-snap"+screenshot_num;
269 screenshot_num++;
270 final String modeS = Region.getRenderModeString(renderModes);
271 final String bname = String.format((Locale)null, "%s-msaa%02d-fontsz%02.1f-%03dx%03d-%s%04d", objName,
272 drawable.getChosenGLCapabilities().getNumSamples(),
273 fontSize, drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), modeS, sampleCount);
274 final String filename = dir + bname +".png";
275 if(screenshot.readPixels(gl, false)) {
276 screenshot.write(new File(filename));
277 }
278 }
279
280}
Abstract Outline shape representation define the method an OutlineShape(s) is bound and rendered.
Definition: Region.java:62
static String getRenderModeString(final int renderModes)
Returns a unique technical description string for renderModes as follows:
Definition: Region.java:251
static final int VBAA_RENDERING_BIT
Rendering-Mode bit for Region.
Definition: Region.java:115
The optional property jogamp.graph.font.ctor allows user to specify the FontConstructor implementatio...
static final FontSet get(final int font)
static final int UBUNTU
Ubuntu is the default font family, {@value}.
void setAlphaBits(final int alphaBits)
Sets the number of bits requested for the color buffer's alpha component.
Specifies a set of OpenGL capabilities.
void setNumSamples(final int numSamples)
If sample buffers are enabled, indicates the number of buffers to be allocated.
void setSampleBuffers(final boolean enable)
Defaults to false.
A generic exception for OpenGL errors used throughout the binding as a substitute for RuntimeExceptio...
Specifies the the OpenGL profile.
Definition: GLProfile.java:77
static final String GL3
The desktop OpenGL core profile 3.x, with x >= 1.
Definition: GLProfile.java:576
static final String GLES2
The embedded OpenGL profile ES 2.x, with x >= 0.
Definition: GLProfile.java:585
static GLProfile get(final AbstractGraphicsDevice device, String profile)
Returns a GLProfile object.
static GLProfile getGL2ES2(final AbstractGraphicsDevice device)
Returns the GL2ES2 profile implementation, hence compatible w/ GL2ES2.
Definition: GLProfile.java:913
void printScreen(final int renderModes, final GLDrawable drawable, final GL gl, final boolean exportAlpha, final int sampleCount)
static float atof(final String str, final float def)
Definition: MiscUtils.java:75
static final int FAMILY_LIGHT
Font family LIGHT, {@value}.
Definition: FontSet.java:39
Font get(int family, int stylebits)
static final int STYLE_NONE
Zero style, {@value}.
Definition: FontSet.java:51
int getUnitsPerEM()
Returns the font's units per EM from the 'head' table.
Interface wrapper for font implementation.
Definition: Font.java:60
AABBox getMetricBounds(final CharSequence string)
Returns metric-bounds in font em-size.
String getFullFamilyName()
Shall return the family and subfamily name, separated a dash.
int getGlyphID(final char codepoint)
Returns the Glyph ID mapped to given UTF16 (unicode) codepoint symbol.
float getAdvanceWidth(final int glyphID)
Returns advance-width of given glyphID in font em-size [0..1], sourced from hmtx table - same as Glyp...
An abstraction for an OpenGL rendering target.
Definition: GLDrawable.java:51