summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/resources/assets-test/crosshair-lumina-trans-64x64.pngbin0 -> 424 bytes
-rw-r--r--make/resources/assets/newt/data/crosshair-lumina-trans-32x32.pngbin0 -> 213 bytes
-rw-r--r--make/scripts/tests.sh9
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java100
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java335
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java63
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java319
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java17
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java10
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java196
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java374
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java193
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java48
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java119
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java4
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java156
-rw-r--r--src/newt/classes/jogamp/newt/PointerIconImpl.java63
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java8
-rw-r--r--src/newt/classes/jogamp/newt/driver/PNGIcon.java35
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java58
-rw-r--r--src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java92
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java50
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java38
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java20
-rw-r--r--src/newt/native/MacWindow.m32
-rw-r--r--src/newt/native/WindowsWindow.c16
-rw-r--r--src/newt/native/X11Display.c15
-rw-r--r--src/newt/native/X11Window.c20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java59
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java54
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java92
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java224
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java (renamed from src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java)100
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java364
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java105
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.pngbin0 -> 213 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.pngbin0 -> 424 bytes
-rw-r--r--src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java62
38 files changed, 2660 insertions, 790 deletions
diff --git a/make/resources/assets-test/crosshair-lumina-trans-64x64.png b/make/resources/assets-test/crosshair-lumina-trans-64x64.png
new file mode 100644
index 000000000..9be285335
--- /dev/null
+++ b/make/resources/assets-test/crosshair-lumina-trans-64x64.png
Binary files differ
diff --git a/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png b/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png
new file mode 100644
index 000000000..92279640b
--- /dev/null
+++ b/make/resources/assets/newt/data/crosshair-lumina-trans-32x32.png
Binary files differ
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index db852ce42..55973eb12 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -229,7 +229,7 @@ function jrun() {
#D_ARGS="-Djogl.debug.GLContext -Dnewt.debug=all"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer -Djogl.debug.TileRenderer.PNG"
#D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GLJPanel -Djogl.debug.TileRenderer"
- #D_ARGS="-Djogl.debug.PNGImage"
+ #D_ARGS="-Djogl.debug.PNG -Dnewt.debug.Display.PointerIcon"
#D_ARGS="-Djogl.debug.JPEGImage"
#D_ARGS="-Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser"
#X_ARGS="-Dsun.java2d.noddraw=True -Dsun.java2d.opengl=True -Dsun.java2d.xrender=false"
@@ -634,9 +634,10 @@ testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasA
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTCompareNewtAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGJoglAWTBenchmarkNewtAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestJPEGTextureFromFileNEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage00NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGImage01NEWT $*
-#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.ToolPNG2CSource $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect00NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGPixelRect01NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil00NEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPixelFormatUtil01NEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileAWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.util.texture.TestPNGTextureFromFileNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.util.texture.TestGLReadBufferUtilTextureIOWrite01AWT $*
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
index 50124c349..a921a2818 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/GLPixelBuffer.java
@@ -30,11 +30,15 @@ package com.jogamp.opengl.util;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
+import javax.media.opengl.GL2;
import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2ES3;
+import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
+import javax.media.opengl.GLProfile;
import com.jogamp.common.nio.Buffers;
import com.jogamp.opengl.util.texture.TextureData;
@@ -202,6 +206,56 @@ public class GLPixelBuffer {
public GLPixelAttributes(int componentCount, int dataFormat, int dataType) {
this(componentCount, dataFormat, dataType, true);
}
+
+ /**
+ * Returns the matching {@link GLPixelAttributes} for the given {@link PixelFormat} and {@link GLProfile} if exists,
+ * otherwise returns <code>null</code>.
+ */
+ public static final GLPixelAttributes convert(PixelFormat pixFmt, GLProfile glp) {
+ int df = 0; // format
+ int dt = GL.GL_UNSIGNED_BYTE; // data type
+ switch(pixFmt) {
+ case LUMINANCE:
+ if( glp.isGL3ES3() ) {
+ // RED is supported on ES3 and >= GL3 [core]; ALPHA/LUMINANCE is deprecated on core
+ df = GL2ES2.GL_RED;
+ } else {
+ // ALPHA/LUMINANCE is supported on ES2 and GL2, i.e. <= GL3 [core] or compatibility
+ df = GL2ES2.GL_LUMINANCE;
+ }
+ break;
+ case BGR888:
+ if( glp.isGL2GL3() ) {
+ df = GL2GL3.GL_BGR;
+ }
+ break;
+ case RGB888:
+ df = GL.GL_RGB;
+ break;
+ case RGBA8888:
+ df = GL.GL_RGBA;
+ break;
+ case ABGR8888:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_RGBA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
+ }
+ break;
+ case BGRA8888:
+ df = GL.GL_BGRA;
+ break;
+ case ARGB8888:
+ if( glp.isGL2GL3() ) {
+ df = GL.GL_BGRA; dt = GL2GL3.GL_UNSIGNED_INT_8_8_8_8;
+ }
+ break;
+ default:
+ break;
+ }
+ if( 0 != df ) {
+ return new GLPixelAttributes(pixFmt.componentCount, df, dt, true);
+ }
+ return null;
+ }
private GLPixelAttributes(int componentCount, int dataFormat, int dataType, boolean checkArgs) {
this.componentCount = componentCount;
this.format = dataFormat;
@@ -216,6 +270,52 @@ public class GLPixelBuffer {
}
}
}
+
+ /**
+ * Returns the matching {@link PixelFormat} of this {@link GLPixelAttributes} if exists,
+ * otherwise returns <code>null</code>.
+ */
+ public final PixelFormat getPixelFormat() {
+ final PixelFormat pixFmt;
+ // FIXME: Take 'type' into consideration and complete mapping!
+ switch(format) {
+ case GL.GL_ALPHA:
+ case GL.GL_LUMINANCE:
+ case GL2ES2.GL_RED:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case GL.GL_RGB:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ case GL.GL_RGBA:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ case GL2.GL_BGR:
+ pixFmt = PixelFormat.BGR888;
+ break;
+ case GL.GL_BGRA:
+ pixFmt = PixelFormat.BGRA8888;
+ break;
+ default:
+ switch( bytesPerPixel ) {
+ case 1:
+ pixFmt = PixelFormat.LUMINANCE;
+ break;
+ case 3:
+ pixFmt = PixelFormat.RGB888;
+ break;
+ case 4:
+ pixFmt = PixelFormat.RGBA8888;
+ break;
+ default:
+ pixFmt = null;
+ break;
+ }
+ break;
+ }
+ return pixFmt;
+ }
+
@Override
public String toString() {
return "PixelAttributes[comp "+componentCount+", fmt 0x"+Integer.toHexString(format)+", type 0x"+Integer.toHexString(type)+", bytesPerPixel "+bytesPerPixel+"]";
diff --git a/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
new file mode 100644
index 000000000..1bbc12f32
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/PNGPixelRect.java
@@ -0,0 +1,335 @@
+/**
+ * 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.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormatUtil;
+
+import jogamp.opengl.Debug;
+import jogamp.opengl.util.pngj.ImageInfo;
+import jogamp.opengl.util.pngj.ImageLine;
+import jogamp.opengl.util.pngj.ImageLineHelper;
+import jogamp.opengl.util.pngj.PngReader;
+import jogamp.opengl.util.pngj.PngWriter;
+import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
+import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
+import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.common.util.IOUtil;
+
+public class PNGPixelRect extends PixelRectangle.GenericPixelRect {
+ private static final boolean DEBUG = Debug.debug("PNG");
+
+ /**
+ * Reads a PNG image from the specified InputStream.
+ * <p>
+ * Implicitly converts the image to match the desired:
+ * <ul>
+ * <li>{@link PixelFormat}, see {@link #getPixelformat()}</li>
+ * <li><code>destStrideInBytes</code>, see {@link #getStride()}</li>
+ * <li><code>destIsGLOriented</code>, see {@link #isGLOriented()}</li>
+ * </ul>
+ * </p>
+ *
+ * @param in input stream
+ * @param destFmt desired destination {@link PixelFormat} incl. conversion, maybe <code>null</code> to use source {@link PixelFormat}
+ * @param destDirectBuffer if true, using a direct NIO buffer, otherwise an array backed buffer
+ * @param destMinStrideInBytes used if greater than PNG's stride, otherwise using PNG's stride. Stride is width * bytes-per-pixel.
+ * @param destIsGLOriented
+ * @return the newly created PNGPixelRect instance
+ * @throws IOException
+ */
+ public static PNGPixelRect read(final InputStream in,
+ final PixelFormat ddestFmt, final boolean destDirectBuffer, final int destMinStrideInBytes,
+ final boolean destIsGLOriented) throws IOException {
+ final PngReader pngr = new PngReader(new BufferedInputStream(in), null);
+ final ImageInfo imgInfo = pngr.imgInfo;
+ final PngChunkPLTE plte = pngr.getMetadata().getPLTE();
+ final PngChunkTRNS trns = pngr.getMetadata().getTRNS();
+ final boolean indexed = imgInfo.indexed;
+ final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ;
+
+ if(DEBUG) {
+ System.err.println("PNGPixelRect: "+imgInfo);
+ }
+ final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ;
+ final boolean isGrayAlpha = 2 == channels && imgInfo.greyscale && imgInfo.alpha;
+ if ( ! ( 1 == channels || 3 == channels || 4 == channels || isGrayAlpha ) ) {
+ throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 channels] or Lum+A (GA) images for now. Channels "+channels + " Paletted: " + indexed);
+ }
+ final int bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ;
+ if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel || isGrayAlpha ) ) {
+ throw new RuntimeException("PNGPixelRect can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel);
+ }
+ if( channels != bytesPerPixel ) {
+ throw new RuntimeException("PNGPixelRect currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+ }
+ final int width = imgInfo.cols;
+ final int height = imgInfo.rows;
+ final double dpiX, dpiY;
+ {
+ final double[] dpi = pngr.getMetadata().getDpi();
+ dpiX = dpi[0];
+ dpiY = dpi[1];
+ }
+ final PixelFormat srcFmt;
+ if ( indexed ) {
+ if ( hasAlpha ) {
+ srcFmt = PixelFormat.RGBA8888;
+ } else {
+ srcFmt = PixelFormat.RGB888;
+ }
+ } else {
+ switch( channels ) {
+ case 1: srcFmt = PixelFormat.LUMINANCE; break;
+ case 2: srcFmt = isGrayAlpha ? PixelFormat.LUMINANCE : null; break;
+ case 3: srcFmt = PixelFormat.RGB888; break;
+ case 4: srcFmt = PixelFormat.RGBA8888; break;
+ default: srcFmt = null;
+ }
+ if( null == srcFmt ) {
+ throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
+ }
+ }
+ final PixelFormat destFmt;
+ if( null == ddestFmt ) {
+ if( isGrayAlpha ) {
+ destFmt = PixelFormat.BGRA8888; // save alpha value on gray-alpha
+ } else {
+ destFmt = srcFmt; // 1:1
+ }
+ } else {
+ destFmt = ddestFmt; // user choice
+ }
+ final int destStrideInBytes = Math.max(destMinStrideInBytes, destFmt.bytesPerPixel() * width);
+ final ByteBuffer destPixels = destDirectBuffer ? Buffers.newDirectByteBuffer(destStrideInBytes * height) :
+ ByteBuffer.allocate(destStrideInBytes * height);
+ {
+ final int reqBytes = destStrideInBytes * height;
+ if( destPixels.limit() < reqBytes ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+destPixels);
+ }
+ }
+ final boolean vert_flip = destIsGLOriented;
+
+ int[] rgbaScanline = indexed ? new int[width * channels] : null;
+ if(DEBUG) {
+ System.err.println("PNGPixelRect: indexed "+indexed+", alpha "+hasAlpha+", grayscale "+imgInfo.greyscale+", channels "+channels+"/"+imgInfo.channels+
+ ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
+ ", grayAlpha "+isGrayAlpha+", pixels "+width+"x"+height+", dpi "+dpiX+"x"+dpiY+", format "+srcFmt);
+ System.err.println("PNGPixelRect: destFormat "+destFmt+" ("+ddestFmt+", bytesPerPixel "+destFmt.bytesPerPixel()+", fast-path "+(destFmt==srcFmt)+"), destDirectBuffer "+destDirectBuffer+", destIsGLOriented (flip) "+destIsGLOriented);
+ System.err.println("PNGPixelRect: destStrideInBytes "+destStrideInBytes+" (destMinStrideInBytes "+destMinStrideInBytes+")");
+ }
+
+ for (int row = 0; row < height; row++) {
+ final ImageLine l1 = pngr.readRow(row);
+ int lineOff = 0;
+ int dataOff = vert_flip ? ( height - 1 - row ) * destStrideInBytes : row * destStrideInBytes;
+ if( indexed ) {
+ for (int j = width - 1; j >= 0; j--) {
+ rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized
+ dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, rgbaScanline, lineOff, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ } else if( 1 == channels ) {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)0xff); // Luminance, 1 bytesPerPixel
+ }
+ } else if( isGrayAlpha ) {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelLUMToAny(destFmt, destPixels, dataOff, (byte)l1.scanline[lineOff++], (byte)l1.scanline[lineOff++]); // Luminance+Alpha, 2 bytesPerPixel
+ }
+ } else if( srcFmt == destFmt ) { // fast-path
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelRGBSame(destPixels, dataOff, l1.scanline, lineOff, bytesPerPixel);
+ lineOff += bytesPerPixel;
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = getPixelRGBA8ToAny(destFmt, destPixels, dataOff, l1.scanline, lineOff, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ }
+ pngr.end();
+
+ return new PNGPixelRect(destFmt, new Dimension(width, height), destStrideInBytes, destIsGLOriented, destPixels, dpiX, dpiY);
+ }
+
+ private static final int getPixelLUMToAny(PixelFormat dest_fmt, ByteBuffer d, int dOff, byte lum, byte alpha) {
+ switch(dest_fmt) {
+ case LUMINANCE:
+ d.put(dOff++, lum);
+ break;
+ case BGR888:
+ case RGB888:
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ break;
+ case ABGR8888:
+ case ARGB8888:
+ d.put(dOff++, alpha); // A
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ break;
+ case BGRA8888:
+ case RGBA8888:
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, lum);
+ d.put(dOff++, alpha); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+dest_fmt);
+ }
+ return dOff;
+ }
+ private static final int getPixelRGBA8ToAny(final PixelFormat dest_fmt, final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final boolean srcHasAlpha) {
+ final int p = PixelFormatUtil.convertToInt32(dest_fmt, (byte)scanline[lineOff], // R
+ (byte)scanline[lineOff+1], // G
+ (byte)scanline[lineOff+2], // B
+ srcHasAlpha ? (byte)scanline[lineOff+3] : (byte)0xff); // A
+ final int dbpp = dest_fmt.bytesPerPixel();
+ d.put(dOff++, (byte) ( p )); // 1
+ if( 1 < dbpp ) {
+ d.put(dOff++, (byte) ( p >>> 8 )); // 2
+ d.put(dOff++, (byte) ( p >>> 16 )); // 3
+ if( 4 == dbpp ) {
+ d.put(dOff++, (byte) ( p >>> 24 )); // 4
+ }
+ }
+ return dOff;
+ }
+ private static final int getPixelRGBSame(final ByteBuffer d, int dOff, final int[] scanline, final int lineOff, final int bpp) {
+ d.put(dOff++, (byte)scanline[lineOff]); // R
+ if( 1 < bpp ) {
+ d.put(dOff++, (byte)scanline[lineOff + 1]); // G
+ d.put(dOff++, (byte)scanline[lineOff + 2]); // B
+ if( 4 == bpp ) {
+ d.put(dOff++, (byte)scanline[lineOff + 3]); // A
+ }
+ }
+ return dOff;
+ }
+ private int setPixelRGBA8(final ImageLine line, final int lineOff, final ByteBuffer d, final int dOff, final int bytesPerPixel, final boolean hasAlpha) {
+ final int b = hasAlpha ? 4-1 : 3-1;
+ if( d.limit() <= dOff + b ) {
+ throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d);
+ }
+ final int p = PixelFormatUtil.convertToInt32(hasAlpha ? PixelFormat.RGBA8888 : PixelFormat.RGB888, pixelformat, d, dOff);
+ line.scanline[lineOff ] = 0xff & p; // R
+ line.scanline[lineOff + 1] = 0xff & ( p >>> 8 ); // G
+ line.scanline[lineOff + 2] = 0xff & ( p >>> 16 ); // B
+ if(hasAlpha) {
+ line.scanline[lineOff + 3] = 0xff & ( p >>> 24 ); // A
+ }
+ return dOff + pixelformat.bytesPerPixel();
+ }
+
+ /**
+ * Creates a PNGPixelRect from data supplied by the end user. Shares
+ * data with the passed ByteBuffer.
+ *
+ * @param pixelformat
+ * @param size
+ * @param strideInBytes
+ * @param isGLOriented see {@link #isGLOriented()}.
+ * @param pixels
+ * @param dpiX
+ * @param dpiY
+ */
+ public PNGPixelRect(final PixelFormat pixelformat, final DimensionImmutable size,
+ final int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels,
+ final double dpiX, final double dpiY) {
+ super(pixelformat, size, strideInBytes, isGLOriented, pixels);
+ this.dpi = new double[] { dpiX, dpiY };
+ }
+ public PNGPixelRect(final PixelRectangle src, final double dpiX, final double dpiY) {
+ super(src);
+ this.dpi = new double[] { dpiX, dpiY };
+ }
+ private final double[] dpi;
+
+ /** Returns the dpi of the image. */
+ public double[] getDpi() { return dpi; }
+
+ public void write(final OutputStream outstream, final boolean closeOutstream) throws IOException {
+ final int width = size.getWidth();
+ final int height = size.getHeight();
+ final int bytesPerPixel = pixelformat.bytesPerPixel();
+ final ImageInfo imi = new ImageInfo(width, height, 8 /* bitdepth */,
+ (4 == bytesPerPixel) ? true : false /* alpha */,
+ (1 == bytesPerPixel) ? true : false /* grayscale */,
+ false /* indexed */);
+
+ // open image for writing to a output stream
+ try {
+ final PngWriter png = new PngWriter(outstream, imi);
+ // add some optional metadata (chunks)
+ png.getMetadata().setDpi(dpi[0], dpi[1]);
+ png.getMetadata().setTimeNow(0); // 0 seconds fron now = now
+ png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGPixelRect");
+ // png.getMetadata().setText("my key", "my text");
+ final boolean hasAlpha = 4 == bytesPerPixel;
+
+ final ImageLine l1 = new ImageLine(imi);
+ for (int row = 0; row < height; row++) {
+ int dataOff = isGLOriented ? ( height - 1 - row ) * strideInBytes : row * strideInBytes;
+ int lineOff = 0;
+ if(1 == bytesPerPixel) {
+ for (int j = width - 1; j >= 0; j--) {
+ l1.scanline[lineOff++] = pixels.get(dataOff++); // // Luminance, 1 bytesPerPixel
+ }
+ } else {
+ for (int j = width - 1; j >= 0; j--) {
+ dataOff = setPixelRGBA8(l1, lineOff, pixels, dataOff, bytesPerPixel, hasAlpha);
+ lineOff += bytesPerPixel;
+ }
+ }
+ png.writeRow(l1, row);
+ }
+ png.end();
+ } finally {
+ if( closeOutstream ) {
+ IOUtil.close(outstream, false);
+ }
+ }
+ }
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
index 67ab5176d..0cde24db4 100644
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java
@@ -41,10 +41,12 @@
package com.jogamp.opengl.util.texture;
import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.net.URL;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -52,9 +54,10 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
-import javax.media.opengl.GL2ES2;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;
@@ -63,11 +66,11 @@ import javax.media.opengl.GLProfile;
import jogamp.opengl.Debug;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.spi.DDSImage;
import com.jogamp.opengl.util.texture.spi.JPEGImage;
import com.jogamp.opengl.util.texture.spi.NetPbmTextureWriter;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
import com.jogamp.opengl.util.texture.spi.SGIImage;
import com.jogamp.opengl.util.texture.spi.TGAImage;
import com.jogamp.opengl.util.texture.spi.TextureProvider;
@@ -1166,27 +1169,29 @@ public class TextureIO {
boolean mipmap,
String fileSuffix) throws IOException {
if (PNG.equals(fileSuffix)) {
- PNGImage image = PNGImage.read(/*glp, */ stream);
- if (pixelFormat == 0) {
- pixelFormat = image.getGLFormat();
- }
- if (internalFormat == 0) {
+ final PNGPixelRect image = PNGPixelRect.read(stream, null, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
+ final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ if ( 0 == pixelFormat ) {
+ pixelFormat = glpa.format;
+ } // else FIXME: Actually not supported w/ preset pixelFormat!
+ if ( 0 == internalFormat ) {
+ final boolean hasAlpha = 4 == glpa.bytesPerPixel;
if(glp.isGL2ES3()) {
- internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA8:GL.GL_RGB8;
+ internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
} else {
- internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB;
+ internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
}
}
return new TextureData(glp, internalFormat,
- image.getWidth(),
- image.getHeight(),
+ image.getSize().getWidth(),
+ image.getSize().getHeight(),
0,
pixelFormat,
- image.getGLType(),
+ glpa.type,
mipmap,
false,
false,
- image.getData(),
+ image.getPixels(),
null);
}
@@ -1392,29 +1397,7 @@ public class TextureIO {
final int pixelFormat = pixelAttribs.format;
final int pixelType = pixelAttribs.type;
final int bytesPerPixel = pixelAttribs.bytesPerPixel;
- final boolean reversedChannels;
- switch(pixelFormat) {
- case GL.GL_ALPHA:
- case GL.GL_LUMINANCE:
- case GL2ES2.GL_RED:
- reversedChannels=false;
- break;
- case GL.GL_RGB:
- reversedChannels=false;
- break;
- case GL.GL_RGBA:
- reversedChannels=false;
- break;
- case GL2.GL_BGR:
- reversedChannels=true;
- break;
- case GL.GL_BGRA:
- reversedChannels=true;
- break;
- default:
- reversedChannels=false;
- break;
- }
+ final PixelFormat pixFmt = pixelAttribs.getPixelFormat();
if ( ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel) &&
( pixelType == GL.GL_BYTE || pixelType == GL.GL_UNSIGNED_BYTE)) {
ByteBuffer buf = (ByteBuffer) data.getBuffer();
@@ -1423,9 +1406,11 @@ public class TextureIO {
}
buf.rewind();
- PNGImage image = PNGImage.createFromData(data.getWidth(), data.getHeight(), -1f, -1f,
- bytesPerPixel, reversedChannels, !data.getMustFlipVertically(), buf);
- image.write(file, true);
+ final PNGPixelRect image = new PNGPixelRect(pixFmt, new Dimension(data.getWidth(), data.getHeight()),
+ 0 /* stride */, true /* isGLOriented */, buf /* pixels */,
+ -1f, -1f);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(file, true /* allowOverwrite */));
+ image.write(outs, true /* close */);
return true;
}
throw new IOException("PNG writer doesn't support this pixel format 0x"+Integer.toHexString(pixelFormat)+
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
deleted file mode 100644
index 71cbbf97e..000000000
--- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/**
- * 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.util.texture.spi;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-import javax.media.opengl.GL;
-
-import jogamp.opengl.Debug;
-import jogamp.opengl.util.pngj.ImageInfo;
-import jogamp.opengl.util.pngj.ImageLine;
-import jogamp.opengl.util.pngj.ImageLineHelper;
-import jogamp.opengl.util.pngj.PngReader;
-import jogamp.opengl.util.pngj.PngWriter;
-import jogamp.opengl.util.pngj.chunks.PngChunkPLTE;
-import jogamp.opengl.util.pngj.chunks.PngChunkTRNS;
-import jogamp.opengl.util.pngj.chunks.PngChunkTextVar;
-
-import com.jogamp.common.nio.Buffers;
-import com.jogamp.common.util.IOUtil;
-
-public class PNGImage {
- private static final boolean DEBUG = Debug.debug("PNGImage");
-
- /**
- * Creates a PNGImage from data supplied by the end user. Shares
- * data with the passed ByteBuffer. Assumes the data is already in
- * the correct byte order for writing to disk, i.e., LUMINANCE, RGB or RGBA.
- * Orientation is <i>bottom-to-top</i> (OpenGL coord. default)
- * or <i>top-to-bottom</i> depending on <code>isGLOriented</code>.
- *
- * @param width
- * @param height
- * @param dpiX
- * @param dpiY
- * @param bytesPerPixel
- * @param reversedChannels
- * @param isGLOriented see {@link #isGLOriented()}.
- * @param data
- * @return
- */
- public static PNGImage createFromData(int width, int height, double dpiX, double dpiY,
- int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
- return new PNGImage(width, height, dpiX, dpiY, bytesPerPixel, reversedChannels, isGLOriented, data);
- }
-
- /**
- * Reads a PNG image from the specified InputStream.
- * <p>
- * Implicitly flip image to GL orientation, see {@link #isGLOriented()}.
- * </p>
- */
- public static PNGImage read(InputStream in) throws IOException {
- return new PNGImage(in);
- }
-
- /** Reverse read and store, implicitly flip image to GL orientation, see {@link #isGLOriented()}. */
- private static final int getPixelRGBA8(ByteBuffer d, int dOff, int[] scanline, int lineOff, boolean hasAlpha) {
- final int b = hasAlpha ? 4-1 : 3-1;
- if( d.limit() <= dOff || dOff - b < 0 ) {
- throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+(dOff-b)+".."+dOff+"]: "+d);
- }
- if(hasAlpha) {
- d.put(dOff--, (byte)scanline[lineOff + 3]); // A
- }
- d.put(dOff--, (byte)scanline[lineOff + 2]); // B
- d.put(dOff--, (byte)scanline[lineOff + 1]); // G
- d.put(dOff--, (byte)scanline[lineOff ]); // R
- return dOff;
- }
-
- /** Reverse write and store, implicitly flip image from current orientation, see {@link #isGLOriented()}. Handle reversed channels (BGR[A]). */
- private int setPixelRGBA8(ImageLine line, int lineOff, ByteBuffer d, int dOff, boolean hasAlpha) {
- final int b = hasAlpha ? 4-1 : 3-1;
- if( d.limit() <= dOff + b ) {
- throw new IndexOutOfBoundsException("Buffer has unsufficient bytes left, needs ["+dOff+".."+(dOff+b)+"]: "+d);
- }
- if( reversedChannels ) {
- if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff++); // A
- }
- line.scanline[lineOff + 2] = d.get(dOff++); // R
- line.scanline[lineOff + 1] = d.get(dOff++); // G
- line.scanline[lineOff ] = d.get(dOff++); // B
- } else {
- line.scanline[lineOff ] = d.get(dOff++); // R
- line.scanline[lineOff + 1] = d.get(dOff++); // G
- line.scanline[lineOff + 2] = d.get(dOff++); // B
- if(hasAlpha) {
- line.scanline[lineOff + 3] = d.get(dOff++); // A
- }
- }
- return isGLOriented ? dOff - bytesPerPixel - bytesPerPixel : dOff;
- }
-
- private PNGImage(int width, int height, double dpiX, double dpiY, int bytesPerPixel, boolean reversedChannels, boolean isGLOriented, ByteBuffer data) {
- pixelWidth=width;
- pixelHeight=height;
- dpi = new double[] { dpiX, dpiY };
- if(4 == bytesPerPixel) {
- glFormat = GL.GL_RGBA;
- } else if (3 == bytesPerPixel) {
- glFormat = GL.GL_RGB;
- } else {
- throw new InternalError("XXX: bytesPerPixel "+bytesPerPixel);
- }
- this.bytesPerPixel = bytesPerPixel;
- this.reversedChannels = reversedChannels;
- this.isGLOriented = isGLOriented;
- this.data = data;
- }
-
- private PNGImage(InputStream in) {
- final PngReader pngr = new PngReader(new BufferedInputStream(in), null);
- final ImageInfo imgInfo = pngr.imgInfo;
- final PngChunkPLTE plte = pngr.getMetadata().getPLTE();
- final PngChunkTRNS trns = pngr.getMetadata().getTRNS();
- final boolean indexed = imgInfo.indexed;
- final boolean hasAlpha = indexed ? ( trns != null ) : imgInfo.alpha ;
-
- final int channels = indexed ? ( hasAlpha ? 4 : 3 ) : imgInfo.channels ;
- if ( ! ( 1 == channels || 3 == channels || 4 == channels ) ) {
- throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 channels] images for now. Channels "+channels + " Paletted: " + indexed);
- }
-
- bytesPerPixel = indexed ? channels : imgInfo.bytesPixel ;
- if ( ! ( 1 == bytesPerPixel || 3 == bytesPerPixel || 4 == bytesPerPixel ) ) {
- throw new RuntimeException("PNGImage can only handle Lum/RGB/RGBA [1/3/4 bpp] images for now. BytesPerPixel "+bytesPerPixel);
- }
- if( channels != bytesPerPixel ) {
- throw new RuntimeException("PNGImage currently only handles Channels [1/3/4] == BytePerPixel [1/3/4], channels: "+channels+", bytesPerPixel "+bytesPerPixel);
- }
- pixelWidth = imgInfo.cols;
- pixelHeight = imgInfo.rows;
- dpi = new double[2];
- {
- final double[] dpi2 = pngr.getMetadata().getDpi();
- dpi[0]=dpi2[0];
- dpi[1]=dpi2[1];
- }
- if ( indexed ) {
- if ( hasAlpha ) {
- glFormat = GL.GL_RGBA;
- } else {
- glFormat = GL.GL_RGB;
- }
- } else {
- switch( channels ) {
- case 1: glFormat = GL.GL_LUMINANCE; break;
- case 3: glFormat = GL.GL_RGB; break;
- case 4: glFormat = GL.GL_RGBA; break;
- default: throw new InternalError("XXX: channels: "+channels+", bytesPerPixel "+bytesPerPixel);
- }
- }
- if(DEBUG) {
- System.err.println("PNGImage: "+imgInfo);
- System.err.println("PNGImage: indexed "+indexed+", alpha "+hasAlpha+", channels "+channels+"/"+imgInfo.channels+
- ", bytesPerPixel "+bytesPerPixel+"/"+imgInfo.bytesPixel+
- ", pixels "+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+"x"+dpi[1]+", glFormat 0x"+Integer.toHexString(glFormat));
- }
-
- data = Buffers.newDirectByteBuffer(bytesPerPixel * pixelWidth * pixelHeight);
- reversedChannels = false; // RGB[A]
- isGLOriented = true;
- int dataOff = bytesPerPixel * pixelWidth * pixelHeight - 1; // start at end-of-buffer, reverse store
-
- int[] rgbaScanline = indexed ? new int[imgInfo.cols * channels] : null;
-
- for (int row = 0; row < pixelHeight; row++) {
- final ImageLine l1 = pngr.readRow(row);
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse read (PNG top-left -> OpenGL bottom-left origin)
- if( indexed ) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- rgbaScanline = ImageLineHelper.palette2rgb(l1, plte, trns, rgbaScanline); // reuse rgbaScanline and update if resized
- dataOff = getPixelRGBA8(data, dataOff, rgbaScanline, lineOff, hasAlpha);
- lineOff -= bytesPerPixel;
- }
- } else if( 1 == channels ) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- data.put(dataOff--, (byte)l1.scanline[lineOff--]); // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = getPixelRGBA8(data, dataOff, l1.scanline, lineOff, hasAlpha);
- lineOff -= bytesPerPixel;
- }
- }
- }
- pngr.end();
- }
- private final int pixelWidth, pixelHeight, glFormat, bytesPerPixel;
- private final boolean reversedChannels;
- private final boolean isGLOriented;
- private final double[] dpi;
- private final ByteBuffer data;
-
- /** Returns the width of the image. */
- public int getWidth() { return pixelWidth; }
-
- /** Returns the height of the image. */
- public int getHeight() { return pixelHeight; }
-
- /** Returns true if data has the channels reversed to BGR or BGRA, otherwise RGB or RGBA is expected. */
- public boolean getHasReversedChannels() { return reversedChannels; }
-
- /**
- * Returns <code>true</code> if the drawable is rendered in
- * OpenGL's coordinate system, <i>origin at bottom left</i>.
- * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
- * <p>
- * Default impl. is <code>true</code>, i.e. OpenGL coordinate system.
- * </p>
- */
- public boolean isGLOriented() { return isGLOriented; }
-
- /** Returns the dpi of the image. */
- public double[] getDpi() { return dpi; }
-
- /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */
- public int getGLFormat() { return glFormat; }
-
- /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */
- public int getGLType() { return GL.GL_UNSIGNED_BYTE; }
-
- /** Returns the bytes per pixel */
- public int getBytesPerPixel() { return bytesPerPixel; }
-
- /** Returns the raw data for this texture in the correct
- (bottom-to-top) order for calls to glTexImage2D. */
- public ByteBuffer getData() { return data; }
-
- public void write(File out, boolean allowOverwrite) throws IOException {
- final ImageInfo imi = new ImageInfo(pixelWidth, pixelHeight, 8, (4 == bytesPerPixel) ? true : false); // 8 bits per channel, no alpha
- // open image for writing to a output stream
- final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out, allowOverwrite));
- try {
- final PngWriter png = new PngWriter(outs, imi);
- // add some optional metadata (chunks)
- png.getMetadata().setDpi(dpi[0], dpi[1]);
- png.getMetadata().setTimeNow(0); // 0 seconds fron now = now
- png.getMetadata().setText(PngChunkTextVar.KEY_Title, "JogAmp PNGImage");
- // png.getMetadata().setText("my key", "my text");
- final boolean hasAlpha = 4 == bytesPerPixel;
- final ImageLine l1 = new ImageLine(imi);
- if( isGLOriented ) {
- // start at last pixel at end-of-buffer, reverse read (OpenGL bottom-left -> PNG top-left origin)
- int dataOff = ( pixelWidth * bytesPerPixel * ( pixelHeight - 1 ) ) + // full lines - 1 line
- ( ( pixelWidth - 1 ) * bytesPerPixel ); // one line - 1 pixel
- for (int row = 0; row < pixelHeight; row++) {
- int lineOff = ( pixelWidth - 1 ) * bytesPerPixel ; // start w/ last pixel in line, reverse store (OpenGL bottom-left -> PNG top-left origin)
- if(1 == bytesPerPixel) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- l1.scanline[lineOff--] = data.get(dataOff--); // // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
- lineOff -= bytesPerPixel;
- }
- }
- png.writeRow(l1, row);
- }
- } else {
- int dataOff = 0; // start at first pixel at start-of-buffer, normal read (same origin: top-left)
- for (int row = 0; row < pixelHeight; row++) {
- int lineOff = 0; // start w/ first pixel in line, normal store (same origin: top-left)
- if(1 == bytesPerPixel) {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- l1.scanline[lineOff++] = data.get(dataOff++); // // Luminance, 1 bytesPerPixel
- }
- } else {
- for (int j = pixelWidth - 1; j >= 0; j--) {
- dataOff = setPixelRGBA8(l1, lineOff, data, dataOff, hasAlpha);
- lineOff += bytesPerPixel;
- }
- }
- png.writeRow(l1, row);
- }
- }
- png.end();
- } finally {
- IOUtil.close(outs, false);
- }
- }
-
- @Override
- public String toString() { return "PNGImage["+pixelWidth+"x"+pixelHeight+", dpi "+dpi[0]+" x "+dpi[1]+", bytesPerPixel "+bytesPerPixel+", reversedChannels "+reversedChannels+", "+data+"]"; }
-}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
index b947505cb..ddf513180 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java
@@ -38,7 +38,6 @@
package com.jogamp.nativewindow.awt;
import com.jogamp.common.os.Platform;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.awt.AWTEDTExecutor;
import com.jogamp.common.util.locks.LockFactory;
import com.jogamp.common.util.locks.RecursiveLock;
@@ -53,7 +52,6 @@ import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.applet.Applet;
-import java.io.IOException;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -66,6 +64,7 @@ import javax.media.nativewindow.OffscreenLayerSurface;
import javax.media.nativewindow.SurfaceUpdatedListener;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.Rectangle;
@@ -433,19 +432,19 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
@Override
- public final boolean setCursor(final IOUtil.ClassResources resources, final PointImmutable hotSpot) throws IOException {
+ public final boolean setCursor(final PixelRectangle pixelrect, final PointImmutable hotSpot) {
AWTEDTExecutor.singleton.invoke(false, new Runnable() {
public void run() {
Cursor c = null;
- if( null == resources || null == hotSpot ) {
+ if( null == pixelrect || null == hotSpot ) {
c = Cursor.getDefaultCursor();
} else {
final java.awt.Point awtHotspot = new java.awt.Point(hotSpot.getX(), hotSpot.getY());
try {
- c = AWTMisc.getCursor(resources, awtHotspot);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ c = AWTMisc.getCursor(pixelrect, awtHotspot);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
if( null != c ) {
component.setCursor(c);
@@ -455,7 +454,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface,
}
@Override
- public boolean hideCursor() {
+ public final boolean hideCursor() {
AWTEDTExecutor.singleton.invoke(false, new Runnable() {
public void run() {
component.setCursor(AWTMisc.getNullCursor());
diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
index 81983a7c2..cf8cf89d2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java
@@ -27,11 +27,9 @@
*/
package javax.media.nativewindow;
-import java.io.IOException;
-
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.PointImmutable;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.locks.RecursiveLock;
/**
@@ -73,12 +71,12 @@ public interface OffscreenLayerSurface {
/**
* Optional method setting cursor in the corresponding on-screen surface/window, if exists.
*
- * @param resources maybe null for default cursor
+ * @param pixelrect cursor pixels, maybe null for default cursor
* @param hotSpot maybe null for default cursor
* @return true if successful, i.e. on-screen surface/window w/ cursor capabilities exists. Otherwise false.
- * @throws IOException
*/
- public boolean setCursor(IOUtil.ClassResources resources, PointImmutable hotSpot) throws IOException;
+ public boolean setCursor(PixelRectangle pixelrect, PointImmutable hotSpot);
+
/**
* Optional method hiding the cursor in the corresponding on-screen surface/window, if exists.
*
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
new file mode 100644
index 000000000..823496a92
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormat.java
@@ -0,0 +1,196 @@
+/**
+ * Copyright (c) 2014 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 javax.media.nativewindow.util;
+
+/**
+ * Basic pixel formats
+ * <p>
+ * Notation follows OpenGL notation, i.e.
+ * name consist of all it's component names
+ * followed by their bit size.
+ * </p>
+ * <p>
+ * Order of component names is from lowest-bit to highest-bit.
+ * </p>
+ * <p>
+ * In case component-size is 1 byte (e.g. OpenGL data-type GL_UNSIGNED_BYTE),
+ * component names are ordered from lowest-byte to highest-byte.
+ * Note that OpenGL applies special interpretation if
+ * data-type is e.g. GL_UNSIGNED_8_8_8_8_REV or GL_UNSIGNED_8_8_8_8_REV.
+ * </p>
+ * <p>
+ * PixelFormat can be converted to OpenGL GLPixelAttributes
+ * via
+ * <pre>
+ * GLPixelAttributes glpa = GLPixelAttributes.convert(PixelFormat pixFmt, GLProfile glp);
+ * </pre>
+ * </p>
+ * <p>
+ * See OpenGL Specification 4.3 - February 14, 2013, Core Profile,
+ * Section 8.4.4 Transfer of Pixel Rectangles, p. 161-174.
+ * </ul>
+ *
+ * </p>
+ */
+public enum PixelFormat {
+ /**
+ * Pixel size is 1 bytes (8 bits) with one component of size 1 byte (8 bits).
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_ALPHA (< GL3), GL_RED (>= GL3), data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>none</i></li>
+ * </ul>
+ * </p>
+ */
+ LUMINANCE(1, 8),
+
+ /**
+ * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: R, G, B</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGB, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ RGB888(3, 24),
+
+ /**
+ * Pixel size is 3 bytes (24 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: B, G, R</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGR (>= GL2), data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_3BYTE_BGR TYPE_3BYTE_BGR}</li>
+ * </ul>
+ * </p>
+ */
+ BGR888(3, 24),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: R, G, B, A</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: <i>None</i></li>
+ * <li>PointerIcon: X11 (XCURSOR)</li>
+ * <li>PNGJ: Scanlines</li>
+ * </ul>
+ * </p>
+ */
+ RGBA8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: A, B, G, R</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_RGBA, data-type GL_UNSIGNED_8_8_8_8</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_4BYTE_ABGR TYPE_4BYTE_ABGR}</li>
+ * </ul>
+ * </p>
+ */
+ ABGR8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: A, R, G, B</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_INT_8_8_8_8</li>
+ * <li>AWT: <i>None</i></li>
+ * </ul>
+ * </p>
+ */
+ ARGB8888(4, 32),
+
+ /**
+ * Pixel size is 4 bytes (32 bits) with each component of size 1 byte (8 bits).
+ * <p>
+ * The components are interleaved in the order:
+ * <ul>
+ * <li>Low to High: B, G, R, A</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Compatible with:
+ * <ul>
+ * <li>OpenGL: data-format GL_BGRA, data-type GL_UNSIGNED_BYTE</li>
+ * <li>AWT: {@link java.awt.image.BufferedImage#TYPE_INT_ARGB TYPE_INT_ARGB}</li>
+ * <li>PointerIcon: Win32, OSX (NSBitmapImageRep), AWT</li>
+ * <li>Window Icon: X11, Win32, OSX (NSBitmapImageRep)</li>
+ * </ul>
+ * </p>
+ */
+ BGRA8888(4, 32);
+
+ /** Number of components per pixel, e.g. 4 for RGBA. */
+ public final int componentCount;
+ /** Number of bits per pixel, e.g. 32 for RGBA. */
+ public final int bitsPerPixel;
+ /** Number of bytes per pixel, e.g. 4 for RGBA. */
+ public final int bytesPerPixel() { return (7+bitsPerPixel)/8; }
+
+ private PixelFormat(int componentCount, int bpp) {
+ this.componentCount = componentCount;
+ this.bitsPerPixel = bpp;
+ }
+}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
new file mode 100644
index 000000000..361d03446
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelFormatUtil.java
@@ -0,0 +1,374 @@
+/**
+ * Copyright (c) 2014 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 javax.media.nativewindow.util;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import com.jogamp.common.nio.Buffers;
+
+/**
+ * Pixel Rectangle Utilities.
+ * <p>
+ * All conversion methods are endian independent.
+ * </p>
+ */
+public class PixelFormatUtil {
+ public static interface PixelSink {
+ /** Return the sink's destination pixelformat. */
+ PixelFormat getPixelformat();
+
+ /**
+ * Returns stride in byte-size, i.e. byte count from one line to the next.
+ * <p>
+ * Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}.
+ * </p>
+ */
+ int getStride();
+
+ /**
+ * Returns <code>true</code> if the sink's memory is laid out in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ */
+ boolean isGLOriented();
+ }
+ /**
+ * Pixel sink for up-to 32bit.
+ */
+ public static interface PixelSink32 extends PixelSink {
+ /**
+ * Will be invoked over all rows top-to down
+ * and all columns left-to-right.
+ * <p>
+ * Shall consider dest pixelformat and only store as much components
+ * as defined, up to 32bit.
+ * </p>
+ * <p>
+ * Implementation may better write single bytes from low-to-high bits,
+ * e.g. {@link ByteOrder#LITTLE_ENDIAN} order.
+ * Otherwise a possible endian conversion must be taken into consideration.
+ * </p>
+ * @param x
+ * @param y
+ * @param pixel
+ */
+ void store(int x, int y, int pixel);
+ }
+
+ /**
+ * Returns the {@link PixelFormat} with reversed components of <code>fmt</code>.
+ * If no reversed {@link PixelFormat} is available, returns <code>fmt</code>.
+ */
+ public static PixelFormat getReversed(PixelFormat fmt) {
+ switch(fmt) {
+ case LUMINANCE:
+ return PixelFormat.LUMINANCE;
+ case RGB888:
+ return PixelFormat.BGR888;
+ case BGR888:
+ return PixelFormat.RGB888;
+ case RGBA8888:
+ return PixelFormat.ABGR8888;
+ case ABGR8888:
+ return PixelFormat.RGBA8888;
+ case ARGB8888:
+ return PixelFormat.BGRA8888;
+ case BGRA8888:
+ return PixelFormat.ABGR8888;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ }
+
+ public static int getValue32(PixelFormat src_fmt, ByteBuffer src, int srcOff) {
+ switch(src_fmt) {
+ case LUMINANCE: {
+ final byte c1 = src.get(srcOff++);
+ return ( 0xff ) << 24 | ( 0xff & c1 ) << 16 | ( 0xff & c1 ) << 8 | ( 0xff & c1 );
+ }
+ case RGB888:
+ case BGR888: {
+ final byte c1 = src.get(srcOff++);
+ final byte c2 = src.get(srcOff++);
+ final byte c3 = src.get(srcOff++);
+ return ( 0xff ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
+ }
+ case RGBA8888:
+ case ABGR8888:
+ case ARGB8888:
+ case BGRA8888: {
+ final byte c1 = src.get(srcOff++);
+ final byte c2 = src.get(srcOff++);
+ final byte c3 = src.get(srcOff++);
+ final byte c4 = src.get(srcOff++);
+ return ( 0xff & c4 ) << 24 | ( 0xff & c3 ) << 16 | ( 0xff & c2 ) << 8 | ( 0xff & c1 );
+ }
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ }
+
+ public static int convertToInt32(PixelFormat dest_fmt, final byte r, final byte g, final byte b, final byte a) {
+ switch(dest_fmt) {
+ case LUMINANCE: {
+ final byte l = ( byte) ( ( ( ( 0xff & r ) + ( 0xff & g ) + ( 0xff & b ) ) / 3 ) );
+ return ( 0xff ) << 24 | ( 0xff & l ) << 16 | ( 0xff & l ) << 8 | ( 0xff & l );
+ }
+ case RGB888:
+ return ( 0xff ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case BGR888:
+ return ( 0xff ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ case RGBA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & b ) << 16 | ( 0xff & g ) << 8 | ( 0xff & r );
+ case ABGR8888:
+ return ( 0xff & r ) << 24 | ( 0xff & g ) << 16 | ( 0xff & b ) << 8 | ( 0xff & a );
+ case ARGB8888:
+ return ( 0xff & b ) << 24 | ( 0xff & g ) << 16 | ( 0xff & r ) << 8 | ( 0xff & a );
+ case BGRA8888:
+ return ( 0xff & a ) << 24 | ( 0xff & r ) << 16 | ( 0xff & g ) << 8 | ( 0xff & b );
+ default:
+ throw new InternalError("Unhandled format "+dest_fmt);
+ }
+ }
+
+ public static int convertToInt32(PixelFormat dest_fmt, PixelFormat src_fmt, ByteBuffer src, int srcOff) {
+ final byte r, g, b, a;
+ switch(src_fmt) {
+ case LUMINANCE:
+ r = src.get(srcOff++); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ a = src.get(srcOff++); // A
+ break;
+ case ABGR8888:
+ a = src.get(srcOff++); // A
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ break;
+ case ARGB8888:
+ a = src.get(srcOff++); // A
+ r = src.get(srcOff++); // R
+ g = src.get(srcOff++); // G
+ b = src.get(srcOff++); // B
+ break;
+ case BGRA8888:
+ b = src.get(srcOff++); // B
+ g = src.get(srcOff++); // G
+ r = src.get(srcOff++); // R
+ a = src.get(srcOff++); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dest_fmt, r, g, b, a);
+ }
+
+ /**
+ public static int convertToInt32(PixelFormat dest_fmt, PixelFormat src_fmt, final int src_pixel) {
+ final byte r, g, b, a;
+ switch(src_fmt) {
+ case LUMINANCE:
+ r = (byte) ( src_pixel ); // R
+ g = r; // G
+ b = r; // B
+ a = (byte) 0xff; // A
+ break;
+ case RGB888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) 0xff; // A
+ break;
+ case BGR888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) 0xff; // A
+ break;
+ case RGBA8888:
+ r = (byte) ( src_pixel ); // R
+ g = (byte) ( src_pixel >>> 8 ); // G
+ b = (byte) ( src_pixel >>> 16 ); // B
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ case ABGR8888:
+ a = (byte) ( src_pixel ); // A
+ b = (byte) ( src_pixel >>> 8 ); // B
+ g = (byte) ( src_pixel >>> 16 ); // G
+ r = (byte) ( src_pixel >>> 24 ); // R
+ break;
+ case ARGB8888:
+ a = (byte) ( src_pixel ); // A
+ r = (byte) ( src_pixel >>> 8 ); // R
+ g = (byte) ( src_pixel >>> 16 ); // G
+ b = (byte) ( src_pixel >>> 24 ); // B
+ break;
+ case BGRA8888:
+ b = (byte) ( src_pixel ); // B
+ g = (byte) ( src_pixel >>> 8 ); // G
+ r = (byte) ( src_pixel >>> 16 ); // R
+ a = (byte) ( src_pixel >>> 24 ); // A
+ break;
+ default:
+ throw new InternalError("Unhandled format "+src_fmt);
+ }
+ return convertToInt32(dest_fmt, r, g, b, a);
+ } */
+
+ public static PixelRectangle convert32(final PixelRectangle src,
+ final PixelFormat destFmt, int ddestStride, final boolean isGLOriented,
+ final boolean destIsDirect) {
+ final int width = src.getSize().getWidth();
+ final int height = src.getSize().getHeight();
+ final int bpp = destFmt.bytesPerPixel();
+ final int destStride;
+ if( 0 != ddestStride ) {
+ destStride = ddestStride;
+ if( destStride < bpp * width ) {
+ throw new IllegalArgumentException("Invalid stride "+destStride+", must be greater than bytesPerPixel "+bpp+" * width "+width);
+ }
+ } else {
+ destStride = bpp * width;
+ }
+ final int capacity = destStride*height;
+ final ByteBuffer bb = destIsDirect ? Buffers.newDirectByteBuffer(capacity) : ByteBuffer.allocate(capacity).order(src.getPixels().order());
+
+ // System.err.println("XXX: SOURCE "+src);
+ // System.err.println("XXX: DEST fmt "+destFmt+", stride "+destStride+" ("+ddestStride+"), isGL "+isGLOriented+", "+width+"x"+height+", capacity "+capacity+", "+bb);
+
+ final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
+ public void store(int x, int y, int pixel) {
+ int o = destStride*y+x*bpp;
+ bb.put(o++, (byte) ( pixel )); // 1
+ if( 3 <= bpp ) {
+ bb.put(o++, (byte) ( pixel >>> 8 )); // 2
+ bb.put(o++, (byte) ( pixel >>> 16 )); // 3
+ if( 4 <= bpp ) {
+ bb.put(o++, (byte) ( pixel >>> 24 )); // 4
+ }
+ }
+ }
+ @Override
+ public final PixelFormat getPixelformat() {
+ return destFmt;
+ }
+ @Override
+ public final int getStride() {
+ return destStride;
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return isGLOriented;
+ }
+ };
+ convert32(imgSink, src);
+ return new PixelRectangle.GenericPixelRect(destFmt, src.getSize(), destStride, isGLOriented, bb);
+ }
+
+ public static void convert32(PixelSink32 destInt32, final PixelRectangle src) {
+ convert32(destInt32,
+ src.getPixels(), src.getPixelformat(),
+ src.isGLOriented(),
+ src.getSize().getWidth(), src.getSize().getHeight(),
+ src.getStride());
+ }
+
+ /**
+ *
+ * @param dest32 32bit pixel sink
+ * @param src_bb
+ * @param src_fmt
+ * @param src_glOriented if true, the source memory is laid out in OpenGL's coordinate system, <i>origin at bottom left</i>,
+ * otherwise <i>origin at top left</i>.
+ * @param width
+ * @param height
+ * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
+ * If zero, stride is set to <code>width * bytes-per-pixel</code>.
+ * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
+ * @param stride_bytes stride in byte-size, i.e. byte count from one line to the next.
+ * Must be >= {@link PixelFormat#bytesPerPixel() src_fmt.bytesPerPixel()} * width.
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid
+ */
+ public static void convert32(PixelSink32 dest32,
+ final ByteBuffer src_bb, final PixelFormat src_fmt, final boolean src_glOriented, final int width, final int height, int stride_bytes) {
+ final int src_bpp = src_fmt.bytesPerPixel();
+ if( 0 != stride_bytes ) {
+ if( stride_bytes < src_bpp * width ) {
+ throw new IllegalArgumentException("Invalid stride "+stride_bytes+", must be greater than bytesPerPixel "+src_bpp+" * width "+width);
+ }
+ } else {
+ stride_bytes = src_bpp * width;
+ }
+ final PixelFormat dest_fmt = dest32.getPixelformat();
+ final boolean vert_flip = src_glOriented != dest32.isGLOriented();
+ final boolean fast_copy = src_fmt == dest_fmt && dest_fmt.bytesPerPixel() == 4 ;
+ // System.err.println("XXX: SRC fmt "+src_fmt+", stride "+stride_bytes+", isGL "+src_glOriented+", "+width+"x"+height);
+ // System.err.println("XXX: DST fmt "+dest_fmt+", fast_copy "+fast_copy);
+
+ if( fast_copy ) {
+ // Fast copy
+ for(int y=0; y<height; y++) {
+ int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
+ for(int x=0; x<width; x++) {
+ dest32.store(x, y, getValue32(src_fmt, src_bb, o));
+ o += src_bpp;
+ }
+ }
+ } else {
+ // Conversion
+ for(int y=0; y<height; y++) {
+ int o = vert_flip ? ( height - 1 - y ) * stride_bytes : y * stride_bytes;
+ for(int x=0; x<width; x++) {
+ dest32.store( x, y, convertToInt32( dest_fmt, src_fmt, src_bb, o));
+ o += src_bpp;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
new file mode 100644
index 000000000..493c712bb
--- /dev/null
+++ b/src/nativewindow/classes/javax/media/nativewindow/util/PixelRectangle.java
@@ -0,0 +1,193 @@
+/**
+ * Copyright (c) 2014 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 javax.media.nativewindow.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Pixel Rectangle identified by it's {@link #hashCode()}.
+ * <p>
+ * The {@link #getPixels()} are assumed to be immutable.
+ * </p>
+ */
+public interface PixelRectangle {
+ /**
+ * <p>
+ * Computes a hash code over:
+ * <ul>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * </ul>
+ * </p>
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
+
+ /** Returns the {@link PixelFormat}. */
+ PixelFormat getPixelformat();
+
+ /** Returns the size, i.e. width and height. */
+ DimensionImmutable getSize();
+
+ /**
+ * Returns stride in byte-size, i.e. byte count from one line to the next.
+ * <p>
+ * Must be >= {@link #getPixelformat()}.{@link PixelFormat#bytesPerPixel() bytesPerPixel()} * {@link #getSize()}.{@link DimensionImmutable#getWidth() getWidth()}.
+ * </p>
+ */
+ int getStride();
+
+ /**
+ * Returns <code>true</code> if the memory is laid out in
+ * OpenGL's coordinate system, <i>origin at bottom left</i>.
+ * Otherwise returns <code>false</code>, i.e. <i>origin at top left</i>.
+ */
+ public boolean isGLOriented();
+
+ /** Returns the pixels. */
+ ByteBuffer getPixels();
+
+ @Override
+ String toString();
+
+ /**
+ * Generic PixelRectangle implementation
+ */
+ public static class GenericPixelRect implements PixelRectangle {
+ protected final PixelFormat pixelformat;
+ protected final DimensionImmutable size;
+ protected final int strideInBytes;
+ protected final boolean isGLOriented;
+ protected final ByteBuffer pixels;
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ /**
+ *
+ * @param pixelformat
+ * @param size
+ * @param strideInBytes stride in byte-size, i.e. byte count from one line to the next.
+ * If not zero, value must be >= <code>width * bytes-per-pixel</code>.
+ * If zero, stride is set to <code>width * bytes-per-pixel</code>.
+ * @param isGLOriented
+ * @param pixels
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelFormat pixelformat, final DimensionImmutable size, int strideInBytes, final boolean isGLOriented, final ByteBuffer pixels)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ if( 0 != strideInBytes ) {
+ if( strideInBytes < pixelformat.bytesPerPixel() * size.getWidth()) {
+ throw new IllegalArgumentException("Invalid stride "+strideInBytes+", must be greater than bytesPerPixel "+pixelformat.bytesPerPixel()+" * width "+size.getWidth());
+ }
+ } else {
+ strideInBytes = pixelformat.bytesPerPixel() * size.getWidth();
+ }
+ final int reqBytes = strideInBytes * size.getHeight();
+ if( pixels.limit() < reqBytes ) {
+ throw new IndexOutOfBoundsException("Dest buffer has insufficient bytes left, needs "+reqBytes+": "+pixels);
+ }
+ this.pixelformat = pixelformat;
+ this.size = size;
+ this.strideInBytes = strideInBytes;
+ this.isGLOriented = isGLOriented;
+ this.pixels = pixels;
+ }
+
+ /**
+ * Copy ctor validating src.
+ * @param src
+ * @throws IllegalArgumentException if <code>strideInBytes</code> is invalid.
+ * @throws IndexOutOfBoundsException if <code>pixels</code> has insufficient bytes left
+ */
+ public GenericPixelRect(final PixelRectangle src)
+ throws IllegalArgumentException, IndexOutOfBoundsException
+ {
+ this(src.getPixelformat(), src.getSize(), src.getStride(), src.isGLOriented(), src.getPixels());
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + strideInBytes;
+ hash = ((hash << 5) - hash) + ( isGLOriented ? 1 : 0);
+ hashCode = ((hash << 5) - hash) + pixels.hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
+
+ @Override
+ public PixelFormat getPixelformat() {
+ return pixelformat;
+ }
+
+ @Override
+ public DimensionImmutable getSize() {
+ return size;
+ }
+
+ @Override
+ public int getStride() {
+ return strideInBytes;
+ }
+
+ @Override
+ public boolean isGLOriented() {
+ return isGLOriented;
+ }
+
+ @Override
+ public ByteBuffer getPixels() {
+ return pixels;
+ }
+
+ @Override
+ public final String toString() {
+ return "PixelRect[obj 0x"+Integer.toHexString(super.hashCode())+", "+pixelformat+", "+size+", stride "+strideInBytes+", isGLOrient "+isGLOriented+", pixels "+pixels+"]";
+ }
+ }
+}
+
diff --git a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
index b690aff4d..069cffeb8 100644
--- a/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
+++ b/src/nativewindow/classes/jogamp/nativewindow/awt/AWTMisc.java
@@ -37,21 +37,19 @@ import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.net.URLConnection;
import java.util.HashMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JRootPane;
import javax.swing.WindowConstants;
-import javax.imageio.ImageIO;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.WindowClosingProtocol;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
import javax.swing.MenuSelectionManager;
-import com.jogamp.common.util.IOUtil;
-
public class AWTMisc {
public static JFrame getJFrame(Component c) {
@@ -173,7 +171,7 @@ public class AWTMisc {
MenuSelectionManager.defaultManager().clearSelectedPath();
}
- static final HashMap<String, Cursor> cursorMap = new HashMap<String, Cursor>();
+ static final HashMap<Integer, Cursor> cursorMap = new HashMap<Integer, Cursor>();
static final Cursor nulCursor;
static {
final Toolkit toolkit = Toolkit.getDefaultToolkit();
@@ -183,21 +181,43 @@ public class AWTMisc {
public static synchronized Cursor getNullCursor() { return nulCursor; }
- public static synchronized Cursor getCursor(IOUtil.ClassResources resources, Point hotSpot) throws IOException {
- final String key = resources.getClass().getName()+":"+resources.resourcePaths[0];
+ public static synchronized Cursor getCursor(PixelRectangle pixelrect, Point hotSpot) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + pixelrect.hashCode();
+ hash = ((hash << 5) - hash) + hotSpot.hashCode();
+ final Integer key = Integer.valueOf(hash);
+
Cursor cursor = cursorMap.get(key);
if( null == cursor ) {
- cursor = createAWTCursor(resources, hotSpot);
+ cursor = createCursor(pixelrect, hotSpot);
cursorMap.put(key, cursor);
}
return cursor;
}
- private static synchronized Cursor createAWTCursor(IOUtil.ClassResources resources, Point hotSpot) throws IOException {
- final URLConnection urlConn = resources.resolve(0);
- final BufferedImage img = ImageIO.read(urlConn.getInputStream());
-
+ private static synchronized Cursor createCursor(PixelRectangle pixelrect, Point hotSpot) {
+ final int width = pixelrect.getSize().getWidth();
+ final int height = pixelrect.getSize().getHeight();
+ final BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); // PixelFormat.BGRA8888
+ final PixelFormatUtil.PixelSink32 imgSink = new PixelFormatUtil.PixelSink32() {
+ public void store(int x, int y, int pixel) {
+ img.setRGB(x, y, pixel);
+ }
+ @Override
+ public final PixelFormat getPixelformat() {
+ return PixelFormat.BGRA8888;
+ }
+ @Override
+ public int getStride() {
+ return width*4;
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ };
+ PixelFormatUtil.convert32(imgSink, pixelrect);
final Toolkit toolkit = Toolkit.getDefaultToolkit();
- return toolkit.createCustomCursor(img, hotSpot, resources.resourcePaths[0]);
+ return toolkit.createCustomCursor(img, hotSpot, pixelrect.toString());
}
public static WindowClosingProtocol.WindowClosingMode AWT2NWClosingOperation(int awtClosingOperation) {
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 8d1445f80..4b38fcca5 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -30,14 +30,14 @@ package com.jogamp.newt;
import java.io.IOException;
import java.lang.ref.WeakReference;
-import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.nativewindow.util.PointImmutable;
import jogamp.newt.Debug;
@@ -47,6 +47,7 @@ import com.jogamp.newt.util.EDTUtil;
public abstract class Display {
public static final boolean DEBUG = Debug.debug("Display");
+ protected static final boolean DEBUG_POINTER_ICON = Debug.debug("Display.PointerIcon");
/** return precomputed hashCode from FQN {@link #getFQName()} */
@Override
@@ -66,7 +67,9 @@ public abstract class Display {
/**
* Native PointerIcon handle.
* <p>
- * Instances can be created via {@link Display}'s {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(..)}.
+ * Instances can be created via {@link Display}'s
+ * {@link Display#createPointerIcon(com.jogamp.common.util.IOUtil.ClassResources, int, int) createPointerIcon(pngResource, ..)}
+ * or {@link Display#createPointerIcon(PixelRectangle, int, int) createPointerIcon(pixelrect, ..)}.
* </p>
* <p>
* Instance is {@link #destroy()}'ed automatically if it's {@link #getDisplay() associated Display} is destroyed.
@@ -75,23 +78,65 @@ public abstract class Display {
* Instance can be re-validated after destruction via {@link #validate()}.
* </p>
* <p>
+ * {@link PointerIcon} must not be {@link #destroy() destroyed} while in use!
+ * </p>
+ * <p>
* {@link PointerIcon} may be {@link #destroy() destroyed} manually after use,
* i.e. when no {@link Window} {@link Window#setPointerIcon(PointerIcon) uses them} anymore.
+ * However, this is not required.
* </p>
* <p>
* PointerIcons can be used via {@link Window#setPointerIcon(PointerIcon)}.
* </p>
*/
- public static interface PointerIcon {
+ public static interface PointerIcon extends PixelRectangle {
/**
- * @return the associated Display
+ * Always neatly packed, i.e. width * bytes_per_pixel.
+ * <p>
+ * {@inheritDoc}
+ * </p>
*/
- Display getDisplay();
+ @Override
+ int getStride();
+
+ /**
+ * Always false, i.e. origin is TOP-LEFT.
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ boolean isGLOriented();
+
+ /**
+ * Computes a hash code over:
+ * <ul>
+ * <li>display</li>
+ * <li>pixelformat</li>
+ * <li>size</li>
+ * <li>stride</li>
+ * <li>isGLOriented</li>
+ * <li>pixels</li>
+ * <li>hotspot</li>
+ * </ul>
+ * Dismissing the native handle!
+ * <p>
+ * The hashCode shall be computed only once with first call
+ * and stored for later retrieval to enhance performance.
+ * </p>
+ * <p>
+ * {@inheritDoc}
+ * </p>
+ */
+ @Override
+ int hashCode();
/**
- * @return the single {@link IOUtil.ClassResources}.
+ * @return the associated Display
*/
- IOUtil.ClassResources getResource();
+ Display getDisplay();
+
+ /** Returns the hotspot. */
+ PointImmutable getHotspot();
/**
* Returns true if valid, otherwise false.
@@ -116,35 +161,69 @@ public abstract class Display {
* </p>
*/
void destroy();
+ }
- /** Returns the size, i.e. width and height. */
- DimensionImmutable getSize();
+ /**
+ * Returns the native platform's {@link PointerIcon.PixelFormat} for pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract PixelFormat getNativePointerIconPixelFormat();
- /** Returns the hotspot. */
- PointImmutable getHotspot();
+ /**
+ * Returns the native platform's direct NIO buffer requirement pointer-icon pixel data.
+ * <p>
+ * Using this value will avoid conversion within {@link #createPointerIcon(PixelRectangle, int, int)}.
+ * </p>
+ */
+ public abstract boolean getNativePointerIconForceDirectNIO();
- @Override
- String toString();
- }
+ /**
+ * Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
+ * <p>
+ * See {@link PointerIcon} for lifecycle semantics.
+ * </p>
+ *
+ * @param pngResource single PNG resource for the {@link PointerIcon}. Only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param hotX pointer hotspot x-coord, origin is upper-left corner
+ * @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pngResource is null or invalid
+ * @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
+ * @throws IOException if the <code>pngResource</code> could not be {@link IOUtil.ClassResources#resolve(int) resolved}
+ * or via the PNG parser processing the input stream.
+ *
+ * @see PointerIcon
+ * @see Window#setPointerIcon(PointerIcon)
+ */
+ public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException;
/**
* Returns the newly created {@link PointerIcon} or <code>null</code> if not implemented on platform.
* <p>
* See {@link PointerIcon} for lifecycle semantics.
* </p>
+ * <p>
+ * In case {@link #getNativePointerIconPixelFormat()} or {@link #getNativePointerIconForceDirectNIO()}
+ * is not matched by the given <code>pixelrect</code>, the <code>pixelrect</code> is converted
+ * into the required {@link PixelFormat} and NIO type.
+ * </p>
*
- * @param pngResource single PNG resource, only the first entry of {@link IOUtil.ClassResources#resourcePaths} is used.
+ * @param pixelrect {@link PixelRectangle} source for the {@link PointerIcon}
* @param hotX pointer hotspot x-coord, origin is upper-left corner
* @param hotY pointer hotspot y-coord, origin is upper-left corner
+ *
+ * @throws IllegalArgumentException if pixelrect is null.
* @throws IllegalStateException if this Display instance is not {@link #isNativeValid() valid yet}.
- * @throws MalformedURLException
- * @throws InterruptedException
- * @throws IOException
*
* @see PointerIcon
* @see Window#setPointerIcon(PointerIcon)
+ * @see #getNativePointerIconPixelFormat()
+ * @see #getNativePointerIconForceDirectNIO()
*/
- public abstract PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws IllegalStateException, MalformedURLException, InterruptedException, IOException;
+ public abstract PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY) throws IllegalArgumentException, IllegalStateException;
/**
* Manual trigger the native creation, if it is not done yet.<br>
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
index 7ffbc2e83..472672fd9 100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -235,10 +235,10 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.setVisible(true);
glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
if( null == pointerIconTest ) {
- final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } );
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } );
final Display disp = glWindow.getScreen().getDisplay();
try {
- pointerIconTest = disp.createPointerIcon(res, 16, 0);
+ pointerIconTest = disp.createPointerIcon(res, 16, 16);
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index 346c03b15..4c7169ec4 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -34,7 +34,9 @@
package jogamp.newt;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
+import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.newt.Display;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.event.NEWTEvent;
@@ -43,17 +45,25 @@ import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
import com.jogamp.newt.util.EDTUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
import javax.media.nativewindow.NativeWindowFactory;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PointImmutable;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
+ private static final boolean pngUtilAvail;
static {
NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
@@ -64,8 +74,14 @@ public abstract class DisplayImpl extends Display {
DisplayImpl.shutdownAll();
}
});
+
+ final ClassLoader cl = DisplayImpl.class.getClassLoader();
+ pngUtilAvail = ReflectionUtil.isClassAvailable("jogamp.opengl.util.pngj.PngReader", cl) &&
+ ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.PNGPixelRect", cl);
}
+ public static final boolean isPNGUtilAvailable() { return pngUtilAvail; }
+
final ArrayList<PointerIconImpl> pointerIconList = new ArrayList<PointerIconImpl>();
/** Executed from EDT! */
@@ -86,13 +102,94 @@ public abstract class DisplayImpl extends Display {
}
@Override
- public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- return createPointerIcon(false /* isTemp */, pngResource, hotX, hotY);
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.BGRA8888; }
+ @Override
+ public boolean getNativePointerIconForceDirectNIO() { return false; }
+
+ @Override
+ public final PointerIcon createPointerIcon(final IOUtil.ClassResources pngResource, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException, IOException
+ {
+ if( !isNativeValid() ) {
+ throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this);
+ }
+ if( null == pngResource || 0 >= pngResource.resourceCount() ) {
+ throw new IllegalArgumentException("Null or invalid pngResource "+pngResource);
+ }
+ if( !pngUtilAvail ) {
+ return null;
+ }
+ final PointerIconImpl[] res = { null };
+ runOnEDTIfAvail(true, new Runnable() {
+ public void run() {
+ try {
+ if( !DisplayImpl.this.isNativeValid() ) {
+ throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this);
+ }
+ final URLConnection urlConn = pngResource.resolve(0);
+ if( null == urlConn ) {
+ throw new IOException("Could not resolve "+pngResource.resourcePaths[0]);
+ }
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(),
+ getNativePointerIconPixelFormat(),
+ getNativePointerIconForceDirectNIO(),
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ final long handle = createPointerIconImplChecked(image.getPixelformat(), image.getSize().getWidth(), image.getSize().getHeight(),
+ image.getPixels(), hotX, hotY);
+ final PointImmutable hotspot = new Point(hotX, hotY);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+image+", handle: "+toHexString(handle)+", hot "+hotspot);
+ }
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, image, hotspot, handle);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconPNG.0: "+res[0]);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } } );
+ if( null != res[0] ) {
+ synchronized(pointerIconList) {
+ pointerIconList.add(res[0]);
+ }
+ }
+ return res[0];
}
- PointerIcon createPointerIcon(final boolean isTemp, final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
+
+ @Override
+ public final PointerIcon createPointerIcon(final PixelRectangle pixelrect, final int hotX, final int hotY)
+ throws IllegalArgumentException, IllegalStateException
+ {
if( !isNativeValid() ) {
throw new IllegalStateException("Display.createPointerIcon(1): Display invalid "+this);
}
+ if( null == pixelrect ) {
+ throw new IllegalArgumentException("Null or pixelrect");
+ }
+ final PixelRectangle fpixelrect;
+ if( getNativePointerIconPixelFormat() != pixelrect.getPixelformat() || pixelrect.isGLOriented() ) {
+ // conversion !
+ fpixelrect = PixelFormatUtil.convert32(pixelrect, getNativePointerIconPixelFormat(),
+ 0 /* ddestStride */, false /* isGLOriented */, getNativePointerIconForceDirectNIO() );
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-FMT "+pixelrect+" -> "+fpixelrect);
+ }
+ } else if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixelrect.getPixels()) ) {
+ // transfer to direct NIO
+ final ByteBuffer sBB = pixelrect.getPixels();
+ final ByteBuffer dBB = Buffers.newDirectByteBuffer(sBB.array(), sBB.arrayOffset());
+ fpixelrect = new PixelRectangle.GenericPixelRect(pixelrect.getPixelformat(), pixelrect.getSize(), pixelrect.getStride(), pixelrect.isGLOriented(), dBB);
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: Conversion-NIO "+pixelrect+" -> "+fpixelrect);
+ }
+ } else {
+ fpixelrect = pixelrect;
+ if( DEBUG_POINTER_ICON ) {
+ System.err.println("createPointerIconRES.0: No conversion "+fpixelrect);
+ }
+ }
final PointerIconImpl[] res = { null };
runOnEDTIfAvail(true, new Runnable() {
public void run() {
@@ -100,22 +197,63 @@ public abstract class DisplayImpl extends Display {
if( !DisplayImpl.this.isNativeValid() ) {
throw new IllegalStateException("Display.createPointerIcon(2): Display invalid "+DisplayImpl.this);
}
- res[0] = createPointerIconImpl(pngResource, hotX, hotY);
+ if( null != fpixelrect ) {
+ final long handle = createPointerIconImplChecked(fpixelrect.getPixelformat(),
+ fpixelrect.getSize().getWidth(),
+ fpixelrect.getSize().getHeight(),
+ fpixelrect.getPixels(), hotX, hotY);
+ if( 0 != handle ) {
+ res[0] = new PointerIconImpl(DisplayImpl.this, fpixelrect, new Point(hotX, hotY), handle);
+ }
+ }
} catch (Exception e) {
e.printStackTrace();
}
} } );
- if( !isTemp ) {
+ if( null != res[0] ) {
synchronized(pointerIconList) {
pointerIconList.add(res[0]);
}
}
return res[0];
}
- /** Executed from EDT! */
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- return null;
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected final long createPointerIconImplChecked(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ if( getNativePointerIconPixelFormat() != pixelformat ) {
+ throw new IllegalArgumentException("Pixelformat no "+getNativePointerIconPixelFormat()+", but "+pixelformat);
+ }
+ if( getNativePointerIconForceDirectNIO() && !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("pixel buffer is not direct "+pixels);
+ }
+ return createPointerIconImpl(pixelformat, width, height, pixels, hotX, hotY);
+ }
+
+ /**
+ * Executed from EDT!
+ *
+ * @param pixelformat the <code>pixels</code>'s format
+ * @param width the <code>pixels</code>'s width
+ * @param height the <code>pixels</code>'s height
+ * @param pixels the <code>pixels</code>
+ * @param hotX the PointerIcon's hot-spot x-coord
+ * @param hotY the PointerIcon's hot-spot x-coord
+ * @return if successful a valid handle (not null), otherwise null.
+ */
+ protected long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return 0;
}
+
/** Executed from EDT! */
protected void destroyPointerIconImpl(final long displayHandle, long piHandle) { }
diff --git a/src/newt/classes/jogamp/newt/PointerIconImpl.java b/src/newt/classes/jogamp/newt/PointerIconImpl.java
index e2388be67..7c8535f20 100644
--- a/src/newt/classes/jogamp/newt/PointerIconImpl.java
+++ b/src/newt/classes/jogamp/newt/PointerIconImpl.java
@@ -27,27 +27,63 @@
*/
package jogamp.newt;
+import java.nio.ByteBuffer;
+
import javax.media.nativewindow.util.DimensionImmutable;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.PointImmutable;
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.common.util.IOUtil.ClassResources;
import com.jogamp.newt.Display;
import com.jogamp.newt.Display.PointerIcon;
public class PointerIconImpl implements PointerIcon {
private final DisplayImpl display;
- private final IOUtil.ClassResources resource;
+ private final PixelFormat pixelformat;
private final DimensionImmutable size;
+ private final ByteBuffer pixels;
private final PointImmutable hotspot;
private long handle;
- public PointerIconImpl(DisplayImpl display, ClassResources resource, final DimensionImmutable size, final PointImmutable hotspot, final long handle) {
+ private int hashCode = 0;
+ private volatile boolean hashCodeComputed = false;
+
+ public PointerIconImpl(final DisplayImpl display, final PixelFormat pixelformat, final DimensionImmutable size, final ByteBuffer pixels, final PointImmutable hotspot, final long handle) {
this.display = display;
- this.resource = resource;
+ this.pixelformat = pixelformat;
this.size = size;
+ this.pixels = pixels;
this.hotspot = hotspot;
+
this.handle=handle;
}
+ public PointerIconImpl(final DisplayImpl display, final PixelRectangle pixelrect, final PointImmutable hotspot, final long handle) {
+ this.display = display;
+ this.pixelformat = pixelrect.getPixelformat();
+ this.size = pixelrect.getSize();
+ this.pixels = pixelrect.getPixels();
+ this.hotspot = hotspot;
+ this.handle=handle;
+ }
+
+ @Override
+ public int hashCode() {
+ if( !hashCodeComputed ) { // DBL CHECKED OK VOLATILE
+ synchronized (this) {
+ if( !hashCodeComputed ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + display.getFQName().hashCode();
+ hash = ((hash << 5) - hash) + pixelformat.hashCode();
+ hash = ((hash << 5) - hash) + size.hashCode();
+ hash = ((hash << 5) - hash) + getStride();
+ hash = ((hash << 5) - hash) + ( isGLOriented() ? 1 : 0);
+ hash = ((hash << 5) - hash) + pixels.hashCode();
+ hashCode = ((hash << 5) - hash) + hotspot.hashCode();
+ }
+ }
+ }
+ return hashCode;
+ }
+
public synchronized final long getHandle() { return handle; }
public synchronized final long validatedHandle() {
synchronized(display.pointerIconList) {
@@ -57,8 +93,7 @@ public class PointerIconImpl implements PointerIcon {
}
if( 0 == handle ) {
try {
- final PointerIconImpl temp = (PointerIconImpl) display.createPointerIcon(true /* isTemp */, resource, hotspot.getX(), hotspot.getY());
- handle = temp.handle;
+ handle = display.createPointerIconImpl(pixelformat, size.getWidth(), size.getHeight(), pixels, hotspot.getX(), hotspot.getY());
return handle;
} catch (Exception e) {
e.printStackTrace();
@@ -71,7 +106,9 @@ public class PointerIconImpl implements PointerIcon {
@Override
public final Display getDisplay() { return display; }
@Override
- public final IOUtil.ClassResources getResource() { return resource; }
+ public final PixelFormat getPixelformat() { return pixelformat; }
+ @Override
+ public final ByteBuffer getPixels() { return pixels; }
@Override
public synchronized final boolean isValid() { return 0 != handle; }
@Override
@@ -116,11 +153,19 @@ public class PointerIconImpl implements PointerIcon {
return size;
}
@Override
+ public final int getStride() {
+ return size.getWidth() * pixelformat.bytesPerPixel();
+ }
+ @Override
+ public final boolean isGLOriented() {
+ return false;
+ }
+ @Override
public final PointImmutable getHotspot() {
return hotspot;
}
@Override
public final String toString() {
- return "PointerIcon["+DisplayImpl.toHexString(super.hashCode())+", "+display.getFQName()+", "+resource.resourcePaths[0]+", 0x"+Long.toHexString(handle)+", "+size+", "+hotspot+"]";
+ return "PointerIcon[obj 0x"+Integer.toHexString(super.hashCode())+", "+display.getFQName()+", 0x"+Long.toHexString(handle)+", "+pixelformat+", "+size+", "+hotspot+", pixels "+pixels+"]";
}
} \ No newline at end of file
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 50f30f04d..dc9affd63 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -53,6 +53,7 @@ import javax.media.nativewindow.WindowClosingProtocol;
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
+import javax.media.nativewindow.util.PixelRectangle;
import javax.media.nativewindow.util.Point;
import javax.media.nativewindow.util.PointImmutable;
import javax.media.nativewindow.util.Rectangle;
@@ -61,7 +62,6 @@ import javax.media.nativewindow.util.RectangleImmutable;
import jogamp.nativewindow.SurfaceUpdatedHelper;
import com.jogamp.common.util.ArrayHashSet;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.IntBitfield;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.common.util.locks.LockFactory;
@@ -1700,7 +1700,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
/**
* Helper method to delegate {@link #setPointerVisibleImpl(boolean)} to
- * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+ * {@link OffscreenLayerSurface#hideCursor()} or {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}.
* <p>
* Note: JAWTWindow is an OffscreenLayerSurface.
* </p>
@@ -1755,7 +1755,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
/**
* Helper method to delegate {@link #setPointerIconIntern(PointerIconImpl)} to
- * {@link OffscreenLayerSurface#setCursor(IOUtil.ClassResources, PointImmutable)}.
+ * {@link OffscreenLayerSurface#setCursor(PixelRectangle, PointImmutable)}
* <p>
* Note: JAWTWindow is an OffscreenLayerSurface.
* </p>
@@ -1777,7 +1777,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
final OffscreenLayerSurface ols = (OffscreenLayerSurface) parent;
try {
if( null != pi ) {
- return ols.setCursor(pi.getResource(), pi.getHotspot());
+ return ols.setCursor(pi, pi.getHotspot());
} else {
return ols.setCursor(null, null); // default
}
diff --git a/src/newt/classes/jogamp/newt/driver/PNGIcon.java b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
index ffa62978f..967acd413 100644
--- a/src/newt/classes/jogamp/newt/driver/PNGIcon.java
+++ b/src/newt/classes/jogamp/newt/driver/PNGIcon.java
@@ -32,6 +32,7 @@ import java.net.MalformedURLException;
import java.nio.ByteBuffer;
import jogamp.newt.Debug;
+import jogamp.newt.DisplayImpl;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.ReflectionUtil;
@@ -45,8 +46,7 @@ public class PNGIcon {
Debug.initSingleton();
final ClassLoader cl = PNGIcon.class.getClassLoader();
- avail = ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl) &&
- ReflectionUtil.isClassAvailable("com.jogamp.opengl.util.texture.spi.PNGImage", cl);
+ avail = DisplayImpl.isPNGUtilAvailable() && ReflectionUtil.isClassAvailable("jogamp.newt.driver.opengl.JoglUtilPNGIcon", cl);
}
/** Returns true if PNG decoder is available. */
@@ -55,7 +55,11 @@ public class PNGIcon {
}
/**
- * Implemented for X11.
+ * Special implementation for X11 Window Icons
+ * <p>
+ * The returned byte buffer is a direct buffer!
+ * </p>
+ *
* @param resources
* @param data_size
* @param elem_bytesize
@@ -73,29 +77,4 @@ public class PNGIcon {
}
throw new UnsupportedOperationException(err0);
}
-
- /**
- * Implemented for Windows.
- * @param resources
- * @param toBGRA if true, arranges stores in BGRA888 order, otherwise RGBA888
- * @param width
- * @param height
- * @param data_size
- * @param resourcesIdx
- * @return pixels with origin at upper-left corner.
- * If storing RGBA8888, component R is located on the lowest 8-bit.
- * If storing BGRA8888, component B is located on the lowest 8-bit.
- * Component A is located on the highest 8-bit.
- *
- * @throws UnsupportedOperationException if not implemented
- * @throws InterruptedException
- * @throws IOException
- * @throws MalformedURLException
- */
- public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- if( avail ) {
- return jogamp.newt.driver.opengl.JoglUtilPNGIcon.singleToRGBAImage(resources, resourceIdx, toBGRA, width, height, data_size);
- }
- throw new UnsupportedOperationException(err0);
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index 30583c48c..d850a18af 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -34,28 +34,25 @@
package jogamp.newt.driver.macosx;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
- private static final int defaultIconWidth, defaultIconHeight;
- private static final Buffer defaultIconData;
+ private static final PNGPixelRect defaultIconData;
static {
NEWTJNILibLoader.loadNEWT();
@@ -67,21 +64,23 @@ public class DisplayDriver extends DisplayImpl {
throw new NativeWindowException("Failed to initialize jmethodIDs");
}
{
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- Buffer data=null;
- if( PNGIcon.isAvailable() ) {
+ PNGPixelRect image=null;
+ if( DisplayImpl.isPNGUtilAvailable() ) {
try {
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
- data = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, false /* toBGRA */, width, height, data_size);
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, true /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
} catch (Exception e) {
e.printStackTrace();
}
}
- defaultIconWidth = width[0];
- defaultIconHeight = height[0];
- defaultIconData = data;
+ defaultIconData = image;
if( null != defaultIconData ) {
- DisplayDriver.setAppIcon0(defaultIconData, defaultIconWidth, defaultIconHeight);
+ final Buffer pixels = defaultIconData.getPixels();
+ DisplayDriver.setAppIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ defaultIconData.getSize().getWidth(), defaultIconData.getSize().getHeight());
}
}
@@ -112,17 +111,20 @@ public class DisplayDriver extends DisplayImpl {
aDevice.close();
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size);
- return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]),
- new Point(hotX, hotY), createPointerIcon0(data, width[0], height[0], hotX, hotY));
- }
- }
- return null;
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon0(
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */,
+ width, height, hotX, hotY);
}
@Override
@@ -140,8 +142,8 @@ public class DisplayDriver extends DisplayImpl {
private static native boolean initNSApplication0();
private static native void runNSApplication0();
private static native void stopNSApplication0();
- /* pp */ static native void setAppIcon0(Object iconData, int iconWidth, int iconHeight);
- private static native long createPointerIcon0(Object iconData, int iconWidth, int iconHeight, int hotX, int hotY);
+ /* pp */ static native void setAppIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height);
+ private static native long createPointerIcon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
private static native long destroyPointerIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
index 216a0cb20..551929b8d 100644
--- a/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
+++ b/src/newt/classes/jogamp/newt/driver/opengl/JoglUtilPNGIcon.java
@@ -32,20 +32,22 @@ import java.net.MalformedURLException;
import java.net.URLConnection;
import java.nio.ByteBuffer;
+import javax.media.nativewindow.util.PixelFormat;
+
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
+import com.jogamp.opengl.util.PNGPixelRect;
public class JoglUtilPNGIcon {
public static ByteBuffer arrayToX11BGRAImages(IOUtil.ClassResources resources, int[] data_size, int[] elem_bytesize) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- final PNGImage[] images = new PNGImage[resources.resourceCount()];
+ final PNGPixelRect[] images = new PNGPixelRect[resources.resourceCount()];
data_size[0] = 0;
for(int i=0; i<resources.resourceCount(); i++) {
final URLConnection urlConn = resources.resolve(i);
- final PNGImage image = PNGImage.read(urlConn.getInputStream());
- data_size[0] += 2 + image.getWidth() * image.getHeight();
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ data_size[0] += 2 + image.getSize().getWidth() * image.getSize().getHeight();
images[i] = image;
}
final boolean is64Bit = Platform.is64Bit();
@@ -53,31 +55,26 @@ public class JoglUtilPNGIcon {
final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize[0] );
for(int i=0; i<images.length; i++) {
- final PNGImage image1 = images[i];
+ final PNGPixelRect image1 = images[i];
+ final int width = image1.getSize().getWidth();
+ final int height = image1.getSize().getHeight();
if( is64Bit ) {
- buffer.putLong(image1.getWidth());
- buffer.putLong(image1.getHeight());
+ buffer.putLong(width);
+ buffer.putLong(height);
} else {
- buffer.putInt(image1.getWidth());
- buffer.putInt(image1.getHeight());
+ buffer.putInt(width);
+ buffer.putInt(height);
}
- final ByteBuffer bb = image1.getData();
- final int bpp = image1.getBytesPerPixel();
- final int stride = image1.getWidth() * bpp;
- for(int y=0; y<image1.getHeight(); y++) {
- int bbOff = image1.isGLOriented() ? ( image1.getHeight() - 1 - y ) * stride : y * stride;
- for(int x=0; x<image1.getWidth(); x++) {
- // Source: R G B A
- // Dest: B G R A
+ final ByteBuffer bb = image1.getPixels();
+ final int stride = image1.getStride();
+ for(int y=0; y<height; y++) {
+ int bbOff = y * stride;
+ for(int x=0; x<width; x++) {
long pixel;
- pixel = ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel = ( 0xffL & bb.get(bbOff++) ); // B
pixel |= ( 0xffL & bb.get(bbOff++) ) << 8; // G
- pixel |= ( 0xffL & bb.get(bbOff++) ); // B
- if( 4 == bpp ) {
- pixel |= ( 0xffL & bb.get(bbOff++) ) << 24;
- } else {
- pixel |= 0x00000000ff000000L;
- }
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 16; // R
+ pixel |= ( 0xffL & bb.get(bbOff++) ) << 24; // A
if( is64Bit ) {
buffer.putLong(pixel);
} else {
@@ -89,51 +86,4 @@ public class JoglUtilPNGIcon {
buffer.rewind();
return buffer;
}
-
- public static ByteBuffer singleToRGBAImage(IOUtil.ClassResources resources, int resourceIdx, boolean toBGRA, int[] width, int[] height, int[] data_size) throws UnsupportedOperationException, InterruptedException, IOException, MalformedURLException {
- width[0] = 0;
- height[0] = 0;
- data_size[0] = 0;
- final URLConnection urlConn = resources.resolve(resourceIdx);
- final PNGImage image = PNGImage.read(urlConn.getInputStream());
- width[0] = image.getWidth();
- height[0] = image.getHeight();
- data_size[0] = image.getWidth() * image.getHeight();
-
- final int elem_bytesize = 4; // BGRA
- final ByteBuffer buffer = Buffers.newDirectByteBuffer( data_size[0] * elem_bytesize );
-
- final ByteBuffer bb = image.getData();
- final int bpp = image.getBytesPerPixel();
- final int stride = image.getWidth() * bpp;
- for(int y=0; y<image.getHeight(); y++) {
- int bbOff = image.isGLOriented() ? ( image.getHeight() - 1 - y ) * stride : y * stride;
- for(int x=0; x<image.getWidth(); x++) {
- // Source: R G B A
- final byte r, g, b, a;
- r = bb.get(bbOff++); // R
- g = bb.get(bbOff++); // G
- b = bb.get(bbOff++); // B
- if( 4 == bpp ) {
- a = bb.get(bbOff++); // A
- } else {
- a = (byte)0xff; // A
- }
- if( toBGRA ) {
- // Dest: B G R A
- buffer.put(b);
- buffer.put(g);
- buffer.put(r);
- } else {
- // Dest: R G B A
- buffer.put(r);
- buffer.put(g);
- buffer.put(b);
- }
- buffer.put(a);
- }
- }
- buffer.rewind();
- return buffer;
- }
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index a4db50165..a30431788 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -34,8 +34,7 @@
package jogamp.newt.driver.windows;
-import java.io.IOException;
-import java.net.MalformedURLException;
+import java.net.URLConnection;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@@ -43,18 +42,16 @@ import jogamp.nativewindow.windows.RegisteredClass;
import jogamp.nativewindow.windows.RegisteredClassFactory;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
import com.jogamp.common.nio.Buffers;
import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.newt.NewtFactory;
+import com.jogamp.opengl.util.PNGPixelRect;
public class DisplayDriver extends DisplayImpl {
@@ -66,17 +63,18 @@ public class DisplayDriver extends DisplayImpl {
NEWTJNILibLoader.loadNEWT();
{
long[] _defaultIconHandle = { 0, 0 };
- if( PNGIcon.isAvailable() ) {
+ if( DisplayImpl.isPNGUtilAvailable() ) {
try {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
final IOUtil.ClassResources iconRes = NewtFactory.getWindowIcons();
{
- final ByteBuffer icon_data_small = PNGIcon.singleToRGBAImage(iconRes, 0, true /* toBGRA */, width, height, data_size);
- _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(icon_data_small, width[0], height[0], false, 0, 0);
+ final URLConnection urlConn = iconRes.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[0] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
}
{
- final ByteBuffer icon_data_big = PNGIcon.singleToRGBAImage(iconRes, iconRes.resourceCount()-1, true /* toBGRA */, width, height, data_size);
- _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(icon_data_big, width[0], height[0], false, 0, 0);
+ final URLConnection urlConn = iconRes.resolve(iconRes.resourceCount()-1);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), PixelFormat.BGRA8888, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ _defaultIconHandle[1] = DisplayDriver.createBGRA8888Icon0(image.getPixels(), image.getSize().getWidth(), image.getSize().getHeight(), false, 0, 0);
}
} catch (Exception e) {
e.printStackTrace();
@@ -127,16 +125,8 @@ public class DisplayDriver extends DisplayImpl {
}
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, true /* toBGRA */, width, height, data_size);
- return new PointerIconImpl( this, pngResource, new Dimension(width[0], height[0]),
- new Point(hotX, hotY), createBGRA8888Icon0(data, width[0], height[0], true, hotX, hotY));
- }
- }
- return null;
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createBGRA8888Icon0(pixels, width, height, true, hotX, hotY);
}
@Override
@@ -149,16 +139,18 @@ public class DisplayDriver extends DisplayImpl {
//
private static native void DispatchMessages0();
- static long createBGRA8888Icon0(Buffer data, int width, int height, boolean isCursor, int hotX, int hotY) {
- if( null == data ) {
+ static long createBGRA8888Icon0(Buffer pixels, int width, int height, boolean isCursor, int hotX, int hotY) {
+ if( null == pixels ) {
throw new IllegalArgumentException("data buffer/size");
}
- if( !Buffers.isDirect(data) ) {
- throw new IllegalArgumentException("data buffer is not direct "+data);
- }
- return createBGRA8888Icon0(data, Buffers.getDirectBufferByteOffset(data), width, height, isCursor, hotX, hotY);
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createBGRA8888Icon0(
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, isCursor, hotX, hotY);
}
- private static native long createBGRA8888Icon0(Object data, int data_offset, int width, int height, boolean isCursor, int hotX, int hotY);
+ private static native long createBGRA8888Icon0(Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, boolean isCursor, int hotX, int hotY);
private static native void destroyIcon0(long handle);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 150337df4..4d1388eec 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -34,25 +34,19 @@
package jogamp.newt.driver.x11;
-import java.io.IOException;
-import java.net.MalformedURLException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
-import javax.media.nativewindow.util.Dimension;
-import javax.media.nativewindow.util.Point;
+import javax.media.nativewindow.util.PixelFormat;
import com.jogamp.common.nio.Buffers;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.DisplayImpl;
import jogamp.newt.NEWTJNILibLoader;
-import jogamp.newt.PointerIconImpl;
-import jogamp.newt.driver.PNGIcon;
public class DisplayDriver extends DisplayImpl {
@@ -132,16 +126,11 @@ public class DisplayDriver extends DisplayImpl {
protected Boolean isXineramaEnabled() { return isNativeValid() ? Boolean.valueOf(((X11GraphicsDevice)aDevice).isXineramaEnabled()) : null; }
@Override
- protected PointerIconImpl createPointerIconImpl(final IOUtil.ClassResources pngResource, final int hotX, final int hotY) throws MalformedURLException, InterruptedException, IOException {
- if( PNGIcon.isAvailable() ) {
- final int[] width = { 0 }, height = { 0 }, data_size = { 0 };
- if( null != pngResource && 0 < pngResource.resourceCount() ) {
- final ByteBuffer data = PNGIcon.singleToRGBAImage(pngResource, 0, false /* toBGRA */, width, height, data_size);
- final long handle = createPointerIcon0(getHandle(), data, width[0], height[0], hotX, hotY);
- return new PointerIconImpl(DisplayDriver.this, pngResource, new Dimension(width[0], height[0]), new Point(hotX, hotY), handle);
- }
- }
- return null;
+ public final PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
+ protected final long createPointerIconImpl(PixelFormat pixelformat, int width, int height, final ByteBuffer pixels, final int hotX, final int hotY) {
+ return createPointerIcon(getHandle(), pixels, width, height, hotX, hotY);
}
@Override
@@ -166,13 +155,16 @@ public class DisplayDriver extends DisplayImpl {
private native void DispatchMessages0(long display, long javaObjectAtom, long windowDeleteAtom /* , long kbdHandle */); // XKB disabled for now
- static long createPointerIcon0(long display, Buffer data, int width, int height, int hotX, int hotY) {
- if( !Buffers.isDirect(data) ) {
- throw new IllegalArgumentException("data buffer is not direct "+data);
- }
- return createPointerIcon0(display, data, Buffers.getDirectBufferByteOffset(data), width, height, hotX, hotY);
+ private static long createPointerIcon(long display, Buffer pixels, int width, int height, int hotX, int hotY) {
+ final boolean pixels_is_direct = Buffers.isDirect(pixels);
+ return createPointerIcon0(display,
+ pixels_is_direct ? pixels : Buffers.getArray(pixels),
+ pixels_is_direct ? Buffers.getDirectBufferByteOffset(pixels) : Buffers.getIndirectBufferByteOffset(pixels),
+ pixels_is_direct,
+ width, height, hotX, hotY);
}
- private static native long createPointerIcon0(long display, Object data, int data_offset, int width, int height, int hotX, int hotY);
+ private static native long createPointerIcon0(long display, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, int width, int height, int hotX, int hotY);
+
static native void destroyPointerIcon0(long display, long handle);
/** X11 Window delete atom marker used on EDT */
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index ad1744f2e..0eda37eac 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -50,6 +50,7 @@ import javax.media.nativewindow.util.Insets;
import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
+import com.jogamp.common.nio.Buffers;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsScreen;
import com.jogamp.newt.NewtFactory;
@@ -74,6 +75,7 @@ public class WindowDriver extends WindowImpl {
Buffer _icon_data=null;
if( PNGIcon.isAvailable() ) {
try {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
final int[] data_size = { 0 }, elem_bytesize = { 0 };
_icon_data = PNGIcon.arrayToX11BGRAImages(NewtFactory.getWindowIcons(), data_size, elem_bytesize);
_icon_data_size = data_size[0];
@@ -124,7 +126,7 @@ public class WindowDriver extends WindowImpl {
( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
edtDevice.lock();
try {
- setWindowHandle(CreateWindow0(getParentWindowHandle(),
+ setWindowHandle(CreateWindow(getParentWindowHandle(),
edtDevice.getHandle(), screen.getIndex(), visualID,
display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
@@ -430,10 +432,24 @@ public class WindowDriver extends WindowImpl {
protected static native boolean initIDs0();
+ private long CreateWindow(long parentWindowHandle, long display, int screen_index,
+ int visualID, long javaObjectAtom, long windowDeleteAtom,
+ int x, int y, int width, int height, boolean autoPosition, int flags,
+ int pixelDataSize, Buffer pixels) {
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ if( !Buffers.isDirect(pixels) ) {
+ throw new IllegalArgumentException("data buffer is not direct "+pixels);
+ }
+ return CreateWindow0(parentWindowHandle, display, screen_index,
+ visualID, javaObjectAtom, windowDeleteAtom,
+ x, y, width, height, autoPosition, flags,
+ pixelDataSize,
+ pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */);
+ }
private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
int visualID, long javaObjectAtom, long windowDeleteAtom,
int x, int y, int width, int height, boolean autoPosition, int flags,
- int iconDataSize, Object iconData);
+ int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct);
private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/ ); // XKB disabled for now
private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
long windowDeleteAtom, int x, int y, int width, int height, int flags);
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index 359b67b39..c6fd805a5 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -287,9 +287,8 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_stopNSApplic
[pool release];
}
-static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jiconWidth, jint jiconHeight) {
- if( NULL != jiconData ) {
- unsigned char * iconData = (unsigned char *) (*env)->GetDirectBufferAddress(env, jiconData);
+static NSImage * createNSImageFromData(JNIEnv *env, unsigned char * iconData, jint jiconWidth, jint jiconHeight) {
+ if( NULL != iconData ) {
NSInteger iconWidth = (NSInteger) jiconWidth;
NSInteger iconHeight = (NSInteger) jiconHeight;
const NSInteger bpc = 8 /* bits per component */, spp=4 /* RGBA */, bpp = bpc * spp;
@@ -319,28 +318,47 @@ static NSImage * createNSImageFromData(JNIEnv *env, jobject jiconData, jint jico
* Method: setAppIcon0
*/
JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_setAppIcon0
- (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight)
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height)
{
+ if( 0 == pixels ) {
+ return;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight);
+ // NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
if( NULL != nsImage ) {
[nsImage autorelease];
[NSApp setApplicationIconImage: nsImage];
}
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
}
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_DisplayDriver_createPointerIcon0
- (JNIEnv *env, jobject unused, jobject jiconData, jint jiconWidth, jint jiconHeight, jint hotX, jint hotY)
+ (JNIEnv *env, jobject unused, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
{
+ if( 0 == pixels ) {
+ return 0;
+ }
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
- NSImage * nsImage = createNSImageFromData(env, jiconData, jiconWidth, jiconHeight);
+ unsigned char * pixelPtr = (unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ NSImage * nsImage = createNSImageFromData(env, pixelPtr + pixels_byte_offset, width, height);
NSCursor * res = NULL;
if( NULL != nsImage ) {
[nsImage autorelease];
NSPoint hotP = { hotX, hotY };
res = [[NSCursor alloc] initWithImage: nsImage hotSpot: hotP];
}
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
[pool release];
DBG_PRINT( "createPointerIcon0 %p\n", res);
return (jlong) (intptr_t) res;
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index 1fd8d0039..c20e156c1 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -2368,9 +2368,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0
JNIEXPORT jlong JNICALL
Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, jobject _unused,
- jobject data, jint data_offset, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
+ jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jboolean isCursor, jint hotX, jint hotY) {
- const unsigned char * data_ptr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, data) + data_offset;
+ if( 0 == pixels ) {
+ return 0;
+ }
+
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
const int bytes = 4 * width * height; // BGRA8888
DWORD dwWidth, dwHeight;
@@ -2403,10 +2409,14 @@ Java_jogamp_newt_driver_windows_DisplayDriver_createBGRA8888Icon0(JNIEnv *env, j
hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
(void **)&lpBits, NULL, (DWORD)0);
- memcpy(lpBits, data_ptr, bytes);
+ memcpy(lpBits, pixelPtr + pixels_byte_offset, bytes);
ReleaseDC(NULL,hdc);
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// Create an empty mask bitmap.
HBITMAP hMonoBitmap = CreateBitmap(dwWidth,dwHeight,1,1,NULL);
diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c
index 19e733111..b62a9b234 100644
--- a/src/newt/native/X11Display.c
+++ b/src/newt/native/X11Display.c
@@ -678,13 +678,15 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
* Signature: (JJILjava/lang/Object;I)V
*/
JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerIcon0
- (JNIEnv *env, jclass clazz, jlong display, jobject data, jint data_offset, jint width, jint height, jint hotX, jint hotY)
+ (JNIEnv *env, jclass clazz, jlong display, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, jint width, jint height, jint hotX, jint hotY)
{
Cursor c;
- if( 0 != data ) {
+ if( 0 != pixels ) {
Display * dpy = (Display *) (intptr_t) display;
- char * data_ptr = (char *) (*env)->GetDirectBufferAddress(env, data) + data_offset;
+ const unsigned char * pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
XcursorImage ci;
ci.version = 1; // XCURSOR_IMAGE_VERSION;
ci.size = width; // nominal size (assume square ..)
@@ -693,11 +695,14 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_createPointerI
ci.xhot = hotX;
ci.yhot = hotY;
ci.delay = 0;
- ci.pixels = (XcursorPixel *)(intptr_t)data_ptr;
+ ci.pixels = (XcursorPixel *)(intptr_t)(pixelPtr + pixels_byte_offset);
c = XcursorImageLoadCursor (dpy, &ci);
- DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", data_ptr, width, height, hotX, hotY, (void *)c);
+ if ( JNI_FALSE == pixels_is_direct ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+ DBG_PRINT( "X11: createPointerIcon0: %p %dx%d %d/%d -> %p\n", (pixelPtr+pixels_byte_offset), width, height, hotX, hotY, (void *)c);
} else {
c = 0;
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index da2778004..54b85c243 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -512,7 +512,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
jint visualID,
jlong javaObjectAtom, jlong windowDeleteAtom,
jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
- jint iconDataSize, jobject iconData)
+ jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
{
Display * dpy = (Display *)(intptr_t)display;
Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -632,10 +632,16 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
{
XEvent event;
int left=0, right=0, top=0, bottom=0;
-
- if( 0 < iconDataSize && NULL != iconData ) {
- const unsigned char * iconDataPtr = (const unsigned char *) (*env)->GetDirectBufferAddress(env, iconData);
- NewtWindows_setIcon(dpy, window, (int)iconDataSize, iconDataPtr);
+ const unsigned char * pixelPtr = NULL;
+
+ // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
+ DBG_PRINT("X11: CreateWindow icon: size %d, pixels %p, offset %d, direct %d\n", pixelDataSize, (void*)pixels, pixels_byte_offset, pixels_is_direct);
+ if( 0 < pixelDataSize && NULL != pixels ) {
+ pixelPtr = (const unsigned char *) ( JNI_TRUE == pixels_is_direct ?
+ (*env)->GetDirectBufferAddress(env, pixels) :
+ (*env)->GetPrimitiveArrayCritical(env, pixels, NULL) );
+ DBG_PRINT("X11: CreateWindow icon: NIO %p\n", pixelPtr);
+ NewtWindows_setIcon(dpy, window, (int)pixelDataSize, pixelPtr+pixels_byte_offset);
}
XMapWindow(dpy, window);
@@ -643,6 +649,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
XSync(dpy, False);
+ if( JNI_FALSE == pixels_is_direct && NULL != pixelPtr ) {
+ (*env)->ReleasePrimitiveArrayCritical(env, pixels, (void*)pixelPtr, JNI_ABORT);
+ }
+
// send insets before visibility, allowing java code a proper sync point!
NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
(*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
index 8cc676291..780338492 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
@@ -29,6 +29,7 @@
package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
import java.io.IOException;
+import java.net.URLConnection;
import com.jogamp.common.util.IOUtil;
import com.jogamp.newt.Display;
@@ -47,6 +48,7 @@ import com.jogamp.opengl.test.junit.util.MiscUtils;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.util.Animator;
+import com.jogamp.opengl.util.PNGPixelRect;
import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
import javax.media.nativewindow.NativeWindowFactory;
@@ -171,25 +173,55 @@ public class TestGearsES2NEWT extends UITestCase {
}
});
- final PointerIcon pointerIconOne;
+ final PointerIcon[] pointerIcons = { null, null, null };
{
- PointerIcon _pointerIconOne = null;
- final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
final Display disp = glWindow.getScreen().getDisplay();
disp.createNative();
- try {
- _pointerIconOne = disp.createPointerIcon(res, 32, 0);
- } catch (Exception e) {
- e.printStackTrace();
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 16, 16);
+ System.err.println("Create PointerIcon #01: "+_pointerIcon);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[0] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 32, 0);
+ System.err.println("Create PointerIcon #02: "+_pointerIcon);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[1] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "crosshair-lumina-trans-64x64.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ System.err.println("Create PointerIcon #03: "+image);
+ _pointerIcon = disp.createPointerIcon(image, 32, 32);
+ System.err.println("Create PointerIcon #03: "+_pointerIcon);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ pointerIcons[2] = _pointerIcon;
}
- pointerIconOne = _pointerIconOne;
}
if( setPointerIcon ) {
- glWindow.setPointerIcon(pointerIconOne);
+ glWindow.setPointerIcon(pointerIcons[0]);
System.err.println("Set PointerIcon: "+glWindow.getPointerIcon());
}
glWindow.addKeyListener(new KeyAdapter() {
+ int pointerIconIdx = 0;
+
@Override
public void keyPressed(final KeyEvent e) {
if( e.isAutoRepeat() ) {
@@ -246,7 +278,14 @@ public class TestGearsES2NEWT extends UITestCase {
final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set pointer-icon pre]");
final PointerIcon currentPI = glWindow.getPointerIcon();
- glWindow.setPointerIcon( currentPI == pointerIconOne ? null : pointerIconOne);
+ final PointerIcon newPI;
+ if( pointerIconIdx >= pointerIcons.length ) {
+ newPI=null;
+ pointerIconIdx=0;
+ } else {
+ newPI=pointerIcons[pointerIconIdx++];
+ }
+ glWindow.setPointerIcon( newPI );
System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
glWindow.setExclusiveContextThread(t);
} }.start();
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java
new file mode 100644
index 000000000..bb9bc42a8
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/PNGTstFiles.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright 2014 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.jogl.util.texture;
+
+public class PNGTstFiles {
+ static public final String[] allBasenames = {
+ "test-ntscN_3-01-160x90",
+ "test-ntscN_4-01-160x90",
+ "test-ntscNG4-01-160x90",
+ "test-ntscI_3-01-160x90",
+ "test-ntscI_4-01-160x90",
+ "test-ntscIG3-01-160x90",
+ "test-ntscIG4-01-160x90",
+ "test-ntscP_3-01-160x90",
+ "test-ntscP_4-01-160x90",
+ "grayscale_texture",
+ "bug724-transparent-grey_orig",
+ "bug724-transparent-grey_gimpexp",
+ "crosshair-lumina-trans-32x32",
+ "crosshair-lumina-trans-64x64",
+ };
+ static public final String[] greyBasenames = {
+ "grayscale_texture",
+ "bug724-transparent-grey_orig",
+ "bug724-transparent-grey_gimpexp",
+ "crosshair-lumina-trans-32x32",
+ "crosshair-lumina-trans-64x64",
+ };
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java
deleted file mode 100644
index 3ace5ab6a..000000000
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage00NEWT.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Copyright 2010 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.jogl.util.texture;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URLConnection;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.FixMethodOrder;
-import org.junit.runners.MethodSorters;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.opengl.test.junit.util.UITestCase;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
-
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class TestPNGImage00NEWT extends UITestCase {
- @Test
- public void testPNGReadWriteAndCompare() throws InterruptedException, IOException, MalformedURLException {
- final File out1_f=new File(getSimpleTestName(".")+"-PNGImageTest1.png");
- final File out2_f=new File(getSimpleTestName(".")+"-PNGImageTest2.png");
- final File out2F_f=new File(getSimpleTestName(".")+"-PNGImageTest2Flipped.png");
- final File out2R_f=new File(getSimpleTestName(".")+"-PNGImageTest2Reversed.png");
- final File out2RF_f=new File(getSimpleTestName(".")+"-PNGImageTest2ReversedFlipped.png");
- final String url_s="jogl/util/data/av/test-ntsc01-57x32.png";
- URLConnection urlConn = IOUtil.getResource(url_s, this.getClass().getClassLoader());
- PNGImage image1 = PNGImage.read(urlConn.getInputStream());
- System.err.println("PNGImage - Orig: "+image1);
- image1.write(out1_f, true);
- {
- Assert.assertEquals(image1.getData(), PNGImage.read(out1_f.toURI().toURL().openStream()).getData());
- }
-
- final PNGImage image2 = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
- image1.getDpi()[0], image1.getDpi()[1],
- image1.getBytesPerPixel(), false /* reverseChannels */, image1.isGLOriented(), image1.getData());
- image2.write(out2_f, true);
- {
- Assert.assertEquals(image1.getData(), PNGImage.read(out2_f.toURI().toURL().openStream()).getData());
- }
-
- // flipped
- final PNGImage image2F = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
- image1.getDpi()[0], image1.getDpi()[1],
- image1.getBytesPerPixel(), false /* reverseChannels */, !image1.isGLOriented(), image1.getData());
- image2F.write(out2F_f, true);
-
- // reversed channels
- final PNGImage image2R = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
- image1.getDpi()[0], image1.getDpi()[1],
- image1.getBytesPerPixel(), true /* reverseChannels */, image1.isGLOriented(), image1.getData());
- image2R.write(out2R_f, true);
-
- // reversed channels and flipped
- final PNGImage image2RF = PNGImage.createFromData(image1.getWidth(), image1.getHeight(),
- image1.getDpi()[0], image1.getDpi()[1],
- image1.getBytesPerPixel(), true /* reverseChannels */, !image1.isGLOriented(), image1.getData());
- image2RF.write(out2RF_f, true);
- }
-
- public static void main(String args[]) {
- org.junit.runner.JUnitCore.main(TestPNGImage00NEWT.class.getName());
- }
-}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java
new file mode 100644
index 000000000..fc97c56fa
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect00NEWT.java
@@ -0,0 +1,224 @@
+/**
+ * Copyright 2014 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.jogl.util.texture;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPNGPixelRect00NEWT extends UITestCase {
+ @Test
+ public void testPNGRead01_All() throws InterruptedException, IOException, MalformedURLException {
+ for(int i=0; i<PNGTstFiles.allBasenames.length; i++) {
+ final String basename = PNGTstFiles.allBasenames[i];
+ final String pathname="";
+ testPNG01Impl(pathname, basename, null, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ }
+
+ @Test
+ public void testPNGRead02_RGB888_to_RGBA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead03_RGB888_to_RGBA8888_stride1000() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 1000 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead04_RGB888_to_RGBA8888_stride999() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_3-01-160x90"; // 640 bytes = 4 * 160
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 999 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead11_RGBA8888_to_LUMINA() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.LUMINANCE, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead12_RGBA8888_to_RGB888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.RGB888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead13_RGBA8888_to_BGR888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.BGR888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ @Test
+ public void testPNGRead14_RGBA8888_to_BGRA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead15_RGBA8888_to_ARGB8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead16_RGBA8888_to_ABGR8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG02Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ private void testPNG01Impl(final String pathname, final String basename,
+ final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test01: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final File out1_f=new File(getSimpleTestName(".")+"-01-"+basename+"-orig.png");
+ final File out2F_f=new File(getSimpleTestName(".")+"-02-"+basename+"-flipped.png");
+ final File out2R_f=new File(getSimpleTestName(".")+"-03-"+basename+"-reversed.png");
+ final File out2RF_f=new File(getSimpleTestName(".")+"-04-"+basename+"-reversed_flipped.png");
+ URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+ {
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */));
+ image1.write(outs, true /* close */);
+ {
+ final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R);
+ Assert.assertEquals(image1.getPixels(), image1_R.getPixels());
+ }
+ }
+
+ //
+ // Flipped Orientation
+ //
+ {
+ final PNGPixelRect image2F = new PNGPixelRect(image1.getPixelformat(), image1.getSize(),
+ image1.getStride(), !image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Flip : "+image2F);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2F_f, true /* allowOverwrite */));
+ image2F.write(outs, true /* close */);
+ {
+ // flip again .. to compare w/ original
+ final PNGPixelRect image2F_R = PNGPixelRect.read(out2F_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented);
+ System.err.println("PNGPixelRect - Flip (Read Back): "+image2F_R);
+ Assert.assertEquals(image1.getPixels(), image2F_R.getPixels());
+ }
+ }
+
+ //
+ // Reversed Components
+ //
+ final PixelFormat revFmt = PixelFormatUtil.getReversed(image1.getPixelformat());
+ {
+ final PNGPixelRect image2R = new PNGPixelRect(revFmt, image1.getSize(),
+ image1.getStride(), image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Reversed : "+image2R);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2R_f, true /* allowOverwrite */));
+ image2R.write(outs, true /* close */);
+ {
+ // reverse again .. to compare w/ original
+ final PNGPixelRect image2R_R = PNGPixelRect.read(out2R_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Reversed (Read Back): "+image2R_R);
+ Assert.assertEquals(image1.getPixels(), image2R_R.getPixels());
+ }
+ }
+
+ // reversed channels and flipped
+ {
+ final PNGPixelRect image2RF = new PNGPixelRect(revFmt, image1.getSize(),
+ image1.getStride(), !image1.isGLOriented(), image1.getPixels(),
+ image1.getDpi()[0], image1.getDpi()[1]);
+ System.err.println("PNGPixelRect - Reversed+Flipped : "+image2RF);
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out2RF_f, true /* allowOverwrite */));
+ image2RF.write(outs, true /* close */);
+ {
+ // reverse+flip again .. to compare w/ original
+ final PNGPixelRect image2RF_R = PNGPixelRect.read(out2RF_f.toURI().toURL().openStream(), revFmt, false /* directBuffer */, destMinStrideInBytes, !destIsGLOriented);
+ System.err.println("PNGPixelRect - Reversed+FLipped (Read Back): "+image2RF_R);
+ Assert.assertEquals(image1.getPixels(), image2RF_R.getPixels());
+ }
+ }
+ }
+
+ private void testPNG02Impl(final String pathname, final String basename,
+ final PixelFormat destFmt, final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test02: "+pathname+basename+".png, destFmt "+destFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final File out1_f=new File(getSimpleTestName(".")+"-"+basename+"-orig.png");
+ URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), destFmt, false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+ {
+ final OutputStream outs = new BufferedOutputStream(IOUtil.getFileOutputStream(out1_f, true /* allowOverwrite */));
+ image1.write(outs, true /* close */);
+ {
+ final PNGPixelRect image1_R = PNGPixelRect.read(out1_f.toURI().toURL().openStream(), image1.getPixelformat(), false /* directBuffer */, destMinStrideInBytes, destIsGLOriented);
+ System.err.println("PNGPixelRect - Orig (Read Back): "+image1_R);
+ Assert.assertEquals(image1.getPixels(), image1_R.getPixels());
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ org.junit.runner.JUnitCore.main(TestPNGPixelRect00NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
index 29e041908..0e92db48e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGPixelRect01NEWT.java
@@ -3,14 +3,14 @@
*
* 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
@@ -20,7 +20,7 @@
* 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.
@@ -32,6 +32,7 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URLConnection;
+import javax.media.nativewindow.util.PixelFormat;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -52,10 +53,10 @@ import com.jogamp.opengl.test.junit.util.QuitAdapter;
import com.jogamp.opengl.test.junit.util.UITestCase;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.GLReadBufferUtil;
+import com.jogamp.opengl.util.PNGPixelRect;
import com.jogamp.opengl.util.GLPixelBuffer.GLPixelAttributes;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
-import com.jogamp.opengl.util.texture.spi.PNGImage;
/**
* Test reading and displaying a PNG image.
@@ -64,71 +65,71 @@ import com.jogamp.opengl.util.texture.spi.PNGImage;
* </p>
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class TestPNGImage01NEWT extends UITestCase {
-
+public class TestPNGPixelRect01NEWT extends UITestCase {
static boolean showFPS = false;
static long duration = 200; // ms
-
- public void testImpl(final InputStream istream) throws InterruptedException, IOException {
- final PNGImage image = PNGImage.read(istream);
+
+ public void testImpl(final int num, final String basename, final InputStream istream, final PixelFormat destFmt) throws InterruptedException, IOException {
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final PNGPixelRect image = PNGPixelRect.read(istream, destFmt, true /* directBuffer */, 0 /* destMinStrideInBytes */, true /* destIsGLOriented */);
Assert.assertNotNull(image);
- final boolean hasAlpha = 4 == image.getBytesPerPixel();
- System.err.println("PNGImage: "+image);
-
+ final GLPixelAttributes glpa = GLPixelAttributes.convert(image.getPixelformat(), glp);
+ final boolean hasAlpha = 4 == glpa.bytesPerPixel;
+ System.err.println("PNGPixelRect: "+basename+", "+image+", glpa "+glpa);
+
final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false);
- final GLProfile glp = GLProfile.getGL2ES2();
final GLCapabilities caps = new GLCapabilities(glp);
if( hasAlpha ) {
caps.setAlphaBits(1);
}
-
+
final int internalFormat;
if(glp.isGL2ES3()) {
internalFormat = hasAlpha ? GL.GL_RGBA8 : GL.GL_RGB8;
} else {
internalFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB;
- }
+ }
final TextureData texData = new TextureData(glp, internalFormat,
- image.getWidth(),
- image.getHeight(),
+ image.getSize().getWidth(),
+ image.getSize().getHeight(),
0,
- new GLPixelAttributes(image.getGLFormat(), image.getGLType()),
+ glpa,
false /* mipmap */,
false /* compressed */,
false /* must flip-vert */,
- image.getData(),
+ image.getPixels(),
null);
-
+
// final TextureData texData = TextureIO.newTextureData(glp, istream, false /* mipmap */, TextureIO.PNG);
- System.err.println("TextureData: "+texData);
-
+ System.err.println("TextureData: "+texData);
+
final GLWindow glad = GLWindow.create(caps);
- glad.setTitle("TestPNGImage01NEWT");
+ glad.setTitle(this.getSimpleTestName("."));
// Size OpenGL to Video Surface
glad.setSize(texData.getWidth(), texData.getHeight());
-
+
// load texture from file inside current GL context to match the way
// the bug submitter was doing it
final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ;
// gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } );
glad.addGLEventListener(gle);
- glad.addGLEventListener(new GLEventListener() {
+ glad.addGLEventListener(new GLEventListener() {
boolean shot = false;
-
+
@Override public void init(GLAutoDrawable drawable) {
System.err.println("Chosen Caps: " + drawable.getChosenGLCapabilities());
System.err.println("GL ctx: " + drawable.getGL().getContext());
}
-
+
@Override public void display(GLAutoDrawable drawable) {
// 1 snapshot
if(null!=((TextureDraw01Accessor)gle).getTexture() && !shot) {
shot = true;
- snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null);
+ snapshot(num, basename, drawable.getGL(), screenshot, TextureIO.PNG, null);
}
}
-
+
@Override public void dispose(GLAutoDrawable drawable) { }
@Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
});
@@ -144,28 +145,43 @@ public class TestPNGImage01NEWT extends UITestCase {
while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) {
Thread.sleep(100);
}
-
+
animator.stop();
glad.destroy();
}
-
+
@Test
- public void testRead01_RGBn_exp() throws InterruptedException, IOException, MalformedURLException {
- final String fname = null == _fname ? "bug724-transparent-grey_gimpexp.png" : _fname;
- final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
- testImpl(urlConn.getInputStream());
+ public void testRead00_Manual() throws InterruptedException, IOException, MalformedURLException {
+ if( null == _fname ) {
+ return;
+ }
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), _fname);
+ testImpl(0, _fname, urlConn.getInputStream(), null);
}
@Test
- public void testRead02_RGBn_orig() throws InterruptedException, IOException, MalformedURLException {
+ public void testRead01_All() throws InterruptedException, IOException, MalformedURLException {
+ if( null != _fname ) {
+ return;
+ }
+ for(int i=0; i<PNGTstFiles.allBasenames.length; i++) {
+ final String basename = PNGTstFiles.allBasenames[i];
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png");
+ testImpl(i, basename, urlConn.getInputStream(), null);
+ }
+ }
+ @Test
+ public void testRead02_Gray2RGBA() throws InterruptedException, IOException, MalformedURLException {
if( null != _fname ) {
return;
}
- final String fname = "bug724-transparent-grey_orig.png";
- final URLConnection urlConn = IOUtil.getResource(this.getClass(), fname);
- testImpl(urlConn.getInputStream());
+ for(int i=0; i<PNGTstFiles.greyBasenames.length; i++) {
+ final String basename = PNGTstFiles.greyBasenames[i];
+ final URLConnection urlConn = IOUtil.getResource(this.getClass(), basename+".png");
+ testImpl(i, basename, urlConn.getInputStream(), PixelFormat.RGBA8888);
+ }
}
-
+
static String _fname = null;
public static void main(String args[]) {
for(int i=0; i<args.length; i++) {
@@ -177,6 +193,6 @@ public class TestPNGImage01NEWT extends UITestCase {
_fname = args[i];
}
}
- org.junit.runner.JUnitCore.main(TestPNGImage01NEWT.class.getName());
+ org.junit.runner.JUnitCore.main(TestPNGPixelRect01NEWT.class.getName());
}
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
new file mode 100644
index 000000000..bfcf9c2d7
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil00NEWT.java
@@ -0,0 +1,364 @@
+/**
+ * Copyright 2014 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.jogl.util.texture;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+import javax.media.nativewindow.util.Dimension;
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.opengl.test.junit.util.UITestCase;
+
+/**
+ * Testing PixelFormatUtil's Conversion using synthetic test data
+ * including strides, endian-order and all PixelFormat conversions.
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPixelFormatUtil00NEWT extends UITestCase {
+ @Test
+ public void testConversion01_srcS000_BE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion02_srcS000_LE_TL_destS000_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.LITTLE_ENDIAN, false /* srcIsGLOriented */,
+ 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion03_srcS000_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(0 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion04_srcS259_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(259 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testConversion05_srcS301_BE_TL_destS259_TL() throws InterruptedException, IOException, MalformedURLException {
+ testPNG00Impl(301 /* srcMinStrideInBytes */, ByteOrder.BIG_ENDIAN, false /* srcIsGLOriented */,
+ 259 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ static final byte red___val = (byte)0x01;
+ static final byte green_val = (byte)0x02;
+ static final byte blue__val = (byte)0x03;
+ static final byte alpha_val = (byte)0x04;
+ static final byte undef_val = (byte)0xff;
+
+ static final void getComponents(final int srcComps, final PixelFormat fmt, final byte[] components) {
+ final byte b1, b2, b3, b4;
+ if( 1 == srcComps ) {
+ // LUM -> Fmt Conversion
+ switch(fmt) {
+ case LUMINANCE:
+ b1 = red___val;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ break;
+ case RGB888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case BGR888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case RGBA8888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case ABGR8888:
+ b1 = undef_val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = red___val;
+ break;
+ case BGRA8888:
+ b1 = red___val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case ARGB8888:
+ b1 = undef_val;
+ b2 = red___val;
+ b3 = red___val;
+ b4 = red___val;
+ break;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ } else {
+ // 1:1 values
+ switch(fmt) {
+ case LUMINANCE:
+ if( srcComps > 1 ) {
+ b1 = ( red___val + green_val+ blue__val ) / 3;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ } else {
+ b1 = red___val;
+ b2 = undef_val;
+ b3 = undef_val;
+ b4 = undef_val;
+ }
+ break;
+ case RGB888:
+ b1 = red___val;
+ b2 = green_val;
+ b3 = blue__val;
+ b4 = undef_val;
+ break;
+ case BGR888:
+ b1 = blue__val;
+ b2 = green_val;
+ b3 = red___val;
+ b4 = undef_val;
+ break;
+ case RGBA8888:
+ b1 = red___val;
+ b2 = green_val;
+ b3 = blue__val;
+ b4 = srcComps > 3 ? alpha_val : undef_val;
+ break;
+ case ABGR8888:
+ b1 = srcComps > 3 ? alpha_val : undef_val;
+ b2 = blue__val;
+ b3 = green_val;
+ b4 = red___val;
+ break;
+ case BGRA8888:
+ b1 = blue__val;
+ b2 = green_val;
+ b3 = red___val;
+ b4 = srcComps > 3 ? alpha_val : undef_val;
+ break;
+ case ARGB8888:
+ b1 = srcComps > 3 ? alpha_val : undef_val;
+ b2 = red___val;
+ b3 = green_val;
+ b4 = blue__val;
+ break;
+ default:
+ throw new InternalError("Unhandled format "+fmt);
+ }
+ }
+ components[0] = b1;
+ components[1] = b2;
+ components[2] = b3;
+ components[3] = b4;
+ }
+ private void testPNG00Impl(final int srcMinStrideInBytes, final ByteOrder srcByteOrder, final boolean srcIsGLOriented,
+ final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test00: srcMinStrideInBytes "+srcMinStrideInBytes+", srcByteOrder "+srcByteOrder+", srcIsGLOriented "+srcIsGLOriented+
+ ", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ final PixelFormat[] formats = PixelFormat.values();
+ final int width = 64, height = 64;
+
+ for(int i=0; i<formats.length; i++) {
+ final PixelFormat srcFmt = formats[i];
+ final int srcBpp = srcFmt.bytesPerPixel();
+ final int srcStrideBytes = Math.max(srcMinStrideInBytes, width*srcBpp);
+ final ByteBuffer srcPixels = ByteBuffer.allocate(height*srcStrideBytes).order(srcByteOrder);
+ final byte[] srcComponents = new byte[4];
+ getComponents(srcFmt.componentCount, srcFmt, srcComponents);
+ for(int y=0; y<height; y++) {
+ int o = y*srcStrideBytes;
+ for(int x=0; x<width; x++) {
+ switch(srcFmt) {
+ case LUMINANCE:
+ srcPixels.put(o++, srcComponents[0]);
+ break;
+ case RGB888:
+ case BGR888:
+ srcPixels.put(o++, srcComponents[0]);
+ srcPixels.put(o++, srcComponents[1]);
+ srcPixels.put(o++, srcComponents[2]);
+ break;
+ case RGBA8888:
+ case ABGR8888:
+ case BGRA8888:
+ case ARGB8888:
+ srcPixels.put(o++, srcComponents[0]);
+ srcPixels.put(o++, srcComponents[1]);
+ srcPixels.put(o++, srcComponents[2]);
+ srcPixels.put(o++, srcComponents[3]);
+ break;
+ default:
+ throw new InternalError("Unhandled format "+srcFmt);
+ }
+ }
+ }
+ final PixelRectangle imageSrc = new PixelRectangle.GenericPixelRect(srcFmt, new Dimension(width, height), srcStrideBytes, srcIsGLOriented, srcPixels);
+ System.err.println("CONVERT["+i+"][*]: Image0 - Orig: "+imageSrc);
+ testComponents(imageSrc, 0, 0, srcComponents);
+ testComponents(imageSrc, width-1, height-1, srcComponents);
+
+ for(int j=0; j<formats.length; j++) {
+ final PixelFormat destFmt = formats[j];
+ System.err.println("CONVERT["+i+"]["+j+"]: "+srcFmt+" -> "+destFmt);
+
+ final int destStrideBytes = Math.max(destMinStrideInBytes, width*destFmt.bytesPerPixel());
+ final byte[] destComponents = new byte[4];
+ getComponents(srcFmt.componentCount, destFmt, destComponents);
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert32(imageSrc, destFmt, destStrideBytes, destIsGLOriented, false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv1: "+imageConv1);
+ testComponents(imageConv1, 0, 0, destComponents);
+ testComponents(imageConv1, width-1, height-1, destComponents);
+ if( PixelFormat.LUMINANCE != srcFmt && PixelFormat.LUMINANCE == destFmt ) {
+ // Cannot convert: RGB* -> LUM -> RGB*
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to RGB* -> LUM");
+ } else if( srcFmt.componentCount > destFmt.componentCount ) {
+ // Cannot convert back if: src.componentCount > dest.componentCount
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: Dropped due to src.componentCount > dest.componentCount");
+ } else {
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, imageSrc.getPixelformat(), imageSrc.getStride(), imageSrc.isGLOriented(), false /* nio */);
+ System.err.println("CONVERT["+i+"]["+j+"]: Conv2: "+imageConv2);
+ testComponents(imageConv2, 0, 0, srcComponents);
+ testComponents(imageConv2, width-1, height-1, srcComponents);
+ if( imageSrc.getStride() == imageConv1.getStride() ) {
+ Assert.assertEquals(imageSrc.getPixels(), imageConv2.getPixels());
+ }
+ }
+ }
+ }
+ }
+ private void dumpComponents(PixelRectangle image, int x1, int y1, int w, int h) {
+ if( x1 + w >= image.getSize().getWidth() ) {
+ x1 = image.getSize().getWidth() - w;
+ }
+ if( y1 + h >= image.getSize().getHeight() ) {
+ y1 = image.getSize().getHeight() - h;
+ }
+ System.err.print("PixelsBytes "+x1+"/"+y1+" "+w+"x"+h+":");
+ final ByteBuffer bb = image.getPixels();
+ final int bpp = image.getPixelformat().bytesPerPixel();
+ for(int y = y1; y< y1+h; y++) {
+ System.err.printf("%n[%3d][%3d] ", x1, y);
+ int o = y * image.getStride()+x1*bpp;
+ for(int x = x1; x< x1+w; x++) {
+ switch(bpp) {
+ case 1: {
+ final byte a = bb.get(o++);
+ System.err.printf(" 0x%02X", a);
+ }
+ break;
+ case 2: {
+ final byte a = bb.get(o++), b = bb.get(o++);
+ System.err.printf(" 0x%02X%02X", b, a);
+ }
+ break;
+ case 3: {
+ final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++);
+ System.err.printf(" 0x%02X%02X%02X", c, b, a);
+ }
+ break;
+ case 4: {
+ final byte a = bb.get(o++), b = bb.get(o++), c = bb.get(o++), d = bb.get(o++);
+ System.err.printf(" 0x%02X%02X%02X%02X", d, c, b, a);
+ }
+ break;
+ }
+ }
+ }
+ System.err.println();
+ }
+ private void testComponents(PixelRectangle image, int x, int y, byte[] components) {
+ dumpComponents(image, x, y, 3, 3);
+ final ByteBuffer bb = image.getPixels();
+ final int bpp = image.getPixelformat().bytesPerPixel();
+ int o = y * image.getStride()+x*bpp;
+ switch(bpp) {
+ case 1: {
+ final byte c1 = bb.get(o++);
+ final boolean equal = c1==components[0];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X == has 0x%02X : %b%n",
+ x, y, components[0], c1, equal );
+ Assert.assertEquals(components[0], c1);
+ }
+ break;
+ case 2: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X == has 0x%02X%02X : %b%n",
+ x, components[1], components[0], c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ }
+ break;
+ case 3: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1] && c3==components[2];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X == has 0x%02X%02X%02X : %b%n",
+ x, y, components[2], components[1], components[0], c3, c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ Assert.assertEquals(components[2], c3);
+ }
+ break;
+ case 4: {
+ final byte c1 = bb.get(o++), c2 = bb.get(o++), c3 = bb.get(o++), c4 = bb.get(o++);
+ final boolean equal = c1==components[0] && c2==components[1] && c3==components[2] && c4==components[3];
+ System.err.printf("Test [%3d][%3d] exp 0x%02X%02X%02X%02X == has 0x%02X%02X%02X%02X : %b%n",
+ x, y, components[3], components[2], components[1], components[0], c4, c3, c2, c1, equal );
+ Assert.assertEquals(components[0], c1);
+ Assert.assertEquals(components[1], c2);
+ Assert.assertEquals(components[2], c3);
+ Assert.assertEquals(components[3], c4);
+ }
+ break;
+ }
+ }
+
+ public static void main(String args[]) {
+ org.junit.runner.JUnitCore.main(TestPixelFormatUtil00NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
new file mode 100644
index 000000000..f54861371
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPixelFormatUtil01NEWT.java
@@ -0,0 +1,105 @@
+/**
+ * Copyright 2014 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.jogl.util.texture;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URLConnection;
+
+import javax.media.nativewindow.util.PixelFormat;
+import javax.media.nativewindow.util.PixelFormatUtil;
+import javax.media.nativewindow.util.PixelRectangle;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+/**
+ * Testing PixelFormatUtil's Conversion using PNG test data
+ * including strides, endian-order and PixelFormat conversions:
+ * { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 }
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestPixelFormatUtil01NEWT extends UITestCase {
+ @Test
+ public void testPNGRead11_fromRGBA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.RGBA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead12_fromABGR8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.ABGR8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead13_fromBGRA8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.BGRA8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+ @Test
+ public void testPNGRead14_fromARGB8888() throws InterruptedException, IOException, MalformedURLException {
+ final String basename ="test-ntscN_4-01-160x90";
+ final String pathname="";
+ testPNG01Impl(pathname, basename, PixelFormat.ARGB8888, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ }
+
+ private void testPNG01Impl(final String pathname, final String basename, final PixelFormat srcFmt,
+ final int destMinStrideInBytes, final boolean destIsGLOriented)
+ throws InterruptedException, IOException, MalformedURLException
+ {
+ System.err.println("Test01: "+pathname+basename+".png, srcFmt "+srcFmt+", destMinStrideInBytes "+destMinStrideInBytes+", destIsGLOriented "+destIsGLOriented);
+
+ URLConnection urlConn = IOUtil.getResource(this.getClass(), pathname+basename+".png");
+
+ final PNGPixelRect image1 = PNGPixelRect.read(urlConn.getInputStream(), srcFmt, false /* directBuffer */, destMinStrideInBytes, false /* isGLOriented */);
+ System.err.println("PNGPixelRect - Orig: "+image1);
+
+ final PixelFormat[] formats = new PixelFormat[] { PixelFormat.RGBA8888, PixelFormat.ABGR8888, PixelFormat.BGRA8888, PixelFormat.ARGB8888 };
+ for(int i=0; i<formats.length; i++) {
+ final PixelFormat destFmt = formats[i];
+ System.err.println("CONVERT["+i+"]: "+srcFmt+" -> "+destFmt);
+ final PixelRectangle imageConv1 = PixelFormatUtil.convert32(image1, destFmt, destMinStrideInBytes, destIsGLOriented, false /* nio */);
+ System.err.println("PNGPixelRect - Conv1: "+imageConv1);
+ final PixelRectangle imageConv2 = PixelFormatUtil.convert32(imageConv1, image1.getPixelformat(), image1.getStride(), image1.isGLOriented(), false /* nio */);
+ System.err.println("PNGPixelRect - Conv2: "+imageConv2);
+ Assert.assertEquals(image1.getPixels(), imageConv2.getPixels());
+ }
+ }
+
+ public static void main(String args[]) {
+ org.junit.runner.JUnitCore.main(TestPixelFormatUtil01NEWT.class.getName());
+ }
+}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png
new file mode 100644
index 000000000..92279640b
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-32x32.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png
new file mode 100644
index 000000000..9be285335
--- /dev/null
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/crosshair-lumina-trans-64x64.png
Binary files differ
diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
index 69874df6b..70d01ae66 100644
--- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
+++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
@@ -28,25 +28,27 @@
package com.jogamp.opengl.test.junit.newt.parenting;
import java.awt.Frame;
+import java.net.URLConnection;
import javax.media.nativewindow.util.InsetsImmutable;
import com.jogamp.common.util.IOUtil;
import com.jogamp.newt.Display;
-import com.jogamp.newt.Window;
import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.test.junit.util.QuitAdapter;
+import com.jogamp.opengl.util.PNGPixelRect;
public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
final Frame frame;
final NewtCanvasAWT newtCanvasAWT;
final GLWindow glWindow;
final QuitAdapter quitAdapter;
- PointerIcon pointerIconTest = null;
+ PointerIcon[] pointerIcons = null;
+ int pointerIconIdx = 0;
public NewtAWTReparentingKeyAdapter(Frame frame, NewtCanvasAWT newtCanvasAWT, GLWindow glWindow, QuitAdapter quitAdapter) {
this.frame = frame;
@@ -144,13 +146,46 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
}
} }.start();
} else if(e.getKeySymbol() == KeyEvent.VK_C ) {
- if( null == pointerIconTest ) {
- final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/jogamp-32x32.png" } );
- final Display disp = glWindow.getScreen().getDisplay();
- try {
- pointerIconTest = disp.createPointerIcon(res, 16, 0);
- } catch (Exception err) {
- err.printStackTrace();
+ if( null == pointerIcons ) {
+ {
+ pointerIcons = new PointerIcon[3];
+ final Display disp = glWindow.getScreen().getDisplay();
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/crosshair-lumina-trans-32x32.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 16, 16);
+ System.err.println("Create PointerIcon #01: "+_pointerIcon);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[0] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 32, 0);
+ System.err.println("Create PointerIcon #02: "+_pointerIcon);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[1] = _pointerIcon;
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "crosshair-lumina-trans-64x64.png" } );
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ System.err.println("Create PointerIcon #03: "+image);
+ _pointerIcon = disp.createPointerIcon(image, 32, 32);
+ System.err.println("Create PointerIcon #03: "+_pointerIcon);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ pointerIcons[2] = _pointerIcon;
+ }
}
}
new Thread() {
@@ -158,7 +193,14 @@ public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
final Thread t = glWindow.setExclusiveContextThread(null);
System.err.println("[set pointer-icon pre]");
final PointerIcon currentPI = glWindow.getPointerIcon();
- glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest);
+ final PointerIcon newPI;
+ if( pointerIconIdx >= pointerIcons.length ) {
+ newPI=null;
+ pointerIconIdx=0;
+ } else {
+ newPI=pointerIcons[pointerIconIdx++];
+ }
+ glWindow.setPointerIcon( newPI );
System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
glWindow.setExclusiveContextThread(t);
} }.start();