diff options
author | JOGAMP DEV TEAM <[email protected]> | 2010-04-22 21:12:36 -0400 |
---|---|---|
committer | JOGAMP DEV TEAM <[email protected]> | 2010-04-22 21:12:36 -0400 |
commit | 1d889ddc4728d1534e310b44fad74a2932d22d39 (patch) | |
tree | 4ad0c3eeb3ef728522ac9459eb12c667301a0c32 /src/jogl/classes/com/jogamp | |
parent | 8790075f074013aa3c71b96993838cf1117275f1 (diff) | |
parent | a588326d206ff32e5ff5db97560851cb9b826022 (diff) |
Merge branch 'master' of github.com:sgothel/jogl
Diffstat (limited to 'src/jogl/classes/com/jogamp')
289 files changed, 88281 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java new file mode 100755 index 000000000..2b51be164 --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Audio.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +import java.io.*; + +public class Audio { + private static Audio instance = null; + private Mixer mixer; + + public synchronized static Audio getInstance() { + if (instance == null) { + instance = new Audio(); + } + return instance; + } + + private Audio() { + mixer = Mixer.getMixer(); + } + + public Mixer getMixer() { + return mixer; + } + + public Track newTrack(File file) throws IOException + { + Track res = new Track(file); + mixer.add(res); + return res; + } + + public void shutdown() { + mixer.shutdown(); + } +} diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java new file mode 100755 index 000000000..60972873e --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Mixer.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +import java.io.*; +import java.nio.*; +import java.util.*; + +// Needed only for NIO workarounds on CVM +import java.lang.reflect.*; + +public class Mixer { + // This class is a singleton + private static Mixer mixer; + + private volatile boolean shutdown; + private volatile Object shutdownLock = new Object(); + private volatile boolean shutdownDone; + + // Windows Event object + private long event; + + private volatile ArrayList/*<Track>*/ tracks = new ArrayList(); + + private Vec3f leftSpeakerPosition = new Vec3f(-1, 0, 0); + private Vec3f rightSpeakerPosition = new Vec3f( 1, 0, 0); + + private float falloffFactor = 1.0f; + + static { + mixer = new Mixer(); + } + + private Mixer() { + event = CreateEvent(); + new FillerThread().start(); + MixerThread m = new MixerThread(); + m.setPriority(Thread.MAX_PRIORITY - 1); + m.start(); + } + + public static Mixer getMixer() { + return mixer; + } + + synchronized void add(Track track) { + ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone(); + newTracks.add(track); + tracks = newTracks; + } + + synchronized void remove(Track track) { + ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone(); + newTracks.remove(track); + tracks = newTracks; + } + + // NOTE: due to a bug on the APX device, we only have mono sounds, + // so we currently only pay attention to the position of the left + // speaker + public void setLeftSpeakerPosition(float x, float y, float z) { + leftSpeakerPosition.set(x, y, z); + } + + // NOTE: due to a bug on the APX device, we only have mono sounds, + // so we currently only pay attention to the position of the left + // speaker + public void setRightSpeakerPosition(float x, float y, float z) { + rightSpeakerPosition.set(x, y, z); + } + + /** This defines a scale factor of sorts -- the higher the number, + the larger an area the sound will affect. Default value is + 1.0f. Valid values are [1.0f, ...]. The formula for the gain + for each channel is +<PRE> + falloffFactor + ------------------- + falloffFactor + r^2 +</PRE> +*/ + public void setFalloffFactor(float factor) { + falloffFactor = factor; + } + + public void shutdown() { + synchronized(shutdownLock) { + shutdown = true; + SetEvent(event); + try { + shutdownLock.wait(); + } catch (InterruptedException e) { + } + } + } + + class FillerThread extends Thread { + FillerThread() { + super("Mixer Thread"); + } + + public void run() { + while (!shutdown) { + List/*<Track>*/ curTracks = tracks; + + for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) { + Track track = (Track) iter.next(); + try { + track.fill(); + } catch (IOException e) { + e.printStackTrace(); + remove(track); + } + } + + try { + // Run ten times per second + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + class MixerThread extends Thread { + // Temporary mixing buffer + // Interleaved left and right channels + float[] mixingBuffer; + private Vec3f temp = new Vec3f(); + + MixerThread() { + super("Mixer Thread"); + if (!initializeWaveOut(event)) { + throw new InternalError("Error initializing waveout device"); + } + } + + public void run() { + while (!shutdown) { + // Get the next buffer + long mixerBuffer = getNextMixerBuffer(); + if (mixerBuffer != 0) { + ByteBuffer buf = getMixerBufferData(mixerBuffer); + + if (buf == null) { + // This is happening on CVM because + // JNI_NewDirectByteBuffer isn't implemented + // by default and isn't compatible with the + // JSR-239 NIO implementation (apparently) + buf = newDirectByteBuffer(getMixerBufferDataAddress(mixerBuffer), + getMixerBufferDataCapacity(mixerBuffer)); + } + + if (buf == null) { + throw new InternalError("Couldn't wrap the native address with a direct byte buffer"); + } + + // System.out.println("Mixing buffer"); + + // If we don't have enough samples in our mixing buffer, expand it + // FIXME: knowledge of native output rendering format + if ((mixingBuffer == null) || (mixingBuffer.length < (buf.capacity() / 2 /* bytes / sample */))) { + mixingBuffer = new float[buf.capacity() / 2]; + } else { + // Zap it + for (int i = 0; i < mixingBuffer.length; i++) { + mixingBuffer[i] = 0.0f; + } + } + + // This assertion should be in place if we have stereo + if ((mixingBuffer.length % 2) != 0) { + String msg = "FATAL ERROR: odd number of samples in the mixing buffer"; + System.out.println(msg); + throw new InternalError(msg); + } + + // Run down all of the registered tracks mixing them in + List/*<Track>*/ curTracks = tracks; + + for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) { + Track track = (Track) iter.next(); + // Consider only playing tracks + if (track.isPlaying()) { + // First recompute its gain + Vec3f pos = track.getPosition(); + float leftGain = gain(pos, leftSpeakerPosition); + float rightGain = gain(pos, rightSpeakerPosition); + // Now mix it in + int i = 0; + while (i < mixingBuffer.length) { + if (track.hasNextSample()) { + float sample = track.nextSample(); + mixingBuffer[i++] = sample * leftGain; + mixingBuffer[i++] = sample * rightGain; + } else { + // This allows tracks to stall without being abruptly cancelled + if (track.done()) { + remove(track); + } + break; + } + } + } + } + + // Now that we have our data, send it down to the card + int outPos = 0; + for (int i = 0; i < mixingBuffer.length; i++) { + short val = (short) mixingBuffer[i]; + buf.put(outPos++, (byte) val); + buf.put(outPos++, (byte) (val >> 8)); + } + if (!prepareMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error preparing mixer buffer"); + } + if (!writeMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error writing mixer buffer to device"); + } + } else { + // System.out.println("No mixer buffer available"); + + // Wait for a buffer to become available + if (!WaitForSingleObject(event)) { + throw new RuntimeException("Error while waiting for event object"); + } + + /* + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + */ + } + } + + // Need to shut down + shutdownWaveOut(); + synchronized(shutdownLock) { + shutdownLock.notifyAll(); + } + } + + // This defines the 3D spatialization gain function. + // The function is defined as: + // falloffFactor + // ------------------- + // falloffFactor + r^2 + private float gain(Vec3f pos, Vec3f speakerPos) { + temp.sub(pos, speakerPos); + float dotp = temp.dot(temp); + return (falloffFactor / (falloffFactor + dotp)); + } + } + + // Initializes waveout device + private static native boolean initializeWaveOut(long eventObject); + // Shuts down waveout device + private static native void shutdownWaveOut(); + + // Gets the next (opaque) buffer of data to fill from the native + // code, or 0 if none was available yet (it should not happen that + // none is available the way the code is written). + private static native long getNextMixerBuffer(); + // Gets the next ByteBuffer to fill out of the mixer buffer. It + // requires interleaved left and right channel samples, 16 signed + // bits per sample, little endian. Implicit 44.1 kHz sample rate. + private static native ByteBuffer getMixerBufferData(long mixerBuffer); + // We need these to work around the lack of + // JNI_NewDirectByteBuffer in CVM + the JSR 239 NIO classes + private static native long getMixerBufferDataAddress(long mixerBuffer); + private static native int getMixerBufferDataCapacity(long mixerBuffer); + // Prepares this mixer buffer for writing to the device. + private static native boolean prepareMixerBuffer(long mixerBuffer); + // Writes this mixer buffer to the device. + private static native boolean writeMixerBuffer(long mixerBuffer); + + // Helpers to prevent mixer thread from busy waiting + private static native long CreateEvent(); + private static native boolean WaitForSingleObject(long event); + private static native void SetEvent(long event); + private static native void CloseHandle(long handle); + + // We need a reflective hack to wrap a direct ByteBuffer around + // the native memory because JNI_NewDirectByteBuffer doesn't work + // in CVM + JSR-239 NIO + private static Class directByteBufferClass; + private static Constructor directByteBufferConstructor; + private static Map createdBuffers = new HashMap(); // Map Long, ByteBuffer + + private static ByteBuffer newDirectByteBuffer(long address, long capacity) { + Long key = new Long(address); + ByteBuffer buf = (ByteBuffer) createdBuffers.get(key); + if (buf == null) { + buf = newDirectByteBufferImpl(address, capacity); + if (buf != null) { + createdBuffers.put(key, buf); + } + } + return buf; + } + private static ByteBuffer newDirectByteBufferImpl(long address, long capacity) { + if (directByteBufferClass == null) { + try { + directByteBufferClass = Class.forName("java.nio.DirectByteBuffer"); + byte[] tmp = new byte[0]; + directByteBufferConstructor = + directByteBufferClass.getDeclaredConstructor(new Class[] { Integer.TYPE, + tmp.getClass(), + Integer.TYPE }); + directByteBufferConstructor.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (directByteBufferConstructor != null) { + try { + return (ByteBuffer) + directByteBufferConstructor.newInstance(new Object[] { + new Integer((int) capacity), + null, + new Integer((int) address) + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java new file mode 100755 index 000000000..c45430d23 --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/SoundBuffer.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +import java.io.*; + +class SoundBuffer { + private byte[] data; + private boolean needsByteSwap; + private int numBytes; + private int bytesPerSample; + private int numSamples; + private boolean playing; + private boolean empty; + + // Note: needsByteSwap argument makes assumptions about the format + SoundBuffer(int size, int bytesPerSample, boolean needsByteSwap) { + this.bytesPerSample = bytesPerSample; + this.needsByteSwap = needsByteSwap; + data = new byte[size * bytesPerSample]; + empty = true; + } + + boolean playing() { + return playing; + } + + void playing(boolean playing) { + this.playing = playing; + } + + boolean empty() { + return empty; + } + + void empty(boolean empty) { + this.empty = empty; + } + + void fill(InputStream input) throws IOException { + synchronized(this) { + if (playing) { + throw new IllegalStateException("Can not fill a buffer that is playing"); + } + } + + empty(true); + int num = input.read(data); + if (num > 0) { + numBytes = num; + numSamples = numBytes / bytesPerSample; + empty(false); + if ((numBytes % bytesPerSample) != 0) { + System.out.println("WARNING: needed integral multiple of " + bytesPerSample + + " bytes, but read " + numBytes + " bytes"); + } + } else { + numBytes = 0; + } + } + + int numSamples() { + return numSamples; + } + + // This is called by the mixer and must be extremely fast + // FIXME: may want to reconsider use of floating point at this point + // FIXME: assumes all sounds are of the same format to avoid normalization + float getSample(int sample) { + int startByte = sample * bytesPerSample; + // FIXME: assumes no more than 4 bytes per sample + int res = 0; + if (needsByteSwap) { + for (int i = startByte + bytesPerSample - 1; i >= startByte; i--) { + res <<= 8; + res |= (data[i] & 0xff); + } + } else { + int endByte = startByte + bytesPerSample - 1; + for (int i = startByte; i <= endByte; i++) { + res <<= 8; + res |= (data[i] & 0xff); + } + } + // Sign extend + if (bytesPerSample == 2) { + res = (short) res; + } else if (bytesPerSample == 1) { + res = (byte) res; + } + + return (float) res; + } +} diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java new file mode 100755 index 000000000..78fb3493f --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/TestSpatialization.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +import java.io.*; +import javax.media.nativewindow.NativeWindow; +import javax.media.opengl.GLDrawableFactory; + +public class TestSpatialization { + public static void main(String[] args) { + if (args.length != 1) { + System.out.println("Usage: TestSpatialization [file name]"); + System.exit(1); + } + + try { + // FIXME: this is a hack to get the native library loaded + try { + GLDrawableFactory.getFactory(NativeWindow.class); + } catch (Exception e) {} + // Initialize the audio subsystem + Audio audio = Audio.getInstance(); + // Create a track + Track track = audio.newTrack(new File(args[0])); + track.setPosition(1, 0, 0); + // Run for ten seconds + long startTime = System.currentTimeMillis(); + long duration = 10000; + long curTime = 0; + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + System.out.println("Playing..."); + track.setLooping(true); + track.play(); + while ((curTime = System.currentTimeMillis()) < startTime + duration) { + // Make one revolution every two seconds + float rads = (float) (((2 * Math.PI) * (((float) (curTime - startTime)) / 1000.0f)) / 2); + track.setPosition((float) Math.cos(rads), 0, (float) Math.sin(rads)); + // Would like to make it go in a circle, but since + // stereo doesn't work now, make it move along a line + // track.setPosition(-1.0f, 0, 2.0f * (float) Math.sin(rads)); + // Sleep a little between updates + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + } + System.out.println("Shutting down audio subsystem"); + audio.shutdown(); + System.out.println("Exiting."); + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } +} diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java new file mode 100755 index 000000000..b57bf1dc6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Track.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +import java.io.*; +import java.nio.*; + +public class Track { + // Default number of samples per buffer + private static final int BUFFER_SIZE = 32768; + // Number of bytes per sample (FIXME: dependence on audio format) + static final int BYTES_PER_SAMPLE = 2; + // Whether we need byte swapping (FIXME: dependence on audio format) + static final boolean NEEDS_BYTE_SWAP = true; + + // This is the buffer this track is currently playing from + private SoundBuffer activeBuffer; + // This is the sample position in the active buffer + private int samplePosition; + // This is the total number of samples in the file + private int totalSamples; + // This is the total number of samples we have read + private int samplesRead; + // This is the buffer that the background filler thread may be filling + private SoundBuffer fillingBuffer; + // If we're playing the file, this is its input stream + private InputStream input; + // Keep around the file name + private File file; + // Whether we're playing this sound + private boolean playing; + // Whether we're looping this sound + private boolean looping; + // The position of this sound; defaults to being at the origin + private volatile Vec3f position = new Vec3f(); + + Track(File file) throws IOException { + if (!file.getName().endsWith(".rawsound")) { + throw new IOException("Unsupported file format (currently supports only raw sounds)"); + } + + this.file = file; + openInput(); + + // Allocate the buffers + activeBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP); + fillingBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP); + + // Fill the first buffer immediately + fill(); + swapBuffers(); + } + + private void openInput() throws IOException { + input = new BufferedInputStream(new FileInputStream(file)); + totalSamples = (int) file.length() / BYTES_PER_SAMPLE; + } + + public File getFile() { + return file; + } + + public synchronized void play() { + if (input == null) { + try { + openInput(); + // Fill it immediately + fill(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + } + + playing = true; + } + + public synchronized boolean isPlaying() { + return playing; + } + + public synchronized void setLooping(boolean looping) { + this.looping = looping; + } + + public synchronized boolean isLooping() { + return looping; + } + + public void setPosition(float x, float y, float z) { + position = new Vec3f(x, y, z); + } + + synchronized void fill() throws IOException { + if (input == null) { + return; + } + SoundBuffer curBuffer = fillingBuffer; + if (!curBuffer.empty()) { + return; + } + curBuffer.fill(input); + if (curBuffer.empty()) { + // End of file + InputStream tmp = null; + synchronized(this) { + tmp = input; + input = null; + } + tmp.close(); + + // If looping, re-open + if (isLooping()) { + openInput(); + // and fill + fill(); + } + } + } + + // These are only for use by the Mixer + private float leftGain; + private float rightGain; + + void setLeftGain(float leftGain) { + this.leftGain = leftGain; + } + + float getLeftGain() { + return leftGain; + } + + void setRightGain(float rightGain) { + this.rightGain = rightGain; + } + + float getRightGain() { + return rightGain; + } + + Vec3f getPosition() { + return position; + } + + // This is called by the mixer and must be extremely fast + // Note this assumes mono sounds (FIXME) + boolean hasNextSample() { + return (!activeBuffer.empty() && samplePosition < activeBuffer.numSamples()); + } + + // This is called by the mixer and must be extremely fast + float nextSample() { + float res = activeBuffer.getSample(samplePosition++); + ++samplesRead; + if (!hasNextSample()) { + swapBuffers(); + samplePosition = 0; + if (done()) { + playing = false; + } + } + return res; + } + + synchronized void swapBuffers() { + SoundBuffer tmp = activeBuffer; + activeBuffer = fillingBuffer; + fillingBuffer = tmp; + fillingBuffer.empty(true); + } + + // This provides a more robust termination condition + boolean done() { + return (samplesRead == totalSamples) && !looping; + } +} diff --git a/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java b/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java new file mode 100755 index 000000000..1afdaf081 --- /dev/null +++ b/src/jogl/classes/com/jogamp/audio/windows/waveout/Vec3f.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.audio.windows.waveout; + +/** 3-element single-precision vector */ + +class Vec3f { + public static final Vec3f X_AXIS = new Vec3f( 1, 0, 0); + public static final Vec3f Y_AXIS = new Vec3f( 0, 1, 0); + public static final Vec3f Z_AXIS = new Vec3f( 0, 0, 1); + public static final Vec3f NEG_X_AXIS = new Vec3f(-1, 0, 0); + public static final Vec3f NEG_Y_AXIS = new Vec3f( 0, -1, 0); + public static final Vec3f NEG_Z_AXIS = new Vec3f( 0, 0, -1); + + private float x; + private float y; + private float z; + + public Vec3f() {} + + public Vec3f(Vec3f arg) { + set(arg); + } + + public Vec3f(float x, float y, float z) { + set(x, y, z); + } + + public Vec3f copy() { + return new Vec3f(this); + } + + public void set(Vec3f arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + + public float dot(Vec3f arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3f times(float val) { + Vec3f tmp = new Vec3f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3f plus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3f a, Vec3f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3f addScaled(float s, Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3f a, float s, Vec3f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3f minus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3f a, Vec3f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3f cross(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3f a, Vec3f b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec3f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/cg/CgException.java b/src/jogl/classes/com/jogamp/opengl/cg/CgException.java new file mode 100644 index 000000000..8bfd9e23e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/cg/CgException.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.cg; + +/** + * A generic exception for errors that occur throughout the NVidia Cg + * binding, as a substitute for {@link RuntimeException}. + */ +public class CgException extends RuntimeException { + /** Constructs a CgException object. */ + public CgException() { + super(); + } + + /** Constructs a CgException object with the specified detail message. */ + public CgException(String message) { + super(message); + } + + /** Constructs a CgException object with the specified detail message and + root cause. */ + public CgException(String message, Throwable cause) { + super(message, cause); + } + + /** Constructs a CgException object with the specified root cause. */ + public CgException(Throwable cause) { + super(cause); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java b/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java new file mode 100755 index 000000000..7e81d194b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/DRIHack.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.NativeLibrary; +import com.jogamp.common.os.Platform; +import java.io.*; +import java.security.*; + +/** + * Helper class for working around problems with open-source DRI + * drivers. In the current DRI implementation it is required that the + * symbols in libGL.so.1.2 be globally visible to be accessible from + * other libraries that are dynamically loaded by the implementation. + * Applications may typically satisfy this need either by linking + * against libGL.so on the command line (-lGL) or by dlopen'ing + * libGL.so.1.2 with the RTLD_GLOBAL flag. The JOGL implementation + * links against libGL on all platforms rather than forcing all OpenGL + * entry points to be called through a function pointer. This allows + * the JOGL library to link directly to core 1.1 OpenGL entry points + * like glVertex3f, while calling through function pointers for entry + * points from later OpenGL versions as well as from + * extensions. However, because libjogl.so (which links against + * libGL.so) is loaded by the JVM, and because the JVM implicitly uses + * RTLD_LOCAL in the implementation of System.loadLibrary(), this + * means via transitivity that the symbols for libGL.so have only + * RTLD_LOCAL visibility to the rest of the application, so the DRI + * drivers can not find the symbols required. <P> + * + * There are at least two possible solutions. One would be to change + * the JOGL implementation to call through function pointers uniformly + * so that it does not need to link against libGL.so. This is + * possible, but requires changes to GlueGen and also is not really + * necessary in any other situation than with the DRI drivers. Another + * solution is to force the first load of libGL.so.1.2 to be done + * dynamically with RTLD_GLOBAL before libjogl.so is loaded and causes + * libGL.so.1.2 to be loaded again. The NativeLibrary class in the + * GlueGen runtime has this property, and we use it to implement this + * workaround. + */ + +public class DRIHack { + + private static final boolean DEBUG = Debug.debug("DRIHack"); + private static boolean driHackNeeded; + private static NativeLibrary oglLib; + + static { + // Allow manual overriding for now as a workaround for + // problems seen in some situations -- needs more investigation + if (Debug.getProperty("jogl.drihack.disable", true) != null) { + driHackNeeded = false; + } else { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String os = Platform.getOS().toLowerCase(); + // Do DRI hack on all Linux distributions for best robustness + driHackNeeded = os.startsWith("linux") + || new File("/usr/lib/dri").exists() + || new File("/usr/X11R6/lib/modules/dri").exists(); + return null; + } + }); + } + } + + public static void begin() { + + if (driHackNeeded) { + if (DEBUG) { + System.err.println("Beginning DRI hack"); + } + + // Try a few different variants for best robustness + // In theory probably only the first is necessary + oglLib = NativeLibrary.open("libGL.so.1", null); + if (DEBUG && oglLib != null) { + System.err.println(" Found libGL.so.1"); + } + if (oglLib == null) { + oglLib = NativeLibrary.open("/usr/lib/libGL.so.1", null); + if (DEBUG && oglLib != null) { + System.err.println(" Found /usr/lib/libGL.so.1"); + } + } + } + + } + + public static void end() { + if (oglLib != null) { + if (DEBUG) { + System.err.println("Ending DRI hack"); + } + + oglLib.close(); + oglLib = null; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/Debug.java b/src/jogl/classes/com/jogamp/opengl/impl/Debug.java new file mode 100644 index 000000000..82a5f2ff2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/Debug.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.security.*; + +/** Helper routines for logging and debugging. */ + +public class Debug { + // Some common properties + private static boolean verbose; + private static boolean debugAll; + private static AccessControlContext localACC; + + static { + localACC=AccessController.getContext(); + verbose = isPropertyDefined("jogl.verbose", true); + debugAll = isPropertyDefined("jogl.debug", true); + if (verbose) { + Package p = Package.getPackage("javax.media.opengl"); + System.err.println("JOGL specification version " + p.getSpecificationVersion()); + System.err.println("JOGL implementation version " + p.getImplementationVersion()); + System.err.println("JOGL implementation vendor " + p.getImplementationVendor()); + } + } + + static int getIntProperty(final String property, final boolean jnlpAlias) { + return getIntProperty(property, jnlpAlias, localACC); + } + + public static int getIntProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + int i=0; + try { + Integer iv = Integer.valueOf(Debug.getProperty(property, jnlpAlias, acc)); + i = iv.intValue(); + } catch (NumberFormatException nfe) {} + return i; + } + + static boolean getBooleanProperty(final String property, final boolean jnlpAlias) { + return getBooleanProperty(property, jnlpAlias, localACC); + } + + public static boolean getBooleanProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + Boolean b = Boolean.valueOf(Debug.getProperty(property, jnlpAlias, acc)); + return b.booleanValue(); + } + + static boolean isPropertyDefined(final String property, final boolean jnlpAlias) { + return isPropertyDefined(property, jnlpAlias, localACC); + } + + public static boolean isPropertyDefined(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + return (Debug.getProperty(property, jnlpAlias, acc) != null) ? true : false; + } + + static String getProperty(final String property, final boolean jnlpAlias) { + return getProperty(property, jnlpAlias, localACC); + } + + public static String getProperty(final String property, final boolean jnlpAlias, final AccessControlContext acc) { + String s=null; + if(null!=acc && acc.equals(localACC)) { + s = (String) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String val=null; + try { + val = System.getProperty(property); + } catch (Exception e) {} + if(null==val && jnlpAlias && !property.startsWith(jnlp_prefix)) { + try { + val = System.getProperty(jnlp_prefix + property); + } catch (Exception e) {} + } + return val; + } + }); + } else { + try { + s = System.getProperty(property); + } catch (Exception e) {} + if(null==s && jnlpAlias && !property.startsWith(jnlp_prefix)) { + try { + s = System.getProperty(jnlp_prefix + property); + } catch (Exception e) {} + } + } + return s; + } + public static final String jnlp_prefix = "jnlp." ; + + public static boolean verbose() { + return verbose; + } + + public static boolean debugAll() { + return debugAll; + } + + public static boolean debug(String subcomponent) { + return debugAll() || isPropertyDefined("jogl.debug." + subcomponent, true); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java b/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java new file mode 100644 index 000000000..9d1235e13 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ExtensionAvailabilityCache.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; +import java.util.*; +// FIXME: refactor Java SE dependencies +//import java.util.regex.*; +import java.lang.reflect.*; + +/** + * A utility object intended to be used by implementations to act as a cache + * of which OpenGL extensions are currently available on both the host machine + * and display. + */ +public final class ExtensionAvailabilityCache { + private static final boolean DEBUG = Debug.debug("ExtensionAvailabilityCache"); + private static final boolean DEBUG_AVAILABILITY = Debug.isPropertyDefined("ExtensionAvailabilityCache", true); + + ExtensionAvailabilityCache(GLContextImpl context) + { + this.context = context; + } + + /** + * Flush the cache. The cache will be rebuilt lazily as calls to {@link + * #isExtensionAvailable(String)} are received. + */ + public void flush() + { + if(DEBUG) { + System.out.println("ExtensionAvailabilityCache: Flush availability OpenGL "+context.getGLVersion()); + } + availableExtensionCache.clear(); + initialized = false; + } + + /** + * Flush the cache and rebuild the cache. + */ + public void reset() { + flush(); + initAvailableExtensions(); + } + + public boolean isInitialized() { + return initialized && !availableExtensionCache.isEmpty() ; + } + + public boolean isExtensionAvailable(String glExtensionName) { + initAvailableExtensions(); + return availableExtensionCache.contains(mapGLExtensionName(glExtensionName)); + } + + public String getPlatformExtensionsString() { + initAvailableExtensions(); + return glXExtensions; + } + + public String getGLExtensions() { + initAvailableExtensions(); + if(DEBUG) { + System.err.println("ExtensionAvailabilityCache: getGLExtensions() called"); + } + return glExtensions; + } + + private void initAvailableExtensions() { + GL gl = context.getGL(); + // if hash is empty (meaning it was flushed), pre-cache it with the list + // of extensions that are in the GL_EXTENSIONS string + if (availableExtensionCache.isEmpty() || !initialized) { + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Pre-caching init "+gl+", OpenGL "+context.getGLVersion()); + } + + boolean useGetStringi = false; + + if ( gl.isGL2GL3() ) { + if ( ! gl.isFunctionAvailable("glGetStringi") ) { + if(DEBUG) { + System.err.println("GLContext: GL >= 3.1 usage, but no glGetStringi"); + } + } else { + useGetStringi = true; + } + } + + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Pre-caching extension availability OpenGL "+context.getGLVersion()+ + ", use "+ ( useGetStringi ? "glGetStringi" : "glGetString" ) ); + } + + StringBuffer sb = new StringBuffer(); + if(useGetStringi) { + GL2GL3 gl2gl3 = gl.getGL2GL3(); + int[] numExtensions = { 0 } ; + gl2gl3.glGetIntegerv(gl2gl3.GL_NUM_EXTENSIONS, numExtensions, 0); + for (int i = 0; i < numExtensions[0]; i++) { + sb.append(gl2gl3.glGetStringi(gl2gl3.GL_EXTENSIONS, i)); + if(i < numExtensions[0]) { + sb.append(" "); + } + } + } else { + sb.append(gl.glGetString(GL.GL_EXTENSIONS)); + } + glExtensions = sb.toString(); + glXExtensions = context.getPlatformExtensionsString(); + + sb.append(" "); + sb.append(glXExtensions); + + String allAvailableExtensions = sb.toString(); + if (DEBUG_AVAILABILITY) { + System.err.println("ExtensionAvailabilityCache: Available extensions: " + allAvailableExtensions); + System.err.println("ExtensionAvailabilityCache: GL vendor: " + gl.glGetString(GL.GL_VENDOR)); + } + StringTokenizer tok = new StringTokenizer(allAvailableExtensions); + while (tok.hasMoreTokens()) { + String availableExt = tok.nextToken().trim(); + availableExt = availableExt.intern(); + availableExtensionCache.add(availableExt); + if (DEBUG_AVAILABILITY) { + System.err.println("ExtensionAvailabilityCache: Available: " + availableExt); + } + } + + int major[] = new int[] { context.getGLVersionMajor() }; + int minor[] = new int[] { context.getGLVersionMinor() }; + if( !gl.isGL3() && !gl.isGL4() && + ( major[0] > 3 || + ( major[0] == 3 && minor[0] >= 1 ) ) ) { + // downsize version to 3.0 in case we are not using GL3 (>=3.1) + major[0] = 3; + minor[0] = 0; + } + while (GLContext.isValidGLVersion(major[0], minor[0])) { + availableExtensionCache.add("GL_VERSION_" + major[0] + "_" + minor[0]); + if (DEBUG) { + System.err.println("ExtensionAvailabilityCache: Added GL_VERSION_" + major[0] + "_" + minor[0] + " to known extensions"); + } + if(!GLContext.decrementGLVersion(major, minor)) break; + } + + // put a dummy var in here so that the cache is no longer empty even if + // no extensions are in the GL_EXTENSIONS string + availableExtensionCache.add("<INTERNAL_DUMMY_PLACEHOLDER>"); + + initialized = true; + } + } + + // FIXME: hack to re-enable GL_NV_vertex_array_range extension after + // recent upgrade to new wglext.h and glxext.h headers + private static String mapGLExtensionName(String extensionName) { + if (extensionName != null && + (extensionName.equals("WGL_NV_vertex_array_range") || + extensionName.equals("GLX_NV_vertex_array_range"))) + return "GL_NV_vertex_array_range"; + return extensionName; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private boolean initialized = false; + private String glExtensions = null; + private String glXExtensions = null; + private HashSet availableExtensionCache = new HashSet(50); + private GLContextImpl context; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java new file mode 100755 index 000000000..48affa534 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferSizeTracker.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible the sizes of allocated OpenGL buffer + * objects. When glMapBuffer or glMapBufferARB is called, in order to + * turn the resulting base address into a java.nio.ByteBuffer, we need + * to know the size in bytes of the allocated OpenGL buffer object. + * Previously we would compute this size by using + * glGetBufferParameterivARB with a pname of GL_BUFFER_SIZE, but + * it appears doing so each time glMapBuffer is called is too costly + * on at least Apple's new multithreaded OpenGL implementation. <P> + * + * Instead we now try to track the sizes of allocated buffer objects. + * We watch calls to glBindBuffer to see which buffer is bound to + * which target and to glBufferData to see how large the buffer's + * allocated size is. When glMapBuffer is called, we consult our table + * of buffer sizes to see if we can return an answer without a glGet + * call. <P> + * + * We share the GLBufferSizeTracker objects among all GLContexts for + * which sharing is enabled, because the namespace for buffer objects + * is the same for these contexts. <P> + * + * Tracking the state of which buffer objects are bound is done in the + * GLBufferStateTracker and is not completely trivial. In the face of + * calls to glPushClientAttrib / glPopClientAttrib we currently punt + * and re-fetch the bound buffer object for the state in question; + * see, for example, glVertexPointer and the calls down to + * GLBufferStateTracker.getBoundBufferObject(). Note that we currently + * ignore new binding targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV; + * the fact that new binding targets may be added in the future makes + * it impossible to cache state for these new targets. <P> + * + * Ignoring new binding targets, the primary situation in which we may + * not be able to return a cached answer is in the case of an error, + * where glBindBuffer may not have been called before trying to call + * glBufferData. Also, if external native code modifies a buffer + * object, we may return an incorrect answer. (FIXME: this case + * requires more thought, and perhaps stochastic and + * exponential-fallback checking. However, note that it can only occur + * in the face of external native code which requires that the + * application be signed anyway, so there is no security risk in this + * area.) + */ + +public class GLBufferSizeTracker { + // Map from buffer names to sizes. + // Note: should probably have some way of shrinking this map, but + // can't just make it a WeakHashMap because nobody holds on to the + // keys; would have to always track creation and deletion of buffer + // objects, which is probably sub-optimal. The expected usage + // pattern of buffer objects indicates that the fact that this map + // never shrinks is probably not that bad. + private Map/*<Integer,Integer>*/ bufferSizeMap = + Collections.synchronizedMap(new HashMap/*<Integer,Integer>*/()); + + private static final boolean DEBUG = Debug.debug("GLBufferSizeTracker"); + + public GLBufferSizeTracker() { + } + + public void setBufferSize(GLBufferStateTracker bufferStateTracker, + int target, + GL caller, + int size) { + // Need to do some similar queries to getBufferSize below + int buffer = bufferStateTracker.getBoundBufferObject(target, caller); + boolean valid = bufferStateTracker.isBoundBufferObjectKnown(target); + if (valid) { + if (buffer == 0) { + // FIXME: this really should not happen if we know what's + // going on. Very likely there is an OpenGL error in the + // application if we get here. Could silently return 0, but it + // seems better to get an early warning that something is + // wrong. + throw new GLException("Error: no OpenGL buffer object appears to be bound to target 0x" + + Integer.toHexString(target)); + } + bufferSizeMap.put(new Integer(buffer), new Integer(size)); + } + // We don't know the current buffer state. Note that the buffer + // state tracker will have made the appropriate OpenGL query if it + // didn't know what was going on, so at this point we have nothing + // left to do except drop this piece of information on the floor. + } + + public int getBufferSize(GLBufferStateTracker bufferStateTracker, + int target, + GL caller) { + // See whether we know what buffer is currently bound to the given + // state + int buffer = bufferStateTracker.getBoundBufferObject(target, caller); + boolean valid = bufferStateTracker.isBoundBufferObjectKnown(target); + if (valid) { + if (buffer == 0) { + // FIXME: this really should not happen if we know what's + // going on. Very likely there is an OpenGL error in the + // application if we get here. Could silently return 0, but it + // seems better to get an early warning that something is + // wrong. + throw new GLException("Error: no OpenGL buffer object appears to be bound to target 0x" + + Integer.toHexString(target)); + } + // See whether we know the size of this buffer object; at this + // point we almost certainly should if the application is + // written correctly + Integer key = new Integer(buffer); + Integer sz = (Integer) bufferSizeMap.get(key); + if (sz == null) { + // For robustness, try to query this value from the GL as we used to + int[] tmp = new int[1]; + caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); + if (tmp[0] == 0) { + // Assume something is wrong rather than silently going along + throw new GLException("Error: buffer size returned by glGetBufferParameteriv was zero; probably application error"); + } + // Assume we just don't know what's happening + sz = new Integer(tmp[0]); + bufferSizeMap.put(key, sz); + if (DEBUG) { + System.err.println("GLBufferSizeTracker.getBufferSize(): made slow query to cache size " + + tmp[0] + + " for buffer " + + buffer); + } + } + return sz.intValue(); + } + // We don't know what's going on in this case; query the GL for an answer + int[] tmp = new int[1]; + caller.glGetBufferParameteriv(target, GL.GL_BUFFER_SIZE, tmp, 0); + if (DEBUG) { + System.err.println("GLBufferSizeTracker.getBufferSize(): no cached buffer information"); + } + return tmp[0]; + } + + // This should be called on any major event where we might start + // producing wrong answers, such as OpenGL context creation and + // destruction if we don't know whether there are other currently- + // created contexts that might be keeping the buffer objects alive + // that we're dealing with + public void clearCachedBufferSizes() { + bufferSizeMap.clear(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java new file mode 100755 index 000000000..df8d673a1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLBufferStateTracker.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible which OpenGL buffer object is bound + * to which binding target in the current OpenGL context. + * GLBufferStateTracker objects are allocated on a per-OpenGL-context basis. + * This class is used to verify that e.g. the vertex + * buffer object extension is in use when the glVertexPointer variant + * taking a long as argument is called. <P> + * + * Note that because the enumerated value used for the binding of a + * buffer object (e.g. GL_ARRAY_BUFFER) is different than that used to + * query the binding using glGetIntegerv (e.g. + * GL_ARRAY_BUFFER_BINDING), then in the face of new binding targets + * being added to the GL (e.g. GL_TRANSFORM_FEEDBACK_BUFFER_NV) it is + * impossible to set up a query of the buffer object currently bound + * to a particular state. It turns out that for some uses, such as + * finding the size of the currently bound buffer, this doesn't + * matter, though of course without knowing the buffer object we can't + * re-associate the queried size with the buffer object ID. <P> + * + * Because the namespace of buffer objects is the unsigned integers + * with 0 reserved by the GL, and because we have to be able to return + * both 0 and other integers as valid answers from + * getBoundBufferObject(), we need a second query, which is to ask + * whether we know the state of the binding for a given target. For + * "unknown" targets such as GL_TRANSFORM_FEEDBACK_BUFFER_NV we return + * false from this, but we also clear the valid bit and later refresh + * the binding state if glPushClientAttrib / glPopClientAttrib are + * called, since we don't want the complexity of tracking stacks of + * these attributes. + * + */ + +public class GLBufferStateTracker { + private static final boolean DEBUG = Debug.debug("GLBufferStateTracker"); + + private static final Integer arrayBufferEnum = new Integer(GL.GL_ARRAY_BUFFER); + private static final Integer elementArrayBufferEnum = new Integer(GL.GL_ELEMENT_ARRAY_BUFFER); + private static final Integer pixelPackBufferEnum = new Integer(GL2.GL_PIXEL_PACK_BUFFER); + private static final Integer pixelUnpackBufferEnum = new Integer(GL2.GL_PIXEL_UNPACK_BUFFER); + private static final Integer zero = new Integer(0); + + // Maps binding targets to buffer objects. A null value indicates + // that the binding is unknown. A zero value indicates that it is + // known that no buffer is bound to the target. + private Map/*<Integer,Integer>*/ bindingMap = new HashMap/*<Integer,Integer>*/(); + + private int[] bufTmp = new int[1]; + + public GLBufferStateTracker() { + // Start with known unbound targets for known keys + bindingMap.put(arrayBufferEnum, zero); + bindingMap.put(elementArrayBufferEnum, zero); + bindingMap.put(pixelPackBufferEnum, zero); + bindingMap.put(pixelUnpackBufferEnum, zero); + } + + public void setBoundBufferObject(int target, int buffer) { + bindingMap.put(box(target), box(buffer)); + } + + /** Note: returns an unspecified value if the binding for the + specified target (e.g. GL_ARRAY_BUFFER) is currently unknown. + You must use isBoundBufferObjectKnown() to see whether the + return value is valid. */ + public int getBoundBufferObject(int target, GL caller) { + Integer value = (Integer) bindingMap.get(box(target)); + if (value == null) { + // User probably either called glPushClientAttrib / + // glPopClientAttrib or is querying an unknown target. See + // whether we know how to fetch this state. + boolean gotQueryTarget = true; + int queryTarget = 0; + switch (target) { + case GL.GL_ARRAY_BUFFER: queryTarget = GL.GL_ARRAY_BUFFER_BINDING; break; + case GL.GL_ELEMENT_ARRAY_BUFFER: queryTarget = GL.GL_ELEMENT_ARRAY_BUFFER_BINDING; break; + case GL2.GL_PIXEL_PACK_BUFFER: queryTarget = GL2.GL_PIXEL_PACK_BUFFER_BINDING; break; + case GL2.GL_PIXEL_UNPACK_BUFFER: queryTarget = GL2.GL_PIXEL_UNPACK_BUFFER_BINDING; break; + default: gotQueryTarget = false; break; + } + if (gotQueryTarget) { + caller.glGetIntegerv(queryTarget, bufTmp, 0); + if (DEBUG) { + System.err.println("GLBufferStateTracker.getBoundBufferObject(): queried bound buffer " + + bufTmp[0] + + " for query target 0x" + Integer.toHexString(queryTarget)); + } + setBoundBufferObject(target, bufTmp[0]); + // Try once more + return getBoundBufferObject(target, caller); + } + return 0; + } + return value.intValue(); + } + + /** Indicates whether the binding state for the specified target is + currently known. Should be called after getBoundBufferObject() + because that method may change the answer for a given target. */ + public boolean isBoundBufferObjectKnown(int target) { + return (bindingMap.get(box(target)) != null); + } + + /** Clears out the known/unknown state of the various buffer object + binding states. These will be refreshed later on an as-needed + basis. This is called by the implementations of + glPushClientAttrib / glPopClientAttrib. Might want to call this + from GLContext.makeCurrent() in the future to possibly increase + the robustness of these caches in the face of external native + code manipulating OpenGL state. */ + public void clearBufferObjectState() { + bindingMap.clear(); + } + + // FIXME: could largely remove this and use Integer.valueOf() in JDK 5 + private static Integer box(int key) { + switch (key) { + case 0: return zero; + case GL.GL_ARRAY_BUFFER: return arrayBufferEnum; + case GL.GL_ELEMENT_ARRAY_BUFFER: return elementArrayBufferEnum; + case GL2.GL_PIXEL_PACK_BUFFER: return pixelPackBufferEnum; + case GL2.GL_PIXEL_UNPACK_BUFFER: return pixelUnpackBufferEnum; + default: return new Integer(key); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java new file mode 100644 index 000000000..7143344bf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -0,0 +1,1057 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.gluegen.runtime.*; +import com.jogamp.gluegen.runtime.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.ReflectionUtil; + +public abstract class GLContextImpl extends GLContext { + protected GLContextLock lock = new GLContextLock(); + protected static final boolean DEBUG = Debug.debug("GLContext"); + protected static final boolean VERBOSE = Debug.verbose(); + // NOTE: default sense of GLContext optimization disabled in JSR-231 + // 1.0 beta 5 due to problems on X11 platforms (both Linux and + // Solaris) when moving and resizing windows. Apparently GLX tokens + // get sent to the X server under the hood (and out from under the + // cover of the AWT lock) in these situations. Users requiring + // multi-screen X11 applications can manually enable this flag. It + // basically had no tangible effect on the Windows or Mac OS X + // platforms anyway in particular with the disabling of the + // GLWorkerThread which we found to be necessary in 1.0 beta 4. + protected boolean optimizationEnabled = Debug.isPropertyDefined("jogl.GLContext.optimize", true); + + // Cache of the functions that are available to be called at the current + // moment in time + protected ExtensionAvailabilityCache extensionAvailability; + // Table that holds the addresses of the native C-language entry points for + // OpenGL functions. + private ProcAddressTable glProcAddressTable; + + // Tracks creation and initialization of buffer objects to avoid + // repeated glGet calls upon glMapBuffer operations + private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet + private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); + private GLStateTracker glStateTracker = new GLStateTracker(); + + protected GLDrawableImpl drawable; + protected GLDrawableImpl drawableRead; + + protected GL gl; + + public GLContextImpl(GLDrawableImpl drawable, GLDrawableImpl drawableRead, GLContext shareWith) { + extensionAvailability = new ExtensionAvailabilityCache(this); + if (shareWith != null) { + GLContextShareSet.registerSharing(this, shareWith); + } + GLContextShareSet.registerForBufferObjectSharing(shareWith, this); + // This must occur after the above calls into the + // GLContextShareSet, which set up state needed by the GL object + setGL(createGL(drawable.getGLProfile())); + + this.drawable = drawable; + setGLDrawableRead(drawableRead); + } + + public GLContextImpl(GLDrawableImpl drawable, GLContext shareWith) { + this(drawable, null, shareWith); + } + + public void setGLDrawableRead(GLDrawable read) { + boolean lockHeld = lock.isHeld(); + if(lockHeld) { + release(); + } + drawableRead = ( null != read ) ? (GLDrawableImpl) read : drawable; + if(lockHeld) { + makeCurrent(); + } + } + + public GLDrawable getGLDrawable() { + return drawable; + } + + public GLDrawable getGLDrawableRead() { + return drawableRead; + } + + public GLDrawableImpl getDrawableImpl() { + return (GLDrawableImpl) getGLDrawable(); + } + + public final GL getGL() { + return gl; + } + + public GL setGL(GL gl) { + if(DEBUG) { + String sgl1 = (null!=this.gl)?this.gl.getClass().toString()+", "+this.gl.toString():new String("<null>"); + String sgl2 = (null!=gl)?gl.getClass().toString()+", "+gl.toString():new String("<null>"); + Exception e = new Exception("setGL (OpenGL "+getGLVersion()+"): "+Thread.currentThread()+", "+sgl1+" -> "+sgl2); + e.printStackTrace(); + } + this.gl = gl; + return gl; + } + + // This is only needed for Mac OS X on-screen contexts + protected void update() throws GLException { } + + public boolean isSynchronized() { + return !lock.getFailFastMode(); + } + + public void setSynchronized(boolean isSynchronized) { + lock.setFailFastMode(!isSynchronized); + } + + public abstract Object getPlatformGLExtensions(); + + public void release() throws GLException { + if (!lock.isHeld()) { + throw new GLException("Context not current on current thread"); + } + setCurrent(null); + try { + releaseImpl(); + } finally { + lock.unlock(); + } + } + + protected abstract void releaseImpl() throws GLException; + + public void destroy() { + if (lock.isHeld()) { + // release current context + release(); + } + + // Must hold the lock around the destroy operation to make sure we + // don't destroy the context out from under another thread rendering to it + lock.lock(); + try { + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if (tracker != null) { + // Don't need to do anything for contexts that haven't been + // created yet + if (isCreated()) { + // If we are tracking creation and destruction of server-side + // OpenGL objects, we must decrement the reference count of the + // GLObjectTracker upon context destruction. + // + // Note that we can only eagerly delete these server-side + // objects if there is another context currrent right now + // which shares textures and display lists with this one. + tracker.unref(deletedObjectTracker); + } + } + */ + + // Because we don't know how many other contexts we might be + // sharing with (and it seems too complicated to implement the + // GLObjectTracker's ref/unref scheme for the buffer-related + // optimizations), simply clear the cache of known buffers' sizes + // when we destroy contexts + if (bufferSizeTracker != null) { + bufferSizeTracker.clearCachedBufferSizes(); + } + + if (bufferStateTracker != null) { + bufferStateTracker.clearBufferObjectState(); + } + + if (glStateTracker != null) { + glStateTracker.clearStates(false); + } + + destroyImpl(); + } finally { + lock.unlock(); + } + } + + protected abstract void destroyImpl() throws GLException; + + //---------------------------------------------------------------------- + // + + /** + * MakeCurrent functionality, which also issues the creation of the actual OpenGL context.<br> + * The complete callgraph for general OpenGL context creation is:<br> + * <ul> + * <li> {@link #makeCurrent} <i>GLContextImpl</i> + * <li> {@link #makeCurrentImpl} <i>Platform Implementation</i> + * <li> {@link #create} <i>Platform Implementation</i> + * <li> If <code>ARB_create_context</code> is supported: + * <ul> + * <li> {@link #createContextARB} <i>GLContextImpl</i> + * <li> {@link #createContextARBImpl} <i>Platform Implementation</i> + * </ul> + * </ul><br> + * + * Once at startup, ie triggered by the singleton {@link GLDrawableImpl} constructor, + * calling {@link #createContextARB} will query all available OpenGL versions:<br> + * <ul> + * <li> <code>FOR ALL GL* DO</code>: + * <ul> + * <li> {@link #createContextARBMapVersionsAvailable} + * <ul> + * <li> {@link #createContextARBVersions} + * </ul> + * <li> {@link #mapVersionAvailable} + * </ul> + * </ul><br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #mapVersionAvailable + * @see #destroyContextARBImpl + */ + public int makeCurrent() throws GLException { + // Support calls to makeCurrent() over and over again with + // different contexts without releasing them + // Could implement this more efficiently without explicit + // releasing of the underlying context; would require more error + // checking during the makeCurrentImpl phase + GLContext current = getCurrent(); + if (current != null) { + if (current == this) { + // Assume we don't need to make this context current again + // For Mac OS X, however, we need to update the context to track resizes + update(); + return CONTEXT_CURRENT; + } else { + current.release(); + } + } + + if (GLWorkerThread.isStarted() && + !GLWorkerThread.isWorkerThread()) { + // Kick the GLWorkerThread off its current context + GLWorkerThread.invokeLater(new Runnable() { public void run() {} }); + } + + lock.lock(); + int res = 0; + try { + res = makeCurrentImpl(); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if ((tracker != null) && + (res == CONTEXT_CURRENT_NEW)) { + // Increase reference count of GLObjectTracker + tracker.ref(); + } + */ + } catch (GLException e) { + lock.unlock(); + throw(e); + } + if (res == CONTEXT_NOT_CURRENT) { + lock.unlock(); + } else { + if(res == CONTEXT_CURRENT_NEW) { + // check if the drawable's and the GL's GLProfile are equal + // throws an GLException if not + getGLDrawable().getGLProfile().verifyEquality(gl.getGLProfile()); + } + setCurrent(this); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + + // Try cleaning up any stale server-side OpenGL objects + // FIXME: not sure what to do here if this throws + if (deletedObjectTracker != null) { + deletedObjectTracker.clean(getGL()); + } + */ + } + return res; + } + + /** + * @see #makeCurrent + */ + protected abstract int makeCurrentImpl() throws GLException; + + /** + * @see #makeCurrent + */ + protected abstract void create() throws GLException ; + + /** + * Platform dependent but harmonized implementation of the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * This method is called from {@link #createContextARB}.<br> + * + * The implementation shall verify this context with a + * <code>MakeContextCurrent</code> call.<br> + * + * @param share the shared context or null + * @param direct flag if direct is requested + * @param ctxOptionFlags <code>ARB_create_context</code> related, see references below + * @param major major number + * @param minor minor number + * @return the valid context if successfull, or null + * + * @see #makeCurrent + * @see #CTX_PROFILE_COMPAT + * @see #CTX_OPTION_FORWARD + * @see #CTX_OPTION_DEBUG + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, + int major, int minor); + + /** + * Destroy the context created by {@link #createContextARBImpl}. + * + * @see #makeCurrent + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected abstract void destroyContextARBImpl(long context); + + /** + * Platform independent part of using the <code>ARB_create_context</code> + * mechanism to create a context.<br> + * + * The implementation of {@link #create} shall use this protocol in case the platform supports <code>ARB_create_context</code>.<br> + * + * This method may call {@link #createContextARBImpl} and {@link #destroyContextARBImpl}. <br> + * + * This method will also query all available native OpenGL context when first called,<br> + * usually the first call should happen with the shared GLContext of the DrawableFactory.<br> + * + * @see #makeCurrentImpl + * @see #create + * @see #createContextARB + * @see #createContextARBImpl + * @see #destroyContextARBImpl + */ + protected long createContextARB(long share, boolean direct, + int major[], int minor[], int ctp[]) + { + AbstractGraphicsConfiguration config = drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + GLProfile glp = glCaps.getGLProfile(); + long _context = 0; + + if( !mappedVersionsAvailableSet ) { + synchronized(mappedVersionsAvailableLock) { + if( !mappedVersionsAvailableSet ) { + createContextARBMapVersionsAvailable(4, false /* compat */); // GL4 + createContextARBMapVersionsAvailable(4, true /* compat */); // GL4bc + createContextARBMapVersionsAvailable(3, false /* compat */); // GL3 + createContextARBMapVersionsAvailable(3, true /* compat */); // GL3bc + createContextARBMapVersionsAvailable(2, true /* compat */); // GL2 + mappedVersionsAvailableSet=true; + } + } + } + + int reqMajor; + if(glp.isGL4()) { + reqMajor=4; + } else if (glp.isGL3()) { + reqMajor=3; + } else /* if (glp.isGL2()) */ { + reqMajor=2; + } + boolean compat = glp.isGL2(); // incl GL3bc and GL4bc + + int key = compose8bit(reqMajor, compat?CTX_PROFILE_COMPAT:CTX_PROFILE_CORE, 0, 0); + int val = mappedVersionsAvailable.get( key ); + long _ctx = 0; + if(val>0) { + int _major = getComposed8bit(val, 1); + int _minor = getComposed8bit(val, 2); + int _ctp = getComposed8bit(val, 3); + + _ctx = createContextARBImpl(share, direct, _ctp, _major, _minor); + if(0!=_ctx) { + setGLFunctionAvailability(true, _major, _minor, _ctp); + } + } + return _ctx; + } + + private void createContextARBMapVersionsAvailable(int reqMajor, boolean compat) + { + long _context; + int ctp = CTX_IS_ARB_CREATED | CTX_PROFILE_CORE | CTX_OPTION_ANY; // default + if(compat) { + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + } + + // FIXME GL3GL4: + // To avoid OpenGL implementation bugs and raise compatibility + // within JOGL, we map to the proper GL version. + // This may change later when GL3 and GL4 drivers become more mature! + // Bug: To ensure GL profile compatibility within the JOGL application + // Bug: we always try to map against the highest GL version, + // Bug: so the use can always cast to a higher one + // Bug: int majorMax=GLContext.getMaxMajor(); + // Bug: int minorMax=GLContext.getMaxMinor(majorMax); + int majorMax, minorMax; + int majorMin, minorMin; + int major[] = new int[1]; + int minor[] = new int[1]; + if( 4 == reqMajor ) { + majorMax=4; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=4; minorMin=0; + } else if( 3 == reqMajor ) { + majorMax=3; minorMax=GLContext.getMaxMinor(majorMax); + majorMin=3; minorMin=1; + } else /* if( glp.isGL2() ) */ { + majorMax=3; minorMax=0; + majorMin=1; minorMin=1; // our minimum desktop OpenGL runtime requirements + } + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + + if(0==_context && !compat) { + ctp &= ~CTX_PROFILE_COMPAT ; + ctp |= CTX_PROFILE_CORE ; + ctp &= ~CTX_OPTION_ANY ; + ctp |= CTX_OPTION_FORWARD ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + if(0==_context) { + // Try a compatible one .. even though not requested .. last resort + ctp &= ~CTX_PROFILE_CORE ; + ctp |= CTX_PROFILE_COMPAT ; + ctp &= ~CTX_OPTION_FORWARD ; + ctp |= CTX_OPTION_ANY ; + _context = createContextARBVersions(0, true, ctp, + /* max */ majorMax, minorMax, + /* min */ majorMin, minorMin, + /* res */ major, minor); + } + } + if(0!=_context) { + destroyContextARBImpl(_context); + mapVersionAvailable(reqMajor, compat, major[0], minor[0], ctp); + } + } + + private long createContextARBVersions(long share, boolean direct, int ctxOptionFlags, + int majorMax, int minorMax, + int majorMin, int minorMin, + int major[], int minor[]) { + major[0]=majorMax; + minor[0]=minorMax; + long _context=0; + + while ( 0==_context && + GLContext.isValidGLVersion(major[0], minor[0]) && + ( major[0]>majorMin || major[0]==majorMin && minor[0] >=minorMin ) ) { + + _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); + + if(0==_context) { + if(!GLContext.decrementGLVersion(major, minor)) break; + } + } + return _context; + } + + //---------------------------------------------------------------------- + // Managing the actual OpenGL version, usually figured at creation time. + // As a last resort, the GL_VERSION string may be used .. + // + + /** + * If major > 0 || minor > 0 : Use passed values, determined at creation time + * If major==0 && minor == 0 : Use GL_VERSION + * Otherwise .. don't touch .. + */ + protected void setContextVersion(int major, int minor, int ctp) { + if (0==ctp) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } + if(major>0 || minor>0) { + if (!GLContext.isValidGLVersion(major, minor)) { + GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); + throw e; + } + ctxMajorVersion = major; + ctxMinorVersion = minor; + ctxOptions = ctp; + ctxVersionString = getGLVersion(gl, ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); + return; + } + + if(major==0 && minor==0) { + String versionStr = getGL().glGetString(GL.GL_VERSION); + if(null==versionStr) { + throw new GLException("GL_VERSION is NULL: "+this); + } + ctxOptions = ctp; + + // Set version + Version version = new Version(versionStr); + if (version.isValid()) { + ctxMajorVersion = version.getMajor(); + ctxMinorVersion = version.getMinor(); + + ctxVersionString = getGLVersion(gl, ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); + return; + } + } + } + + private static boolean appendString(StringBuffer sb, String string, boolean needColon, boolean condition) { + if(condition) { + if(needColon) { + sb.append(", "); + } + sb.append(string); + needColon=true; + } + return needColon; + } + + protected static String getGLVersion(GL gl, int major, int minor, int ctp, String gl_version) { + boolean needColon = false; + StringBuffer sb = new StringBuffer(); + sb.append(major); + sb.append("."); + sb.append(minor); + sb.append(" ("); + needColon = appendString(sb, "ES", needColon, null!=gl && gl.isGLES()); + needColon = appendString(sb, "compatibility profile", needColon, 0 != ( CTX_PROFILE_COMPAT & ctp )); + needColon = appendString(sb, "core profile", needColon, 0 != ( CTX_PROFILE_CORE & ctp )); + needColon = appendString(sb, "forward compatible", needColon, 0 != ( CTX_OPTION_FORWARD & ctp )); + needColon = appendString(sb, "any", needColon, 0 != ( CTX_OPTION_ANY & ctp )); + needColon = appendString(sb, "new", needColon, 0 != ( CTX_IS_ARB_CREATED & ctp )); + needColon = appendString(sb, "old", needColon, 0 == ( CTX_IS_ARB_CREATED & ctp )); + sb.append(") - "); + if(null!=gl_version) { + sb.append(gl_version); + } else { + sb.append("n/a"); + } + return sb.toString(); + } + + //---------------------------------------------------------------------- + // Helpers for various context implementations + // + + private Object createInstance(GLProfile glp, String suffix, Class[] cstrArgTypes, Object[] cstrArgs) { + return ReflectionUtil.createInstance(glp.getGLImplBaseClassName()+suffix, cstrArgTypes, cstrArgs); + } + + /** Create the GL for this context. */ + protected GL createGL(GLProfile glp) { + GL gl = (GL) createInstance(glp, "Impl", new Class[] { GLProfile.class, GLContextImpl.class }, new Object[] { glp, this } ); + + /* FIXME: refactor dependence on Java 2D / JOGL bridge + if (tracker != null) { + gl.setObjectTracker(tracker); + } + */ + return gl; + } + + public final ProcAddressTable getGLProcAddressTable() { + return glProcAddressTable; + } + + /** + * Shall return the platform extension ProcAddressTable, + * ie for GLXExt, EGLExt, .. + */ + public abstract ProcAddressTable getPlatformExtProcAddressTable(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, binds this pbuffer to its texture target. + */ + public abstract void bindPbufferToTexture(); + + /** + * Pbuffer support; given that this is a GLContext associated with a + * pbuffer, releases this pbuffer from its texture target. + */ + public abstract void releasePbufferFromTexture(); + + public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3); + + public void setSwapInterval(final int interval) { + GLContext current = getCurrent(); + if (current != this) { + throw new GLException("This context is not current. Current context: "+current+ + ", this context "+this); + } + setSwapIntervalImpl(interval); + } + + protected int currentSwapInterval = -1; // default: not set yet .. + + public int getSwapInterval() { + return currentSwapInterval; + } + + protected void setSwapIntervalImpl(final int interval) { + // nop per default .. + } + + /** Maps the given "platform-independent" function name to a real function + name. Currently this is only used to map "glAllocateMemoryNV" and + associated routines to wglAllocateMemoryNV / glXAllocateMemoryNV. */ + protected String mapToRealGLFunctionName(String glFunctionName) { + Map/*<String, String>*/ map = getFunctionNameMap(); + String lookup = ( null != map ) ? (String) map.get(glFunctionName) : null; + if (lookup != null) { + return lookup; + } + return glFunctionName; + } + protected abstract Map/*<String, String>*/ getFunctionNameMap() ; + + /** Maps the given "platform-independent" extension name to a real + function name. Currently this is only used to map + "GL_ARB_pbuffer" to "WGL_ARB_pbuffer/GLX_SGIX_pbuffer" and + "GL_ARB_pixel_format" to "WGL_ARB_pixel_format/n.a." + */ + protected String mapToRealGLExtensionName(String glExtensionName) { + Map/*<String, String>*/ map = getExtensionNameMap(); + String lookup = ( null != map ) ? (String) map.get(glExtensionName) : null; + if (lookup != null) { + return lookup; + } + return glExtensionName; + } + protected abstract Map/*<String, String>*/ getExtensionNameMap() ; + + /** Helper routine which resets a ProcAddressTable generated by the + GLEmitter by looking up anew all of its function pointers. */ + protected void resetProcAddressTable(Object table) { + GLProcAddressHelper.resetProcAddressTable(table, getDrawableImpl().getDynamicLookupHelper() ); + } + + /** Indicates whether the underlying OpenGL context has been + created. This is used to manage sharing of display lists and + textures between contexts. */ + public abstract boolean isCreated(); + + /** + * Sets the OpenGL implementation class and + * the cache of which GL functions are available for calling through this + * context. See {@link #isFunctionAvailable(String)} for more information on + * the definition of "available". + * + * @param force force the setting, even if is already being set. + * This might be usefull if you change the OpenGL implementation. + * + * @see #setContextVersion + */ + protected void setGLFunctionAvailability(boolean force, int major, int minor, int ctp) { + if(null!=this.gl && null!=glProcAddressTable && !force) { + return; // already done and not forced + } + if(null==this.gl || force) { + setGL(createGL(getGLDrawable().getGLProfile())); + } + + updateGLProcAddressTable(major, minor, ctp); + } + + /** + * Updates the cache of which GL functions are available for calling through this + * context. See {@link #isFunctionAvailable(String)} for more information on + * the definition of "available". + * + * @see #setContextVersion + */ + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if(null==this.gl) { + throw new GLException("setGLFunctionAvailability not called yet"); + } + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing OpenGL extension address table for " + this); + } + if (glProcAddressTable == null) { + glProcAddressTable = (ProcAddressTable) createInstance(gl.getGLProfile(), "ProcAddressTable", new Class[0], null); + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + } + resetProcAddressTable(getGLProcAddressTable()); + + setContextVersion(major, minor, ctp); + + extensionAvailability.reset(); + } + + /** + * Returns true if the specified OpenGL core- or extension-function can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isFunctionAvailable(String)} for more details. + * + * @param glFunctionName the name of the OpenGL function (e.g., use + * "glPolygonOffsetEXT" or "glPolygonOffset" to check if the {@link + * javax.media.opengl.GL#glPolygonOffset(float,float)} is available). + */ + public boolean isFunctionAvailable(String glFunctionName) { + if(isCreated()) { + // Check GL 1st (cached) + ProcAddressTable pTable = getGLProcAddressTable(); + try { + if(0!=pTable.getAddressFor(glFunctionName)) { + return true; + } + } catch (Exception e) {} + + // Check platform extensions 2nd (cached) + pTable = getPlatformExtProcAddressTable(); + try { + if(0!=pTable.getAddressFor(glFunctionName)) { + return true; + } + } catch (Exception e) {} + } + // dynamic function lookup at last incl name aliasing (not cached) + DynamicLookupHelper dynLookup = getDrawableImpl().getDynamicLookupHelper(); + String tmpBase = GLExtensionNames.normalizeVEN(GLExtensionNames.normalizeARB(glFunctionName, true), true); + long addr = 0; + int variants = GLExtensionNames.getFuncNamePermutationNumber(tmpBase); + for(int i = 0; 0==addr && i < variants; i++) { + String tmp = GLExtensionNames.getFuncNamePermutation(tmpBase, i); + try { + addr = dynLookup.dynamicLookupFunction(tmp); + } catch (Exception e) { } + } + if(0!=addr) { + return true; + } + return false; + } + + /** + * Returns true if the specified OpenGL extension can be + * successfully called using this GL context given the current host (OpenGL + * <i>client</i>) and display (OpenGL <i>server</i>) configuration. + * + * See {@link GL#isExtensionAvailable(String)} for more details. + * + * @param glExtensionName the name of the OpenGL extension (e.g., + * "GL_VERTEX_PROGRAM_ARB"). + */ + public boolean isExtensionAvailable(String glExtensionName) { + return extensionAvailability.isExtensionAvailable(mapToRealGLExtensionName(glExtensionName)); + } + + public String getPlatformExtensionsString() { + return extensionAvailability.getPlatformExtensionsString(); + } + + public String getGLExtensions() { + return extensionAvailability.getGLExtensions(); + } + + public boolean isExtensionCacheInitialized() { + return extensionAvailability.isInitialized(); + } + + /** Indicates which floating-point pbuffer implementation is in + use. Returns one of GLPbuffer.APPLE_FLOAT, GLPbuffer.ATI_FLOAT, + or GLPbuffer.NV_FLOAT. */ + public int getFloatingPointMode() throws GLException { + throw new GLException("Not supported on non-pbuffer contexts"); + } + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. */ + public abstract boolean offscreenImageNeedsVerticalFlip(); + + /** Only called for offscreen contexts; needed by glReadPixels */ + public abstract int getOffscreenContextPixelDataType(); + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + + //---------------------------------------------------------------------- + // Helpers for buffer object optimizations + + public void setBufferSizeTracker(GLBufferSizeTracker bufferSizeTracker) { + this.bufferSizeTracker = bufferSizeTracker; + } + + public GLBufferSizeTracker getBufferSizeTracker() { + return bufferSizeTracker; + } + + public GLBufferStateTracker getBufferStateTracker() { + return bufferStateTracker; + } + + public GLStateTracker getGLStateTracker() { + return glStateTracker; + } + + //--------------------------------------------------------------------------- + // Helpers for context optimization where the last context is left + // current on the OpenGL worker thread + // + + public boolean isOptimizable() { + return optimizationEnabled; + } + + public boolean hasWaiters() { + return lock.hasWaiters(); + } + + /* FIXME: needed only by the Java 2D / JOGL bridge; refactor + + public GLContextImpl(GLContext shareWith) { + this(shareWith, false); + } + + public GLContextImpl(GLContext shareWith, boolean dontShareWithJava2D) { + extensionAvailability = new ExtensionAvailabilityCache(this); + GLContext shareContext = shareWith; + if (!dontShareWithJava2D) { + shareContext = Java2D.filterShareContext(shareWith); + } + if (shareContext != null) { + GLContextShareSet.registerSharing(this, shareContext); + } + // Always indicate real behind-the-scenes sharing to track deleted objects + if (shareContext == null) { + shareContext = Java2D.filterShareContext(shareWith); + } + GLContextShareSet.registerForObjectTracking(shareWith, this, shareContext); + GLContextShareSet.registerForBufferObjectSharing(shareWith, this); + // This must occur after the above calls into the + // GLContextShareSet, which set up state needed by the GL object + setGL(createGL()); + } + + //--------------------------------------------------------------------------- + // Helpers for integration with Java2D/OpenGL pipeline when FBOs are + // being used + // + + public void setObjectTracker(GLObjectTracker tracker) { + this.tracker = tracker; + } + + public GLObjectTracker getObjectTracker() { + return tracker; + } + + public void setDeletedObjectTracker(GLObjectTracker deletedObjectTracker) { + this.deletedObjectTracker = deletedObjectTracker; + } + + public GLObjectTracker getDeletedObjectTracker() { + return deletedObjectTracker; + } + + // Tracks creation and deletion of server-side OpenGL objects when + // the Java2D/OpenGL pipeline is active and using FBOs to render + private GLObjectTracker tracker; + // Supports deletion of these objects when no other context is + // current which can support immediate deletion of them + private GLObjectTracker deletedObjectTracker; + + */ + + /** + * A class for storing and comparing OpenGL version numbers. + * This only works for desktop OpenGL at the moment. + */ + private static class Version implements Comparable + { + private boolean valid; + private int major, minor, sub; + public Version(int majorRev, int minorRev, int subMinorRev) + { + major = majorRev; + minor = minorRev; + sub = subMinorRev; + } + + /** + * @param versionString must be of the form "GL_VERSION_X" or + * "GL_VERSION_X_Y" or "GL_VERSION_X_Y_Z" or "X.Y", where X, Y, + * and Z are integers. + * + * @exception IllegalArgumentException if the argument is not a valid + * OpenGL version identifier + */ + public Version(String versionString) + { + try + { + if (versionString.startsWith("GL_VERSION_")) + { + StringTokenizer tok = new StringTokenizer(versionString, "_"); + + tok.nextToken(); // GL_ + tok.nextToken(); // VERSION_ + if (!tok.hasMoreTokens()) { major = 0; return; } + major = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { minor = 0; return; } + minor = Integer.valueOf(tok.nextToken()).intValue(); + if (!tok.hasMoreTokens()) { sub = 0; return; } + sub = Integer.valueOf(tok.nextToken()).intValue(); + } + else + { + int radix = 10; + if (versionString.length() > 2) { + if (Character.isDigit(versionString.charAt(0)) && + versionString.charAt(1) == '.' && + Character.isDigit(versionString.charAt(2))) { + major = Character.digit(versionString.charAt(0), radix); + minor = Character.digit(versionString.charAt(2), radix); + + // See if there's version-specific information which might + // imply a more recent OpenGL version + StringTokenizer tok = new StringTokenizer(versionString, " "); + if (tok.hasMoreTokens()) { + tok.nextToken(); + if (tok.hasMoreTokens()) { + String token = tok.nextToken(); + int i = 0; + while (i < token.length() && !Character.isDigit(token.charAt(i))) { + i++; + } + if (i < token.length() - 2 && + Character.isDigit(token.charAt(i)) && + token.charAt(i+1) == '.' && + Character.isDigit(token.charAt(i+2))) { + int altMajor = Character.digit(token.charAt(i), radix); + int altMinor = Character.digit(token.charAt(i+2), radix); + // Avoid possibly confusing situations by putting some + // constraints on the upgrades we do to the major and + // minor versions + if ((altMajor == major && altMinor > minor) || + altMajor == major + 1) { + major = altMajor; + minor = altMinor; + } + } + } + } + } + } + } + valid = true; + } + catch (Exception e) + { + e.printStackTrace(); + // FIXME: refactor desktop OpenGL dependencies and make this + // class work properly for OpenGL ES + System.err.println("ExtensionAvailabilityCache: FunctionAvailabilityCache.Version.<init>: "+e); + major = 1; + minor = 0; + /* + throw (IllegalArgumentException) + new IllegalArgumentException( + "Illegally formatted version identifier: \"" + versionString + "\"") + .initCause(e); + */ + } + } + + public boolean isValid() { + return valid; + } + + public int compareTo(Object o) + { + Version vo = (Version)o; + if (major > vo.major) return 1; + else if (major < vo.major) return -1; + else if (minor > vo.minor) return 1; + else if (minor < vo.minor) return -1; + else if (sub > vo.sub) return 1; + else if (sub < vo.sub) return -1; + + return 0; // they are equal + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + } // end class Version + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java new file mode 100644 index 000000000..56a5b023f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextLock.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; + +/** Implements the makeCurrent / release locking behavior of the + GLContext class. When "fail fast mode" is enabled, attempts to + lock the same GLContextLock on more than one thread cause + GLException to be raised. This lock is not recursive. Attempts to + lock it more than once on a given thread will cause GLException to + be raised. */ + +public class GLContextLock { + private Object lock = new Object(); + private Thread owner; + private boolean failFastMode = true; + private volatile int waiters; + + /** Locks this GLContextLock on the current thread. If fail fast + mode is enabled and the GLContextLock is already owned by + another thread, throws GLException. */ + public void lock() throws GLException { + synchronized(lock) { + Thread current = Thread.currentThread(); + if (owner == null) { + owner = current; + } else if (owner != current) { + while (owner != null) { + if (failFastMode) { + throw new GLException("Attempt to make context current on thread " + current + + " which is already current on thread " + owner); + } else { + try { + ++waiters; + lock.wait(); + } catch (InterruptedException e) { + throw new GLException(e); + } finally { + --waiters; + } + } + } + owner = current; + } else { + throw new GLException("Attempt to make the same context current twice on thread " + current); + } + } + } + + /** Unlocks this GLContextLock. */ + public void unlock() throws GLException { + synchronized (lock) { + Thread current = Thread.currentThread(); + if (owner == current) { + owner = null; + lock.notifyAll(); + } else { + if (owner != null) { + throw new GLException("Attempt by thread " + current + + " to release context owned by thread " + owner); + } else { + throw new GLException("Attempt by thread " + current + + " to release unowned context"); + } + } + } + } + + /** Indicates whether this lock is held by the current thread. */ + public boolean isHeld() { + synchronized(lock) { + Thread current = Thread.currentThread(); + return (owner == current); + } + } + + public void setFailFastMode(boolean onOrOff) { + failFastMode = onOrOff; + } + + public boolean getFailFastMode() { + return failFastMode; + } + + public boolean hasWaiters() { + return (waiters != 0); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java new file mode 100644 index 000000000..abeb231f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextShareSet.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +// FIXME: refactor Java SE dependencies +// import java.awt.GraphicsConfiguration; +// import java.awt.GraphicsDevice; +// import java.awt.GraphicsEnvironment; +import java.lang.ref.*; +import java.util.*; +import javax.media.opengl.*; + +/** Provides a mechanism by which OpenGL contexts can share textures + and display lists in the face of multithreading and asynchronous + context creation as is inherent in the AWT and Swing. */ + +public class GLContextShareSet { + // FIXME: refactor Java SE dependencies + // private static boolean forceTracking = Debug.isPropertyDefined("jogl.glcontext.forcetracking"); + private static final boolean DEBUG = Debug.debug("GLContextShareSet"); + + // This class is implemented with a WeakHashMap that goes from the + // contexts as keys to a complex data structure as value that tracks + // context creation and deletion. + + private static Map/*<GLContext, ShareSet>*/ shareMap = new WeakHashMap(); + private static Object dummyValue = new Object(); + + private static class ShareSet { + private Map allShares = new WeakHashMap(); + private Map createdShares = new WeakHashMap(); + private Map destroyedShares = new WeakHashMap(); + + public void add(GLContext ctx) { + if (allShares.put(ctx, dummyValue) == null) { + // FIXME: downcast to GLContextImpl undesirable + if (((GLContextImpl) ctx).isCreated()) { + createdShares.put(ctx, dummyValue); + } else { + destroyedShares.put(ctx, dummyValue); + } + } + } + + public GLContext getCreatedShare(GLContext ignore) { + for (Iterator iter = createdShares.keySet().iterator(); iter.hasNext(); ) { + GLContext ctx = (GLContext) iter.next(); + if (ctx != ignore) { + return ctx; + } + } + return null; + } + + public void contextCreated(GLContext ctx) { + Object res = destroyedShares.remove(ctx); + assert res != null : "State of ShareSet corrupted; thought context " + + ctx + " should have been in destroyed set but wasn't"; + res = createdShares.put(ctx, dummyValue); + assert res == null : "State of ShareSet corrupted; thought context " + + ctx + " shouldn't have been in created set but was"; + } + + public void contextDestroyed(GLContext ctx) { + Object res = createdShares.remove(ctx); + assert res != null : "State of ShareSet corrupted; thought context " + + ctx + " should have been in created set but wasn't"; + res = destroyedShares.put(ctx, dummyValue); + assert res == null : "State of ShareSet corrupted; thought context " + + ctx + " shouldn't have been in destroyed set but was"; + } + } + + /** Indicate that contexts <code>share1</code> and + <code>share2</code> will share textures and display lists. Both + must be non-null. */ + public static synchronized void registerSharing(GLContext share1, GLContext share2) { + if (share1 == null || share2 == null) { + throw new IllegalArgumentException("Both share1 and share2 must be non-null"); + } + ShareSet share = entryFor(share1); + if (share == null) { + share = entryFor(share2); + } + if (share == null) { + share = new ShareSet(); + } + share.add(share1); + share.add(share2); + addEntry(share1, share); + addEntry(share2, share); + } + + public static synchronized GLContext getShareContext(GLContext contextToCreate) { + ShareSet share = entryFor(contextToCreate); + if (share == null) { + return null; + } + return share.getCreatedShare(contextToCreate); + } + + public static synchronized void contextCreated(GLContext context) { + ShareSet share = entryFor(context); + if (share != null) { + share.contextCreated(context); + } + } + + public static synchronized void contextDestroyed(GLContext context) { + ShareSet share = entryFor(context); + if (share != null) { + share.contextDestroyed(context); + } + } + + /** In order to avoid glGet calls for buffer object checks related + to glVertexPointer, etc. calls as well as glMapBuffer calls, we + need to share the same GLBufferSizeTracker object between + contexts sharing textures and display lists. For now we keep + this mechanism orthogonal to the GLObjectTracker to hopefully + keep things easier to understand. (The GLObjectTracker is + currently only needed in a fairly esoteric case, when the + Java2D/JOGL bridge is active, but the GLBufferSizeTracker + mechanism is now always required.) */ + public static void registerForBufferObjectSharing(GLContext olderContextOrNull, GLContext newContext) { + // FIXME: downcasts to GLContextImpl undesirable + GLContextImpl older = (GLContextImpl) olderContextOrNull; + GLContextImpl newer = (GLContextImpl) newContext; + GLBufferSizeTracker tracker = null; + if (older != null) { + tracker = older.getBufferSizeTracker(); + assert (tracker != null) + : "registerForBufferObjectSharing was not called properly for the older context, or has a bug in it"; + } + if (tracker == null) { + tracker = new GLBufferSizeTracker(); + } + newer.setBufferSizeTracker(tracker); + } + + // FIXME: refactor Java SE dependencies + // /** Indicates that the two supplied contexts (which must be able to + // share textures and display lists) should be in the same + // namespace for tracking of server-side object creation and + // deletion. Because the sharing necessary behind the scenes is + // different than that requested at the user level, the two notions + // are different. This must be called immediately after the + // creation of the new context (which is the second argument) + // before any server-side OpenGL objects have been created in that + // context. */ + // public static void registerForObjectTracking(GLContext olderContextOrNull, + // GLContext newContext, + // GLContext realShareContext) { + // if (isObjectTrackingEnabled() || isObjectTrackingDebuggingEnabled()) { + // GLContextImpl impl1 = null; + // GLContextImpl impl2 = null; + // GLObjectTracker tracker = null; + // + // synchronized (GLContextShareSet.class) { + // if (olderContextOrNull != null && + // newContext != null) { + // if (entryFor(olderContextOrNull) != entryFor(newContext)) { + // throw new IllegalArgumentException("old and new contexts must be able to share textures and display lists"); + // } + // } + // + // // FIXME: downcast to GLContextImpl undesirable + // impl1 = (GLContextImpl) olderContextOrNull; + // impl2 = (GLContextImpl) newContext; + // + // GLObjectTracker deletedObjectTracker = null; + // GLContextImpl shareImpl = (GLContextImpl) realShareContext; + // // Before we zap the "user-level" object trackers, make sure + // // that all contexts in the share set share the destroyed object + // // tracker + // if (shareImpl != null) { + // deletedObjectTracker = shareImpl.getDeletedObjectTracker(); + // } + // if (deletedObjectTracker == null) { + // // Must create one and possibly set it up in the older context + // deletedObjectTracker = new GLObjectTracker(); + // if (DEBUG) { + // System.err.println("Created deletedObjectTracker " + deletedObjectTracker + " because " + + // ((shareImpl == null) ? "shareImpl was null" : "shareImpl's (" + shareImpl + ") deletedObjectTracker was null")); + // } + // + // if (shareImpl != null) { + // // FIXME: think should really assert in this case + // shareImpl.setDeletedObjectTracker(deletedObjectTracker); + // if (DEBUG) { + // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in shareImpl context " + shareImpl); + // } + // } + // } + // impl2.setDeletedObjectTracker(deletedObjectTracker); + // if (DEBUG) { + // System.err.println("Set deletedObjectTracker " + deletedObjectTracker + " in impl2 context " + impl2); + // } + // } + // + // // Must not hold lock around this operation + // // Don't share object trackers with the primordial share context from Java2D + // if (Java2D.isOGLPipelineActive()) { + // // FIXME: probably need to do something different here + // // Need to be able to figure out the GraphicsDevice for the + // // older context if it's on-screen + // GraphicsDevice device = GraphicsEnvironment. + // getLocalGraphicsEnvironment(). + // getDefaultScreenDevice(); + // GLContext j2dShareContext = Java2D.getShareContext(device); + // if (impl1 != null && impl1 == j2dShareContext) { + // impl1 = null; + // } + // } + // + // synchronized (GLContextShareSet.class) { + // if (impl1 != null) { + // tracker = impl1.getObjectTracker(); + // assert (tracker != null) + // : "registerForObjectTracking was not called properly for the older context"; + // } + // if (tracker == null) { + // tracker = new GLObjectTracker(); + // } + // // Note that we don't assert that the tracker is non-null for + // // impl2 because the way we use this functionality we actually + // // overwrite the initially-set object tracker in the new context + // impl2.setObjectTracker(tracker); + // } + // } + // } + + //---------------------------------------------------------------------- + // Internals only below this point + + + private static ShareSet entryFor(GLContext context) { + return (ShareSet) shareMap.get(context); + } + + private static void addEntry(GLContext context, ShareSet share) { + if (shareMap.get(context) == null) { + shareMap.put(context, share); + } + } + + // FIXME: refactor Java SE dependencies + // private static boolean isObjectTrackingEnabled() { + // return ((Java2D.isOGLPipelineActive() && Java2D.isFBOEnabled()) || + // isObjectTrackingDebuggingEnabled()); + // } + // + // private static boolean isObjectTrackingDebuggingEnabled() { + // return forceTracking; + // } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java new file mode 100644 index 000000000..cdf5beb24 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.util.*; +import com.jogamp.gluegen.runtime.*; +import java.lang.reflect.*; + +/** Extends GLDrawableFactory with a few methods for handling + typically software-accelerated offscreen rendering (Device + Independent Bitmaps on Windows, pixmaps on X11). Direct access to + these GLDrawables is not supplied directly to end users, though + they may be instantiated by the GLJPanel implementation. */ +public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { + protected static final boolean DEBUG = Debug.debug("GLDrawableFactory"); + + private boolean isValid = false; + + public void shutdown() { + validate(); + isValid = false; + } + + protected final void validate() { + if(!isValid) { + throw new GLException("GLDrawableFactory is already shutdown!"); + } + } + + //--------------------------------------------------------------------------- + // Dispatching GLDrawable construction in respect to the NativeWindow Capabilities + // + public GLDrawable createGLDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + AbstractGraphicsConfiguration config = target.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities) target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + GLDrawable result = null; + if(caps.isOnscreen()) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target); + } + result = createOnscreenDrawable(target); + } else { + if( ! ( target instanceof SurfaceChangeable ) ) { + throw new IllegalArgumentException("Passed NativeWindow must implement SurfaceChangeable for offscreen: "+target); + } + if(caps.isPBuffer()) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> PbufferDrawable: "+target); + } + result = createGLPbufferDrawable(target); + } + if(null==result) { + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable: "+target); + } + result = createOffscreenDrawable(target); + } + } + if(DEBUG) { + System.out.println("GLDrawableFactoryImpl.createGLDrawable: "+result); + } + return result; + } + + //--------------------------------------------------------------------------- + // + // Onscreen GLDrawable construction + // + + protected abstract GLDrawableImpl createOnscreenDrawable(NativeWindow target); + + //--------------------------------------------------------------------------- + // + // PBuffer GLDrawable construction + // + + /** Target must implement SurfaceChangeable */ + protected abstract GLDrawableImpl createGLPbufferDrawableImpl(NativeWindow target); + + protected GLDrawableImpl createGLPbufferDrawable(NativeWindow target) { + if (!canCreateGLPbuffer(target.getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice())) { + throw new GLException("Pbuffer support not available with current graphics card"); + } + return createGLPbufferDrawableImpl(target); + } + + public GLDrawable createGLPbufferDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height) { + validate(); + if(height<=0 || height<=0) { + throw new GLException("Width and height of pbuffer must be positive (were (" + + width + ", " + height + "))"); + } + capabilities.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + capabilities.setOnscreen(false); + capabilities.setPBuffer(true); + return createGLPbufferDrawable( createOffscreenWindow(capabilities, chooser, height, height) ); + } + + public GLPbuffer createGLPbuffer(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height, + GLContext shareWith) { + validate(); + return new GLPbufferImpl( (GLDrawableImpl) createGLPbufferDrawable(capabilities, chooser, height, height), + shareWith); + } + + + //--------------------------------------------------------------------------- + // + // Offscreen GLDrawable construction + // + + protected abstract GLDrawableImpl createOffscreenDrawable(NativeWindow target) ; + + public GLDrawable createOffscreenDrawable(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + int width, + int height) { + validate(); + if(width<=0 || height<=0) { + throw new GLException("Width and height of pbuffer must be positive (were (" + + width + ", " + height + "))"); + } + capabilities.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + capabilities.setOnscreen(false); + capabilities.setPBuffer(false); + return createOffscreenDrawable( createOffscreenWindow(capabilities, chooser, width, height) ); + } + + /** + * creates an offscreen NativeWindow, which must implement SurfaceChangeable as well, + * so the windowing system related implementation is able to set the surface handle. + */ + protected abstract NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, + int width, int height); + + protected abstract GLDrawableImpl getSharedDrawable(); + protected abstract GLContextImpl getSharedContext(); + + protected GLDrawableFactoryImpl() { + super(); + isValid = true; + } + + protected void maybeDoSingleThreadedWorkaround(Runnable action) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(action); + } else { + action.run(); + } + } + + /** + * Returns the sole GLDrawableFactoryImpl instance. + * + * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory, + * or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL. + */ + public static GLDrawableFactoryImpl getFactoryImpl(GLProfile glp) { + return (GLDrawableFactoryImpl) getFactory(glp); + } + + // Helper function for more lazily loading the GLU library; + // apparently can't use System.loadLibrary on UNIX because it uses + // RTLD_LOCAL and we need to call dlsym(RTLD_DEFAULT) + public abstract void loadGLULibrary(); + + //---------------------------------------------------------------------- + // Support for locking and unlocking the toolkit -- needed only on X11 platforms + // + + public void lockToolkit() { + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + } + + public void unlockToolkit() { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + //--------------------------------------------------------------------------- + // Support for Java2D/JOGL bridge on Mac OS X; the external + // GLDrawable mechanism in the public API is sufficient to + // implement this functionality on all other platforms + // + + public abstract boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device); + + public abstract GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException; + + //---------------------------------------------------------------------- + // Gamma adjustment support + // Thanks to the LWJGL team for illustrating how to make these + // adjustments on various OSs. + + /* + * Portions Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + + /** + * Sets the gamma, brightness, and contrast of the current main + * display. Returns true if the settings were changed, false if + * not. If this method returns true, the display settings will + * automatically be reset upon JVM exit (assuming the JVM does not + * crash); if the user wishes to change the display settings back to + * normal ahead of time, use resetDisplayGamma(). Throws + * IllegalArgumentException if any of the parameters were + * out-of-bounds. + * + * @param gamma The gamma value, typically > 1.0 (default value is + * 1.0) + * @param brightness The brightness value between -1.0 and 1.0, + * inclusive (default value is 0) + * @param contrast The contrast, greater than 0.0 (default value is 1) + * @throws IllegalArgumentException if any of the parameters were + * out-of-bounds + */ + public boolean setDisplayGamma(float gamma, float brightness, float contrast) throws IllegalArgumentException { + validate(); + if ((brightness < -1.0f) || (brightness > 1.0f)) { + throw new IllegalArgumentException("Brightness must be between -1.0 and 1.0"); + } + if (contrast < 0) { + throw new IllegalArgumentException("Contrast must be greater than 0.0"); + } + // FIXME: ensure gamma is > 1.0? Are smaller / negative values legal? + int rampLength = getGammaRampLength(); + if (rampLength == 0) { + return false; + } + float[] gammaRamp = new float[rampLength]; + for (int i = 0; i < rampLength; i++) { + float intensity = (float) i / (float) (rampLength - 1); + // apply gamma + float rampEntry = (float) java.lang.Math.pow(intensity, gamma); + // apply brightness + rampEntry += brightness; + // apply contrast + rampEntry = (rampEntry - 0.5f) * contrast + 0.5f; + // Clamp entry to [0, 1] + if (rampEntry > 1.0f) + rampEntry = 1.0f; + else if (rampEntry < 0.0f) + rampEntry = 0.0f; + gammaRamp[i] = rampEntry; + } + registerGammaShutdownHook(); + return setGammaRamp(gammaRamp); + } + + public synchronized void resetDisplayGamma() { + validate(); + if (gammaShutdownHook == null) { + throw new IllegalArgumentException("Should not call this unless setDisplayGamma called first"); + } + resetGammaRamp(originalGammaRamp); + unregisterGammaShutdownHook(); + } + + //------------------------------------------------------ + // Gamma-related methods to be implemented by subclasses + // + + /** Returns the length of the computed gamma ramp for this OS and + hardware. Returns 0 if gamma changes are not supported. */ + protected int getGammaRampLength() { + return 0; + } + + /** Sets the gamma ramp for the main screen. Returns false if gamma + ramp changes were not supported. */ + protected boolean setGammaRamp(float[] ramp) { + return false; + } + + /** Gets the current gamma ramp. This is basically an opaque value + used only on some platforms to reset the gamma ramp to its + original settings. */ + protected Buffer getGammaRamp() { + return null; + } + + /** Resets the gamma ramp, potentially using the specified Buffer as + data to restore the original values. */ + protected void resetGammaRamp(Buffer originalGammaRamp) { + } + + // Shutdown hook mechanism for resetting gamma + private boolean gammaShutdownHookRegistered; + private Thread gammaShutdownHook; + private Buffer originalGammaRamp; + private synchronized void registerGammaShutdownHook() { + if (gammaShutdownHookRegistered) + return; + if (gammaShutdownHook == null) { + gammaShutdownHook = new Thread(new Runnable() { + public void run() { + synchronized (GLDrawableFactoryImpl.this) { + resetGammaRamp(originalGammaRamp); + } + } + }); + originalGammaRamp = getGammaRamp(); + } + Runtime.getRuntime().addShutdownHook(gammaShutdownHook); + gammaShutdownHookRegistered = true; + } + + private synchronized void unregisterGammaShutdownHook() { + if (!gammaShutdownHookRegistered) + return; + if (gammaShutdownHook == null) { + throw new InternalError("Error in gamma shutdown hook logic"); + } + Runtime.getRuntime().removeShutdownHook(gammaShutdownHook); + gammaShutdownHookRegistered = false; + // Leave the original gamma ramp data alone + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java new file mode 100644 index 000000000..7a4e84081 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableHelper.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** Encapsulates the implementation of most of the GLAutoDrawable's + methods to be able to share it between GLCanvas and GLJPanel. */ + +public class GLDrawableHelper { + private volatile List listeners = new ArrayList(); + private static final boolean DEBUG = Debug.debug("GLDrawableHelper"); + private static final boolean VERBOSE = Debug.verbose(); + private static final boolean NVIDIA_CRASH_WORKAROUND = Debug.isPropertyDefined("jogl.nvidia.crash.workaround", true); + private boolean autoSwapBufferMode = true; + + public GLDrawableHelper() { + } + + public synchronized String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("GLEventListeners num "+listeners.size()+" ["); + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + sb.append(iter.next()+", "); + } + sb.append("]"); + return sb.toString(); + } + + public synchronized void addGLEventListener(GLEventListener listener) { + List newListeners = (List) ((ArrayList) listeners).clone(); + newListeners.add(listener); + listeners = newListeners; + } + + public synchronized void removeGLEventListener(GLEventListener listener) { + List newListeners = (List) ((ArrayList) listeners).clone(); + newListeners.remove(listener); + listeners = newListeners; + } + + public synchronized void dispose(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).dispose(drawable); + } + } + + public void init(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).init(drawable); + } + } + + public void display(GLAutoDrawable drawable) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).display(drawable); + } + } + + public void reshape(GLAutoDrawable drawable, + int x, int y, int width, int height) { + for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { + ((GLEventListener) iter.next()).reshape(drawable, x, y, width, height); + } + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + autoSwapBufferMode = onOrOff; + } + + public boolean getAutoSwapBufferMode() { + return autoSwapBufferMode; + } + + private static final ThreadLocal perThreadInitAction = new ThreadLocal(); + /** Principal helper method which runs a Runnable with the context + made current. This could have been made part of GLContext, but a + desired goal is to be able to implement the GLCanvas in terms of + the GLContext's public APIs, and putting it into a separate + class helps ensure that we don't inadvertently use private + methods of the GLContext or its implementing classes. */ + public void invokeGL(GLDrawable drawable, + GLContext context, + Runnable runnable, + Runnable initAction) { + if(null==context) { + if (DEBUG) { + Exception e = new GLException(Thread.currentThread().getName()+" GLDrawableHelper " + this + ".invokeGL(): NULL GLContext"); + e.printStackTrace(); + } + return; + } + // Support for recursive makeCurrent() calls as well as calling + // other drawables' display() methods from within another one's + GLContext lastContext = GLContext.getCurrent(); + Runnable lastInitAction = (Runnable) perThreadInitAction.get(); + if (lastContext != null) { + lastContext.release(); + } + + int res = 0; + try { + res = context.makeCurrent(); + if (res != GLContext.CONTEXT_NOT_CURRENT) { + if(null!=initAction) { + perThreadInitAction.set(initAction); + if (res == GLContext.CONTEXT_CURRENT_NEW) { + if (DEBUG) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running initAction"); + } + initAction.run(); + } + } + if(null!=runnable) { + if (DEBUG && VERBOSE) { + System.err.println("GLDrawableHelper " + this + ".invokeGL(): Running runnable"); + } + runnable.run(); + if (autoSwapBufferMode) { + if (drawable != null) { + drawable.swapBuffers(); + } + } + } + } + } finally { + try { + if (res != GLContext.CONTEXT_NOT_CURRENT) { + context.release(); + } + } catch (Exception e) { + } + if (lastContext != null) { + int res2 = lastContext.makeCurrent(); + if (res2 == GLContext.CONTEXT_CURRENT_NEW) { + lastInitAction.run(); + } + } + } + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java new file mode 100644 index 000000000..2fef8fd80 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableImpl.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import com.jogamp.common.os.DynamicLookupHelper; +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +public abstract class GLDrawableImpl implements GLDrawable { + protected static final boolean DEBUG = Debug.debug("GLDrawable"); + + protected GLDrawableImpl(GLDrawableFactory factory, + NativeWindow comp, + boolean realized) { + this.factory = factory; + this.component = comp; + this.realized = realized; + this.requestedCapabilities = (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getRequestedCapabilities(); // a copy .. + } + + /** + * Returns the DynamicLookupHelper + */ + public abstract DynamicLookupHelper getDynamicLookupHelper(); + + public GLDrawableFactoryImpl getFactoryImpl() { + return (GLDrawableFactoryImpl) getFactory(); + } + + /** For offscreen GLDrawables (pbuffers and "pixmap" drawables), + indicates that native resources should be reclaimed. */ + public void destroy() { + throw new GLException("Should not call this (should only be called for offscreen GLDrawables)"); + } + + public void swapBuffers() throws GLException { + GLCapabilities caps = (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!component.surfaceSwap()) { + swapBuffersImpl(); + } + } else { + GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFinish(); + } + } + component.surfaceUpdated(this, component, System.currentTimeMillis()); + } + + protected abstract void swapBuffersImpl(); + + public static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } + + public GLProfile getGLProfile() { + return requestedCapabilities.getGLProfile(); + } + + public GLCapabilities getChosenGLCapabilities() { + return (GLCapabilities)component.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); // a copy + } + + public GLCapabilities getRequestedGLCapabilities() { + return requestedCapabilities; + } + + public NativeWindow getNativeWindow() { + return component; + } + + public GLDrawableFactory getFactory() { + return factory; + } + + public void setRealized(boolean realized) { + if ( this.realized != realized ) { + if(DEBUG) { + System.err.println("setRealized: "+getClass().getName()+" "+this.realized+" -> "+realized); + } + this.realized = realized; + setRealizedImpl(); + } else if(DEBUG) { + System.err.println("setRealized: "+getClass().getName()+" "+this.realized+" == "+realized); + } + } + protected abstract void setRealizedImpl(); + + public boolean getRealized() { + return realized; + } + + public int getWidth() { + return component.getWidth(); + } + + /** Returns the current height of this GLDrawable. */ + public int getHeight() { + return component.getHeight(); + } + + public int lockSurface() throws GLException { + if (!realized) { + return NativeWindow.LOCK_SURFACE_NOT_READY; + } + return component.lockSurface(); + } + + public void unlockSurface() { + component.unlockSurface(); + } + + public boolean isSurfaceLocked() { + return component.isSurfaceLocked(); + } + + public String toString() { + return getClass().getName()+"[Realized "+getRealized()+ + ",\n\tFactory "+getFactory()+ + ",\n\tWindow "+getNativeWindow()+"]"; + } + + protected GLDrawableFactory factory; + protected NativeWindow component; + protected GLCapabilities requestedCapabilities; + + // Indicates whether the component (if an onscreen context) has been + // realized. Plausibly, before the component is realized the JAWT + // should return an error or NULL object from some of its + // operations; this appears to be the case on Win32 but is not true + // at least with Sun's current X11 implementation (1.4.x), which + // crashes with no other error reported if the DrawingSurfaceInfo is + // fetched from a locked DrawingSurface during the validation as a + // result of calling show() on the main thread. To work around this + // we prevent any JAWT or OpenGL operations from being done until + // addNotify() is called on the component. + protected boolean realized; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java b/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java new file mode 100644 index 000000000..c3958eedf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLJNILibLoader.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +// FIXME: refactor Java SE dependencies +//import java.awt.Toolkit; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashSet; +import com.jogamp.common.jvm.JNILibLoaderBase; + +public class GLJNILibLoader extends JNILibLoaderBase { + public static void loadNEWT() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("newt", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadGLDesktop() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_desktop", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadGLDesktopES12() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_gl2es12", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadES2() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_es2", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadES1() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + loadLibrary("jogl_es1", nativeOSPreload, true); + return null; + } + }); + } + + public static void loadCgImpl() { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String[] preload = { "nativewindow", "cg", "cgGL" }; + loadLibrary("jogl_cg", preload, true); + return null; + } + }); + } + + private static final String[] nativeOSPreload = { "nativewindow_x11" }; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java new file mode 100644 index 000000000..dd8d980a6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLPbufferImpl.java @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +/** +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.event.*; +import java.beans.PropertyChangeListener; + */ + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +/** Platform-independent class exposing pbuffer functionality to + applications. This class is not exposed in the public API as it + would probably add no value; however it implements the GLDrawable + interface so can be interacted with via its display() method. */ + +public class GLPbufferImpl implements GLPbuffer { + private GLDrawableImpl pbufferDrawable; + private GLContextImpl context; + private GLDrawableHelper drawableHelper = new GLDrawableHelper(); + private int floatMode; + + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, + GLContext parentContext) { + GLCapabilities caps = (GLCapabilities) + pbufferDrawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if(caps.isOnscreen()) { + if(caps.isPBuffer()) { + throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable); + } + throw new IllegalArgumentException("Error: Given drawable is Onscreen: "+pbufferDrawable); + } else { + if(!caps.isPBuffer()) { + throw new IllegalArgumentException("Error: Given drawable is not Pbuffer: "+pbufferDrawable); + } + } + this.pbufferDrawable = pbufferDrawable; + context = (GLContextImpl) pbufferDrawable.createContext(parentContext); + context.setSynchronized(true); + } + + public GLContext createContext(GLContext shareWith) { + return pbufferDrawable.createContext(shareWith); + } + + public void setRealized(boolean realized) { + } + + public void setSize(int width, int height) { + // FIXME + throw new GLException("Not yet implemented"); + } + + public NativeWindow getNativeWindow() { + return pbufferDrawable.getNativeWindow(); + } + + public GLDrawableFactory getFactory() { + return pbufferDrawable.getFactory(); + } + + public int getWidth() { + return pbufferDrawable.getWidth(); + } + + public int getHeight() { + return pbufferDrawable.getHeight(); + } + + public void display() { + maybeDoSingleThreadedWorkaround(displayOnEventDispatchThreadAction, + displayAction, + false); + } + + public void repaint() { + display(); + } + + public void addGLEventListener(GLEventListener listener) { + drawableHelper.addGLEventListener(listener); + } + + public void removeGLEventListener(GLEventListener listener) { + drawableHelper.removeGLEventListener(listener); + } + + public void setContext(GLContext ctx) { + context=(GLContextImpl)ctx; + } + + public GLContext getContext() { + return context; + } + + public GLDrawable getDrawable() { + return pbufferDrawable; + } + + public GL getGL() { + return getContext().getGL(); + } + + public GL setGL(GL gl) { + return getContext().setGL(gl); + } + + public void setAutoSwapBufferMode(boolean onOrOff) { + drawableHelper.setAutoSwapBufferMode(onOrOff); + } + + public boolean getAutoSwapBufferMode() { + return drawableHelper.getAutoSwapBufferMode(); + } + + public void swapBuffers() { + maybeDoSingleThreadedWorkaround(swapBuffersOnEventDispatchThreadAction, swapBuffersAction, false); + } + + public void bindTexture() { + // Doesn't make much sense to try to do this on the event dispatch + // thread given that it has to be called while the context is current + context.bindPbufferToTexture(); + } + + public void releaseTexture() { + // Doesn't make much sense to try to do this on the event dispatch + // thread given that it has to be called while the context is current + context.releasePbufferFromTexture(); + } + + public GLCapabilities getChosenGLCapabilities() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getChosenGLCapabilities(); + } + + public GLCapabilities getRequestedGLCapabilities() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getRequestedGLCapabilities(); + } + + public GLProfile getGLProfile() { + if (pbufferDrawable == null) + return null; + + return pbufferDrawable.getGLProfile(); + } + + private boolean surfaceLocked = false; + + public int lockSurface() throws GLException { + surfaceLocked=true; + return NativeWindow.LOCK_SUCCESS; + } + + public void unlockSurface() { + surfaceLocked=false; + } + + public boolean isSurfaceLocked() { + return surfaceLocked; + } + + //---------------------------------------------------------------------- + // No-ops for ComponentEvents + // + + /* + public void addComponentListener(ComponentListener l) {} + public void removeComponentListener(ComponentListener l) {} + public void addFocusListener(FocusListener l) {} + public void removeFocusListener(FocusListener l) {} + public void addHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void removeHierarchyBoundsListener(HierarchyBoundsListener l) {} + public void addHierarchyListener(HierarchyListener l) {} + public void removeHierarchyListener(HierarchyListener l) {} + public void addInputMethodListener(InputMethodListener l) {} + public void removeInputMethodListener(InputMethodListener l) {} + public void addKeyListener(KeyListener l) {} + public void removeKeyListener(KeyListener l) {} + public void addMouseListener(MouseListener l) {} + public void removeMouseListener(MouseListener l) {} + public void addMouseMotionListener(MouseMotionListener l) {} + public void removeMouseMotionListener(MouseMotionListener l) {} + public void addMouseWheelListener(MouseWheelListener l) {} + public void removeMouseWheelListener(MouseWheelListener l) {} + public void addPropertyChangeListener(PropertyChangeListener listener) {} + public void removePropertyChangeListener(PropertyChangeListener listener) {} + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) {} + */ + + public void destroy() { + // FIXME: not calling event listeners .. see GLAutoDrawable spec + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(destroyAction); + } else { + destroyAction.run(); + } + } + + public int getFloatingPointMode() { + if (floatMode == 0) { + throw new GLException("Pbuffer not initialized, or floating-point support not requested"); + } + return floatMode; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void maybeDoSingleThreadedWorkaround(Runnable eventDispatchThreadAction, + Runnable invokeGLAction, + boolean isReshape) { + if (Threading.isSingleThreaded() && + !Threading.isOpenGLThread()) { + Threading.invokeOnOpenGLThread(eventDispatchThreadAction); + } else { + drawableHelper.invokeGL(pbufferDrawable, context, invokeGLAction, initAction); + } + } + + class InitAction implements Runnable { + public void run() { + floatMode = context.getFloatingPointMode(); + drawableHelper.init(GLPbufferImpl.this); + } + } + private InitAction initAction = new InitAction(); + + class DisplayAction implements Runnable { + public void run() { + drawableHelper.display(GLPbufferImpl.this); + } + } + private DisplayAction displayAction = new DisplayAction(); + + class SwapBuffersAction implements Runnable { + public void run() { + pbufferDrawable.swapBuffers(); + } + } + private SwapBuffersAction swapBuffersAction = new SwapBuffersAction(); + + // Workaround for ATI driver bugs related to multithreading issues + // like simultaneous rendering via Animators to canvases that are + // being resized on the AWT event dispatch thread + class DisplayOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(pbufferDrawable, context, displayAction, initAction); + } + } + private DisplayOnEventDispatchThreadAction displayOnEventDispatchThreadAction = + new DisplayOnEventDispatchThreadAction(); + class SwapBuffersOnEventDispatchThreadAction implements Runnable { + public void run() { + drawableHelper.invokeGL(pbufferDrawable, context, swapBuffersAction, initAction); + } + } + private SwapBuffersOnEventDispatchThreadAction swapBuffersOnEventDispatchThreadAction = + new SwapBuffersOnEventDispatchThreadAction(); + + class DestroyAction implements Runnable { + public void run() { + if (null != context) { + context.destroy(); + } + pbufferDrawable.destroy(); + } + } + private DestroyAction destroyAction = new DestroyAction(); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java new file mode 100755 index 000000000..744e7b924 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLStateTracker.java @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.util.*; +import javax.media.opengl.*; + +/** + * Tracks as closely as possible OpenGL states. + * GLStateTracker objects are allocated on a per-OpenGL-context basis. + * <p> + * Currently supported states: PixelStorei + */ + +public class GLStateTracker { + private static final boolean DEBUG = Debug.debug("GLStateTracker"); + + private volatile boolean enabled = true; + + private Map/*<Integer,Integer>*/ pixelStateMap = new HashMap/*<Integer,Integer>*/(); + + static class SavedState { + SavedState() { + this.pixelStateMap = null; + } + void putPixelStateMap(Map pixelStateMap) { + this.pixelStateMap = new HashMap(); + this.pixelStateMap.putAll(pixelStateMap); + } + Map getPixelStateMap() { return pixelStateMap; } + + private Map pixelStateMap; + // private Map otherStateMap; + } + private List/*<SavedState>*/ stack = new ArrayList(); + + public GLStateTracker() { + resetStates(); + } + + public void clearStates(boolean enable) { + enabled = enable; + pixelStateMap.clear(); + } + + public void setEnabled(boolean on) { + enabled = on; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean getInt(int pname, int[] params, int params_offset) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + Integer value = (Integer) pixelStateMap.get(key); + if(null!=value) { + params[params_offset] = value.intValue(); + } else { + GLException re = new GLException("Key (0x"+Integer.toHexString(key.intValue())+") is not mapped"); + throw re; + } + return true; + } + } + return false; + } + + public boolean getInt(int pname, java.nio.IntBuffer params, int dummy) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + Integer value = (Integer) pixelStateMap.get(key); + if(null!=value) { + params.put(params.position(), value.intValue()); + } else { + GLException re = new GLException("Key (0x"+Integer.toHexString(key.intValue())+") is not mapped"); + throw re; + } + return true; + } + } + return false; + } + + public void setInt(int pname, int param) { + if(enabled) { + Integer key = boxKey(pname); + if(null!=key) { + pixelStateMap.put(key, boxInt(param)); + } + } + } + + public void pushAttrib(int flags) { + if(enabled) { + SavedState state = new SavedState(); + if( 0 != (flags&GL2.GL_CLIENT_PIXEL_STORE_BIT) ) { + state.putPixelStateMap(pixelStateMap); + } + stack.add(0, state); + } + } + + public void popAttrib() { + if(enabled) { + if(stack.size()==0) { + throw new GLException("stack contains no elements"); + } + SavedState state = (SavedState) stack.remove(0); + if(null==state) { + throw new GLException("null stack element (remaining stack size "+stack.size()+")"); + } + + Map/*<Integer,Integer>*/ pixelStateMapNew = new HashMap/*<Integer,Integer>*/(); + if ( null != state.getPixelStateMap() ) { + pixelStateMapNew.putAll(state.getPixelStateMap()); + } + pixelStateMap = pixelStateMapNew; + } + } + + private static final Integer GL_PACK_SWAP_BYTES = new Integer(GL2GL3.GL_PACK_SWAP_BYTES); + private static final Integer GL_PACK_LSB_FIRST = new Integer(GL2GL3.GL_PACK_LSB_FIRST); + private static final Integer GL_PACK_ROW_LENGTH = new Integer(GL2GL3.GL_PACK_ROW_LENGTH); + private static final Integer GL_PACK_SKIP_ROWS = new Integer(GL2GL3.GL_PACK_SKIP_ROWS); + private static final Integer GL_PACK_SKIP_PIXELS = new Integer(GL2GL3.GL_PACK_SKIP_PIXELS); + private static final Integer GL_PACK_ALIGNMENT = new Integer(GL.GL_PACK_ALIGNMENT); + private static final Integer GL_PACK_IMAGE_HEIGHT = new Integer(GL2GL3.GL_PACK_IMAGE_HEIGHT); + private static final Integer GL_PACK_SKIP_IMAGES = new Integer(GL2GL3.GL_PACK_SKIP_IMAGES); + + private static final Integer GL_UNPACK_SWAP_BYTES = new Integer(GL2GL3.GL_UNPACK_SWAP_BYTES); + private static final Integer GL_UNPACK_LSB_FIRST = new Integer(GL2GL3.GL_UNPACK_LSB_FIRST); + private static final Integer GL_UNPACK_ROW_LENGTH = new Integer(GL2GL3.GL_UNPACK_ROW_LENGTH); + private static final Integer GL_UNPACK_SKIP_ROWS = new Integer(GL2GL3.GL_UNPACK_SKIP_ROWS); + private static final Integer GL_UNPACK_SKIP_PIXELS = new Integer(GL2GL3.GL_UNPACK_SKIP_PIXELS); + private static final Integer GL_UNPACK_ALIGNMENT = new Integer(GL.GL_UNPACK_ALIGNMENT); + private static final Integer GL_UNPACK_IMAGE_HEIGHT = new Integer(GL2GL3.GL_UNPACK_IMAGE_HEIGHT); + private static final Integer GL_UNPACK_SKIP_IMAGES = new Integer(GL2GL3.GL_UNPACK_SKIP_IMAGES); + + private static final Integer zero = new Integer(0); + private static final Integer one = new Integer(1); + + private static Integer boxKey(int key) { + switch (key) { + case 0: return zero; + case GL2GL3.GL_PACK_SWAP_BYTES: return GL_PACK_SWAP_BYTES; + case GL2GL3.GL_PACK_LSB_FIRST: return GL_PACK_LSB_FIRST; + case GL2GL3.GL_PACK_ROW_LENGTH: return GL_PACK_ROW_LENGTH; + case GL2GL3.GL_PACK_SKIP_ROWS: return GL_PACK_SKIP_ROWS; + case GL2GL3.GL_PACK_SKIP_PIXELS: return GL_PACK_SKIP_PIXELS; + case GL.GL_PACK_ALIGNMENT: return GL_PACK_ALIGNMENT; + case GL2GL3.GL_PACK_IMAGE_HEIGHT: return GL_PACK_IMAGE_HEIGHT; + case GL2GL3.GL_PACK_SKIP_IMAGES: return GL_PACK_SKIP_IMAGES; + + case GL2GL3.GL_UNPACK_SWAP_BYTES: return GL_UNPACK_SWAP_BYTES; + case GL2GL3.GL_UNPACK_LSB_FIRST: return GL_UNPACK_LSB_FIRST; + case GL2GL3.GL_UNPACK_ROW_LENGTH: return GL_UNPACK_ROW_LENGTH; + case GL2GL3.GL_UNPACK_SKIP_ROWS: return GL_UNPACK_SKIP_ROWS; + case GL2GL3.GL_UNPACK_SKIP_PIXELS: return GL_UNPACK_SKIP_PIXELS; + case GL.GL_UNPACK_ALIGNMENT: return GL_UNPACK_ALIGNMENT; + case GL2GL3.GL_UNPACK_IMAGE_HEIGHT: return GL_UNPACK_IMAGE_HEIGHT; + case GL2GL3.GL_UNPACK_SKIP_IMAGES: return GL_UNPACK_SKIP_IMAGES; + + default: return null; + } + } + + public void resetStates() { + pixelStateMap.clear(); + + pixelStateMap.put(GL_PACK_SWAP_BYTES, zero /* GL_FALSE */); + pixelStateMap.put(GL_PACK_LSB_FIRST, zero /* GL_FALSE */); + pixelStateMap.put(GL_PACK_ROW_LENGTH, zero); + pixelStateMap.put(GL_PACK_SKIP_ROWS, zero); + pixelStateMap.put(GL_PACK_SKIP_PIXELS, zero); + pixelStateMap.put(GL_PACK_ALIGNMENT, new Integer(4)); + pixelStateMap.put(GL_PACK_IMAGE_HEIGHT, zero); + pixelStateMap.put(GL_PACK_SKIP_IMAGES, zero); + + pixelStateMap.put(GL_UNPACK_SWAP_BYTES, zero /* GL_FALSE */); + pixelStateMap.put(GL_UNPACK_LSB_FIRST, zero /* GL_FALSE */); + pixelStateMap.put(GL_UNPACK_ROW_LENGTH, zero); + pixelStateMap.put(GL_UNPACK_SKIP_ROWS, zero); + pixelStateMap.put(GL_UNPACK_SKIP_PIXELS, zero); + pixelStateMap.put(GL_UNPACK_ALIGNMENT, new Integer(4)); + pixelStateMap.put(GL_UNPACK_IMAGE_HEIGHT, zero); + pixelStateMap.put(GL_UNPACK_SKIP_IMAGES, zero); + } + + private static Integer boxInt(int value) { + switch (value) { + case 0: return zero; + case 1: return one; + + default: return new Integer(value); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java b/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java new file mode 100755 index 000000000..768eea3f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLWorkerThread.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.InvocationTargetException; +import java.security.*; +import java.util.*; +import javax.media.opengl.*; + +/** Singleton thread upon which all OpenGL work is performed by + default. Unfortunately many vendors' OpenGL drivers are not really + thread-safe and stability is much improved by performing OpenGL + work on at most one thread. This is the default behavior of the + GLAutoDrawable implementations according to the {@link + javax.media.opengl.Threading Threading} class. The GLWorkerThread + replaces the original AWT event queue thread-based mechanism for + two reasons: first, more than one AWT event queue thread may be + spawned, for example if a dialog is being shown; second, it avoids + blocking the AWT event queue thread during OpenGL rendering. */ + +public class GLWorkerThread { + private static volatile boolean started; + private static volatile Thread thread; + private static Object lock; + private static volatile boolean shouldTerminate; + private static volatile Throwable exception; + + // The Runnable to execute immediately on the worker thread + private static volatile Runnable work; + // Queue of Runnables to be asynchronously invoked + private static List queue = new LinkedList(); + + /** Should only be called by Threading class if creation of the + GLWorkerThread was requested via the opengl.1thread system + property. */ + public static void start() { + if (!started) { + synchronized (GLWorkerThread.class) { + if (!started) { + lock = new Object(); + thread = new Thread(new WorkerRunnable(), + "JOGL GLWorkerThread"); + thread.setDaemon(true); + started = true; + synchronized (lock) { + thread.start(); + try { + lock.wait(); + } catch (InterruptedException e) { + } + } + + /* + + // Note: it appears that there is a bug in NVidia's current + // drivers where if a context was ever made current on a + // given thread and that thread has exited before program + // exit, a crash occurs in the drivers. Releasing the + // context from the given thread does not work around the + // problem. + // + // For the time being, we're going to work around this + // problem by not terminating the GLWorkerThread. In theory, + // shutting down the GLWorkerThread cleanly could be a good + // general solution to the problem of needing to + // cooperatively terminate all Animators at program exit. + // + // It appears that this doesn't even work around all of the + // kinds of crashes. Causing the context to be unilaterally + // released from the GLWorkerThread after each invocation + // seems to work around all of the kinds of crashes seen. + // + // These appear to be similar to the kinds of crashes seen + // when the Java2D/OpenGL pipeline terminates, and those are + // a known issue being fixed, so presumably these will be + // fixed in NVidia's next driver set. + + // Install shutdown hook to terminate daemon thread more or + // less cooperatively + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + Object lockTemp = lock; + if (lockTemp == null) { + // Already terminating (?) + return; + } + synchronized (lockTemp) { + shouldTerminate = true; + lockTemp.notifyAll(); + try { + lockTemp.wait(500); + } catch (InterruptedException e) { + } + } + } + }); + return null; + } + }); + + */ + + } else { + throw new RuntimeException("Should not start GLWorkerThread twice"); + } + } + } + } + + public static void invokeAndWait(Runnable runnable) + throws InvocationTargetException, InterruptedException { + if (!started) { + throw new RuntimeException("May not invokeAndWait on worker thread without starting it first"); + } + + Object lockTemp = lock; + if (lockTemp == null) { + return; // Terminating + } + + synchronized (lockTemp) { + if (thread == null) { + // Terminating + return; + } + + work = runnable; + lockTemp.notifyAll(); + lockTemp.wait(); + if (exception != null) { + Throwable localException = exception; + exception = null; + throw new InvocationTargetException(localException); + } + } + } + + public static void invokeLater(Runnable runnable) { + if (!started) { + throw new RuntimeException("May not invokeLater on worker thread without starting it first"); + } + + Object lockTemp = lock; + if (lockTemp == null) { + return; // Terminating + } + + synchronized (lockTemp) { + if (thread == null) { + // Terminating + return; + } + + queue.add(runnable); + lockTemp.notifyAll(); + } + } + + /** Indicates whether the OpenGL worker thread was started, i.e., + whether it is currently in use. */ + public static boolean isStarted() { + return started; + } + + /** Indicates whether the current thread is the OpenGL worker + thread. */ + public static boolean isWorkerThread() { + return (Thread.currentThread() == thread); + } + + static class WorkerRunnable implements Runnable { + public void run() { + // Notify starting thread that we're ready + synchronized (lock) { + lock.notifyAll(); + } + + while (!shouldTerminate) { + synchronized (lock) { + while (!shouldTerminate && + (work == null) && + queue.isEmpty()) { + try { + // Avoid race conditions with wanting to release contexts on this thread + lock.wait(1000); + } catch (InterruptedException e) { + } + + if (GLContext.getCurrent() != null) { + // Test later to see whether we need to release this context + break; + } + } + + if (shouldTerminate) { + lock.notifyAll(); + thread = null; + lock = null; + return; + } + + if (work != null) { + try { + work.run(); + } catch (Throwable t) { + exception = t; + } finally { + work = null; + lock.notifyAll(); + } + } + + while (!queue.isEmpty()) { + try { + Runnable curAsync = (Runnable) queue.remove(0); + curAsync.run(); + } catch (Throwable t) { + System.out.println("Exception occurred on JOGL OpenGL worker thread:"); + t.printStackTrace(); + } + } + + // See about releasing current context + GLContext curContext = GLContext.getCurrent(); + if (curContext != null && + (curContext instanceof GLContextImpl)) { + GLContextImpl impl = (GLContextImpl) curContext; + if (impl.hasWaiters()) { + impl.release(); + } + } + } + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp new file mode 100644 index 000000000..4a0eaa22b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javame_cdc_fp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.*; +import java.nio.*; + +/** Internal copy of selected routines from BufferUtil to avoid + outward dependencies on com.jogamp.opengl.util package. */ +public class InternalBufferUtil { + public static final int SIZEOF_BYTE = 1; + public static final int SIZEOF_SHORT = 2; + public static final int SIZEOF_INT = 4; + public static final int SIZEOF_FLOAT = 4; + + //---------------------------------------------------------------------- + // Allocation routines + // + + /** Allocates a new direct ByteBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ByteBuffer newByteBuffer(int numElements) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + nativeOrder(bb); + return bb; + } + + /** Allocates a new direct IntBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static IntBuffer newIntBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); + return bb.asIntBuffer(); + } + + /** Allocates a new direct ShortBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ShortBuffer newShortBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_SHORT); + return bb.asShortBuffer(); + } + + /** Allocates a new direct FloatBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static FloatBuffer newFloatBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT); + return bb.asFloatBuffer(); + } + + //---------------------------------------------------------------------- + // Copy routines (type-to-type) + // + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed FloatBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyFloatBufferAsByteBuffer(FloatBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_FLOAT); + dest.asFloatBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed IntBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyIntBufferAsByteBuffer(IntBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_INT); + dest.asIntBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ShortBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyShortBufferAsByteBuffer(ShortBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_SHORT); + dest.asShortBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ByteBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyByteBuffer(ByteBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining()); + dest.put(orig); + dest.rewind(); + return dest; + } + + //---------------------------------------------------------------------- + // Conversion routines + // + + public static float[] getFloatArray(double[] source) { + int i=source.length; + float[] dest = new float[i--]; + while(i>=0) { dest[i]=(float)source[i]; i--; } + return dest; + } + + public static ByteBuffer nativeOrder(ByteBuffer buf) { + if (!isCDCFP) { + try { + if (byteOrderClass == null) { + byteOrderClass = Class.forName("java.nio.ByteOrder"); + orderMethod = ByteBuffer.class.getMethod("order", new Class[] { byteOrderClass }); + Method nativeOrderMethod = byteOrderClass.getMethod("nativeOrder", null); + nativeOrderObject = nativeOrderMethod.invoke(null, null); + } + } catch (Throwable t) { + // Must be running on CDC / FP + isCDCFP = true; + } + + if (!isCDCFP) { + try { + orderMethod.invoke(buf, new Object[] { nativeOrderObject }); + } catch (Throwable t) { + } + } + } + return buf; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // NOTE that this work must be done reflectively at the present time + // because this code must compile and run correctly on both CDC/FP and J2SE + private static boolean isCDCFP; + private static Class byteOrderClass; + private static Object nativeOrderObject; + private static Method orderMethod; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase new file mode 100644 index 000000000..655fa95de --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/InternalBufferUtil.java.javase @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.*; +import java.nio.*; + +/** Internal copy of selected routines from BufferUtil to avoid + outward dependencies on com.jogamp.opengl.util package. */ +public class InternalBufferUtil { + public static final int SIZEOF_BYTE = 1; + public static final int SIZEOF_SHORT = 2; + public static final int SIZEOF_INT = 4; + public static final int SIZEOF_FLOAT = 4; + public static final int SIZEOF_LONG = 8; + public static final int SIZEOF_DOUBLE = 8; + + //---------------------------------------------------------------------- + // Allocation routines + // + + /** Allocates a new direct ByteBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ByteBuffer newByteBuffer(int numElements) { + ByteBuffer bb = ByteBuffer.allocateDirect(numElements); + nativeOrder(bb); + return bb; + } + + /** Allocates a new direct DoubleBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static DoubleBuffer newDoubleBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_DOUBLE); + return bb.asDoubleBuffer(); + } + + /** Allocates a new direct IntBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static IntBuffer newIntBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_INT); + return bb.asIntBuffer(); + } + + /** Allocates a new direct ShortBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static ShortBuffer newShortBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_SHORT); + return bb.asShortBuffer(); + } + + /** Allocates a new direct FloatBuffer with the specified number of + elements. The returned buffer will have its byte order set to + the host platform's native byte order. */ + public static FloatBuffer newFloatBuffer(int numElements) { + ByteBuffer bb = newByteBuffer(numElements * SIZEOF_FLOAT); + return bb.asFloatBuffer(); + } + + //---------------------------------------------------------------------- + // Copy routines (type-to-ByteBuffer) + // + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed FloatBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyFloatBufferAsByteBuffer(FloatBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_FLOAT); + dest.asFloatBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed IntBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyIntBufferAsByteBuffer(IntBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_INT); + dest.asIntBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ShortBuffer + into a newly-allocated direct ByteBuffer. The returned buffer + will have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyShortBufferAsByteBuffer(ShortBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining() * SIZEOF_SHORT); + dest.asShortBuffer().put(orig); + dest.rewind(); + return dest; + } + + /** Copies the <i>remaining</i> elements (as defined by + <code>limit() - position()</code>) in the passed ByteBuffer into + a newly-allocated direct ByteBuffer. The returned buffer will + have its byte order set to the host platform's native byte + order. The position of the newly-allocated buffer will be zero, + and the position of the passed buffer is unchanged (though its + mark is changed). */ + public static ByteBuffer copyByteBuffer(ByteBuffer orig) { + ByteBuffer dest = newByteBuffer(orig.remaining()); + dest.put(orig); + dest.rewind(); + return dest; + } + + //---------------------------------------------------------------------- + // Conversion routines + // + + public static float[] getFloatArray(double[] source) { + int i=source.length; + float[] dest = new float[i--]; + while(i>=0) { dest[i]=(float)source[i]; i--; } + return dest; + } + + public static ByteBuffer nativeOrder(ByteBuffer buf) { + if (!isCDCFP) { + try { + if (byteOrderClass == null) { + byteOrderClass = Class.forName("java.nio.ByteOrder"); + orderMethod = ByteBuffer.class.getMethod("order", new Class[] { byteOrderClass }); + Method nativeOrderMethod = byteOrderClass.getMethod("nativeOrder", null); + nativeOrderObject = nativeOrderMethod.invoke(null, null); + } + } catch (Throwable t) { + // Must be running on CDC / FP + isCDCFP = true; + } + + if (!isCDCFP) { + try { + orderMethod.invoke(buf, new Object[] { nativeOrderObject }); + } catch (Throwable t) { + } + } + } + return buf; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // NOTE that this work must be done reflectively at the present time + // because this code must compile and run correctly on both CDC/FP and J2SE + private static boolean isCDCFP; + private static Class byteOrderClass; + private static Object nativeOrderObject; + private static Method orderMethod; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java b/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java new file mode 100755 index 000000000..dbd84c9de --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ProjectFloat.java @@ -0,0 +1,1057 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-13 22:20:29 -0700 (Fri, 13 Mar 2009) $ $Revision: 1867 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ +package com.jogamp.opengl.impl; + +import java.nio.*; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +/** + * ProjectFloat.java + * <p/> + * <p/> + * Created 11-jan-2004 + * + * @author Erik Duijs + * @author Kenneth Russell + */ +public class ProjectFloat { + private static final float[] IDENTITY_MATRIX = + new float[] { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + + private static final float[] ZERO_MATRIX = + new float[] { + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f }; + + // Note that we have cloned parts of the implementation in order to + // support incoming Buffers. The reason for this is to avoid loading + // non-direct buffer subclasses unnecessarily, because doing so can + // cause performance decreases on direct buffer operations, at least + // on the current HotSpot JVM. It would be nicer (and make the code + // simpler) to simply have the array-based entry points delegate to + // the versions taking Buffers by wrapping the arrays. + + // Array-based implementation + private final float[] matrix = new float[16]; + private final float[][] tempInvertMatrix = new float[4][4]; + + private final float[] in = new float[4]; + private final float[] out = new float[4]; + + private final float[] forward = new float[3]; + private final float[] side = new float[3]; + private final float[] up = new float[3]; + + // Buffer-based implementation + private FloatBuffer locbuf; + private final FloatBuffer matrixBuf; + private final FloatBuffer tempInvertMatrixBuf; + + private final FloatBuffer inBuf; + private final FloatBuffer outBuf; + + private final FloatBuffer forwardBuf; + private final FloatBuffer sideBuf; + private final FloatBuffer upBuf; + + public ProjectFloat() { + // Use direct buffers to avoid loading indirect buffer + // implementations for applications trying to avoid doing so. + // Slice up one big buffer because some NIO implementations + // allocate a huge amount of memory to back even the smallest of + // buffers. + locbuf = InternalBufferUtil.newFloatBuffer(2*16+2*4+3*3); + int pos = 0; + int sz = 16; + matrixBuf = slice(locbuf, pos, sz); + pos += sz; + tempInvertMatrixBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 4; + inBuf = slice(locbuf, pos, sz); + pos += sz; + outBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 3; + forwardBuf = slice(locbuf, pos, sz); + pos += sz; + sideBuf = slice(locbuf, pos, sz); + pos += sz; + upBuf = slice(locbuf, pos, sz); + } + + public void destroy() { + if(locbuf!=null) { + locbuf.clear(); + locbuf=null; + } + } + + private static FloatBuffer slice(FloatBuffer buf, int pos, int len) { + buf.position(pos); + buf.limit(pos + len); + return buf.slice(); + } + + /** + * Make matrix an identity matrix + */ + public static void gluMakeIdentityf(FloatBuffer m) { + int oldPos = m.position(); + m.put(IDENTITY_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an zero matrix + */ + public static void gluMakeZero(FloatBuffer m) { + int oldPos = m.position(); + m.put(ZERO_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an identity matrix + */ + public static void gluMakeIdentityf(float[] m) { + for (int i = 0; i < 16; i++) { + m[i] = IDENTITY_MATRIX[i]; + } + } + + /** + * Method __gluMultMatrixVecf + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecf(float[] matrix, int matrix_offset, float[] in, float[] out) { + for (int i = 0; i < 4; i++) { + out[i] = + in[0] * matrix[0*4+i+matrix_offset] + + in[1] * matrix[1*4+i+matrix_offset] + + in[2] * matrix[2*4+i+matrix_offset] + + in[3] * matrix[3*4+i+matrix_offset]; + } + } + + /** + * Method __gluMultMatrixVecf + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecf(FloatBuffer matrix, FloatBuffer in, FloatBuffer out) { + int inPos = in.position(); + int outPos = out.position(); + int matrixPos = matrix.position(); + for (int i = 0; i < 4; i++) { + out.put(i + outPos, + in.get(0+inPos) * matrix.get(0*4+i+matrixPos) + + in.get(1+inPos) * matrix.get(1*4+i+matrixPos) + + in.get(2+inPos) * matrix.get(2*4+i+matrixPos) + + in.get(3+inPos) * matrix.get(3*4+i+matrixPos)); + } + } + + /** + * @param src + * @param inverse + * + * @return + */ + public boolean gluInvertMatrixf(float[] src, float[] inverse) { + int i, j, k, swap; + float t; + float[][] temp = tempInvertMatrix; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp[i][j] = src[i*4+j]; + } + } + gluMakeIdentityf(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp[i][k]; + temp[i][k] = temp[swap][k]; + temp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + if (temp[i][i] == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp[i][i]; + for (k = 0; k < 4; k++) { + temp[i][k] /= t; + inverse[i*4+k] /= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp[j][i]; + for (k = 0; k < 4; k++) { + temp[j][k] -= temp[i][k] * t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } + return true; + } + + /** + * @param src + * @param inverse + * + * @return + */ + public boolean gluInvertMatrixf(FloatBuffer src, FloatBuffer inverse) { + int i, j, k, swap; + float t; + + int srcPos = src.position(); + int invPos = inverse.position(); + + FloatBuffer temp = tempInvertMatrixBuf; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp.put(i*4+j, src.get(i*4+j + srcPos)); + } + } + gluMakeIdentityf(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp.get(i*4+k); + temp.put(i*4+k, temp.get(swap*4+k)); + temp.put(swap*4+k, t); + + t = inverse.get(i*4+k + invPos); + inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos)); + inverse.put(swap*4+k + invPos, t); + } + } + + if (temp.get(i*4+i) == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp.get(i*4+i); + for (k = 0; k < 4; k++) { + temp.put(i*4+k, temp.get(i*4+k) / t); + inverse.put(i*4+k + invPos, inverse.get(i*4+k + invPos) / t); + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp.get(j*4+i); + for (k = 0; k < 4; k++) { + temp.put(j*4+k, temp.get(j*4+k) - temp.get(i*4+k) * t); + inverse.put(j*4+k + invPos, inverse.get(j*4+k + invPos) - inverse.get(i*4+k + invPos) * t); + } + } + } + } + return true; + } + + + /** + * @param a + * @param b + * @param r + */ + private void gluMultMatricesf(float[] a, int a_offset, float[] b, int b_offset, float[] r) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i*4+j] = + a[i*4+0+a_offset]*b[0*4+j+b_offset] + + a[i*4+1+a_offset]*b[1*4+j+b_offset] + + a[i*4+2+a_offset]*b[2*4+j+b_offset] + + a[i*4+3+a_offset]*b[3*4+j+b_offset]; + } + } + } + + + /** + * @param a + * @param b + * @param r + */ + public static void gluMultMatricesf(FloatBuffer a, FloatBuffer b, FloatBuffer r) { + int aPos = a.position(); + int bPos = b.position(); + int rPos = r.position(); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r.put(i*4+j + rPos, + a.get(i*4+0+aPos)*b.get(0*4+j+bPos) + + a.get(i*4+1+aPos)*b.get(1*4+j+bPos) + + a.get(i*4+2+aPos)*b.get(2*4+j+bPos) + + a.get(i*4+3+aPos)*b.get(3*4+j+bPos)); + } + } + } + + /** + * Normalize vector + * + * @param v + */ + public static void normalize(float[] v) { + float r; + + r = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if ( r == 0.0 || r == 1.0) + return; + + r = 1.0f / r; + + v[0] *= r; + v[1] *= r; + v[2] *= r; + + return; + } + + /** + * Normalize vector + * + * @param v + */ + public static void normalize(FloatBuffer v) { + float r; + + int vPos = v.position(); + + r = (float) Math.sqrt(v.get(0+vPos) * v.get(0+vPos) + + v.get(1+vPos) * v.get(1+vPos) + + v.get(2+vPos) * v.get(2+vPos)); + if ( r == 0.0 || r == 1.0) + return; + + r = 1.0f / r; + + v.put(0+vPos, v.get(0+vPos) * r); + v.put(1+vPos, v.get(1+vPos) * r); + v.put(2+vPos, v.get(2+vPos) * r); + + return; + } + + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(float[] v1, float[] v2, float[] result) { + result[0] = v1[1] * v2[2] - v1[2] * v2[1]; + result[1] = v1[2] * v2[0] - v1[0] * v2[2]; + result[2] = v1[0] * v2[1] - v1[1] * v2[0]; + } + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(FloatBuffer v1, FloatBuffer v2, FloatBuffer result) { + int v1Pos = v1.position(); + int v2Pos = v2.position(); + int rPos = result.position(); + + result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos)); + result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos)); + result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos)); + } + + /** + * Method gluOrtho2D. + * + * @param left + * @param right + * @param bottom + * @param top + */ + public void gluOrtho2D(GLMatrixFunc gl, float left, float right, float bottom, float top) { + gl.glOrthof(left, right, bottom, top, -1, 1); + } + + /** + * Method gluPerspective. + * + * @param fovy + * @param aspect + * @param zNear + * @param zFar + */ + public void gluPerspective(GLMatrixFunc gl, float fovy, float aspect, float zNear, float zFar) { + float sine, cotangent, deltaZ; + float radians = fovy / 2 * (float) Math.PI / 180; + + deltaZ = zFar - zNear; + sine = (float) Math.sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { + return; + } + + cotangent = (float) Math.cos(radians) / sine; + + gluMakeIdentityf(matrixBuf); + + matrixBuf.put(0 * 4 + 0, cotangent / aspect); + matrixBuf.put(1 * 4 + 1, cotangent); + matrixBuf.put(2 * 4 + 2, - (zFar + zNear) / deltaZ); + matrixBuf.put(2 * 4 + 3, -1); + matrixBuf.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ); + matrixBuf.put(3 * 4 + 3, 0); + + gl.glMultMatrixf(matrixBuf); + } + + /** + * Method gluLookAt + * + * @param eyex + * @param eyey + * @param eyez + * @param centerx + * @param centery + * @param centerz + * @param upx + * @param upy + * @param upz + */ + public void gluLookAt(GLMatrixFunc gl, + float eyex, + float eyey, + float eyez, + float centerx, + float centery, + float centerz, + float upx, + float upy, + float upz) { + FloatBuffer forward = this.forwardBuf; + FloatBuffer side = this.sideBuf; + FloatBuffer up = this.upBuf; + + forward.put(0, centerx - eyex); + forward.put(1, centery - eyey); + forward.put(2, centerz - eyez); + + up.put(0, upx); + up.put(1, upy); + up.put(2, upz); + + normalize(forward); + + /* Side = forward x up */ + cross(forward, up, side); + normalize(side); + + /* Recompute up as: up = side x forward */ + cross(side, forward, up); + + gluMakeIdentityf(matrixBuf); + matrixBuf.put(0 * 4 + 0, side.get(0)); + matrixBuf.put(1 * 4 + 0, side.get(1)); + matrixBuf.put(2 * 4 + 0, side.get(2)); + + matrixBuf.put(0 * 4 + 1, up.get(0)); + matrixBuf.put(1 * 4 + 1, up.get(1)); + matrixBuf.put(2 * 4 + 1, up.get(2)); + + matrixBuf.put(0 * 4 + 2, -forward.get(0)); + matrixBuf.put(1 * 4 + 2, -forward.get(1)); + matrixBuf.put(2 * 4 + 2, -forward.get(2)); + + gl.glMultMatrixf(matrixBuf); + gl.glTranslatef(-eyex, -eyey, -eyez); + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(float objx, + float objy, + float objz, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float[] win_pos, + int win_pos_offset ) { + + float[] in = this.in; + float[] out = this.out; + + in[0] = objx; + in[1] = objy; + in[2] = objz; + in[3] = 1.0f; + + __gluMultMatrixVecf(modelMatrix, modelMatrix_offset, in, out); + __gluMultMatrixVecf(projMatrix, projMatrix_offset, out, in); + + if (in[3] == 0.0f) + return false; + + in[3] = (1.0f / in[3]) * 0.5f; + + // Map x, y and z to range 0-1 + in[0] = in[0] * in[3] + 0.5f; + in[1] = in[1] * in[3] + 0.5f; + in[2] = in[2] * in[3] + 0.5f; + + // Map x,y to viewport + win_pos[0+win_pos_offset] = in[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset]; + win_pos[1+win_pos_offset] = in[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset]; + win_pos[2+win_pos_offset] = in[2]; + + return true; + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(float objx, + float objy, + float objz, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + FloatBuffer win_pos) { + + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + in.put(0, objx); + in.put(1, objy); + in.put(2, objz); + in.put(3, 1.0f); + + __gluMultMatrixVecf(modelMatrix, in, out); + __gluMultMatrixVecf(projMatrix, out, in); + + if (in.get(3) == 0.0f) + return false; + + in.put(3, (1.0f / in.get(3)) * 0.5f); + + // Map x, y and z to range 0-1 + in.put(0, in.get(0) * in.get(3) + 0.5f); + in.put(1, in.get(1) * in.get(3) + 0.5f); + in.put(2, in.get(2) * in.get(3) + 0.5f); + + // Map x,y to viewport + int vPos = viewport.position(); + int wPos = win_pos.position(); + win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos)); + win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos)); + win_pos.put(2+wPos, in.get(2)); + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(float winx, + float winy, + float winz, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float[] obj_pos, + int obj_pos_offset) { + float[] in = this.in; + float[] out = this.out; + + gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!gluInvertMatrixf(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = 1.0f; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecf(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + out[3] = 1.0f / out[3]; + + obj_pos[0+obj_pos_offset] = out[0] * out[3]; + obj_pos[1+obj_pos_offset] = out[1] * out[3]; + obj_pos[2+obj_pos_offset] = out[2] * out[3]; + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(float winx, + float winy, + float winz, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + FloatBuffer obj_pos) { + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); + + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, 1.0f); + + // Map x and y from window coordinates + int vPos = viewport.position(); + int oPos = obj_pos.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecf(matrixBuf, in, out); + + if (out.get(3) == 0.0f) + return false; + + out.put(3, 1.0f / out.get(3)); + + obj_pos.put(0+oPos, out.get(0) * out.get(3)); + obj_pos.put(1+oPos, out.get(1) * out.get(3)); + obj_pos.put(2+oPos, out.get(2) * out.get(3)); + + return true; + } + + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(float winx, + float winy, + float winz, + float clipw, + float[] modelMatrix, + int modelMatrix_offset, + float[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + float near, + float far, + float[] obj_pos, + int obj_pos_offset ) { + float[] in = this.in; + float[] out = this.out; + + gluMultMatricesf(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!gluInvertMatrixf(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = clipw; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + in[2] = (in[2] - near) / (far - near); + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecf(matrix, 0, in, out); + + if (out[3] == 0.0f) + return false; + + obj_pos[0+obj_pos_offset] = out[0]; + obj_pos[1+obj_pos_offset] = out[1]; + obj_pos[2+obj_pos_offset] = out[2]; + obj_pos[3+obj_pos_offset] = out[3]; + return true; + } + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(float winx, + float winy, + float winz, + float clipw, + FloatBuffer modelMatrix, + FloatBuffer projMatrix, + IntBuffer viewport, + float near, + float far, + FloatBuffer obj_pos) { + FloatBuffer in = this.inBuf; + FloatBuffer out = this.outBuf; + + gluMultMatricesf(modelMatrix, projMatrix, matrixBuf); + + if (!gluInvertMatrixf(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, clipw); + + // Map x and y from window coordinates + int vPos = viewport.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + in.put(2, (in.get(2) - near) / (far - near)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecf(matrixBuf, in, out); + + if (out.get(3) == 0.0f) + return false; + + int oPos = obj_pos.position(); + obj_pos.put(0+oPos, out.get(0)); + obj_pos.put(1+oPos, out.get(1)); + obj_pos.put(2+oPos, out.get(2)); + obj_pos.put(3+oPos, out.get(3)); + return true; + } + + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + */ + public void gluPickMatrix(GLMatrixFunc gl, + float x, + float y, + float deltaX, + float deltaY, + IntBuffer viewport) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + int vPos = viewport.position(); + gl.glTranslatef((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX, + (viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY, + 0); + gl.glScalef(viewport.get(2) / deltaX, viewport.get(3) / deltaY, 1.0f); + } + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + * @param viewport_offset + */ + public void gluPickMatrix(GLMatrixFunc gl, + float x, + float y, + float deltaX, + float deltaY, + int[] viewport, + int viewport_offset) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + gl.glTranslatef((viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX, + (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY, + 0); + gl.glScalef(viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0f); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp new file mode 100644 index 000000000..f686bea92 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javame_cdc_fp @@ -0,0 +1,10 @@ +package com.jogamp.opengl.impl; + +public class SystemUtil { + + /** Wrapper for System.getenv(), which doesn't work on platforms + earlier than JDK 5 */ + public static String getenv(String variableName) { + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase new file mode 100644 index 000000000..dbb717a32 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/SystemUtil.java.javase @@ -0,0 +1,18 @@ +package com.jogamp.opengl.impl; + +public class SystemUtil { + + private static volatile boolean getenvSupported = true; + /** Wrapper for System.getenv(), which doesn't work on platforms + earlier than JDK 5 */ + public static String getenv(String variableName) { + if (getenvSupported) { + try { + return System.getenv(variableName); + } catch (Error e) { + getenvSupported = false; + } + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java new file mode 100644 index 000000000..1a68f38d4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.impl; + +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLException; + +/** Implementation of the {@link javax.media.opengl.Threading} class. */ + +public class ThreadingImpl { + public static final int AWT = 1; + public static final int WORKER = 2; + + protected static final boolean DEBUG = Debug.debug("Threading"); + + private static boolean singleThreaded = true; + private static int mode; + private static boolean hasAWT; + // We need to know whether we're running on X11 platforms to change + // our behavior when the Java2D/JOGL bridge is active + private static boolean _isX11; + + private static final ThreadingPlugin threadingPlugin; + + static { + Object threadingPluginTmp = + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + String workaround = Debug.getProperty("jogl.1thread", true); + // Default to using the AWT thread on all platforms except + // Windows. On OS X there is instability apparently due to + // using the JAWT on non-AWT threads. On X11 platforms there + // are potential deadlocks which can be caused if the AWT + // EventQueue thread hands work off to the GLWorkerThread + // while holding the AWT lock. The optimization of + // makeCurrent / release calls isn't worth these stability + // problems. + hasAWT = ReflectionUtil.isClassAvailable("java.awt.Canvas") && + ReflectionUtil.isClassAvailable("javax.media.opengl.awt.GLCanvas"); + + String osType = NativeWindowFactory.getNativeWindowType(false); + _isX11 = NativeWindowFactory.TYPE_X11.equals(osType); + // boolean isWindows = NativeWindowFactory.TYPE_WINDOWS.equals(osType); + + // int defaultMode = (isWindows ? WORKER : ( hasAWT ? AWT : WORKER ) ); + int defaultMode = ( hasAWT ? AWT : WORKER ); + + mode = defaultMode; + if (workaround != null) { + workaround = workaround.toLowerCase(); + if (workaround.equals("true") || + workaround.equals("auto")) { + // Nothing to do; singleThreaded and mode already set up + } else if (workaround.equals("worker")) { + singleThreaded = true; + mode = WORKER; + } else if (workaround.equals("awt")) { + singleThreaded = true; + mode = AWT; + } else { + singleThreaded = false; + } + } + printWorkaroundNotice(); + + Object threadingPluginObj=null; + // try to fetch the AWTThreadingPlugin + try { + threadingPluginObj = ReflectionUtil.createInstance("com.jogamp.opengl.impl.awt.AWTThreadingPlugin"); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + return threadingPluginObj; + } + }); + threadingPlugin = (ThreadingPlugin) threadingPluginTmp; + if(DEBUG) { + System.err.println("Threading: hasAWT "+hasAWT+", mode "+((mode==AWT)?"AWT":"WORKER")+", plugin "+threadingPlugin); + } + } + + /** No reason to ever instantiate this class */ + private ThreadingImpl() {} + + public static boolean isX11() { return _isX11; } + public static int getMode() { return mode; } + + /** If an implementation of the javax.media.opengl APIs offers a + multithreading option but the default behavior is single-threading, + this API provides a mechanism for end users to disable single-threading + in this implementation. Users are strongly discouraged from + calling this method unless they are aware of all of the + consequences and are prepared to enforce some amount of + threading restrictions in their applications. Disabling + single-threading, for example, may have unintended consequences + on GLAutoDrawable implementations such as GLCanvas, GLJPanel and + GLPbuffer. Currently there is no supported way to re-enable it + once disabled, partly to discourage careless use of this + method. This method should be called as early as possible in an + application. */ + public static void disableSingleThreading() { + singleThreaded = false; + if (Debug.verbose()) { + System.err.println("Application forced disabling of single-threading of javax.media.opengl implementation"); + } + } + + /** Indicates whether OpenGL work is being automatically forced to a + single thread in this implementation. */ + public static boolean isSingleThreaded() { + return singleThreaded; + } + + /** Indicates whether the current thread is the single thread on + which this implementation of the javax.media.opengl APIs + performs all of its OpenGL-related work. This method should only + be called if the single-thread model is in effect. */ + public static boolean isOpenGLThread() throws GLException { + if (!isSingleThreaded()) { + throw new GLException("Should only call this in single-threaded mode"); + } + + if(null!=threadingPlugin) { + return threadingPlugin.isOpenGLThread(); + } + + switch (mode) { + case AWT: + return true; + case WORKER: + return GLWorkerThread.isWorkerThread(); + default: + throw new InternalError("Illegal single-threading mode " + mode); + } + } + + /** Executes the passed Runnable on the single thread used for all + OpenGL work in this javax.media.opengl API implementation. It is + not specified exactly which thread is used for this + purpose. This method should only be called if the single-thread + model is in use and if the current thread is not the OpenGL + thread (i.e., if <code>isOpenGLThread()</code> returns + false). It is up to the end user to check to see whether the + current thread is the OpenGL thread and either execute the + Runnable directly or perform the work inside it. */ + public static void invokeOnOpenGLThread(Runnable r) throws GLException { + if (!isSingleThreaded()) { + throw new GLException ("Should only call this in single-threaded mode"); + } + + if (isOpenGLThread()) { + throw new GLException ("Should only call this from other threads than the OpenGL thread"); + } + + if(null!=threadingPlugin) { + threadingPlugin.invokeOnOpenGLThread(r); + return; + } + + switch (mode) { + case AWT: + r.run(); + break; + + case WORKER: + if (!GLWorkerThread.isStarted()) { + synchronized (GLWorkerThread.class) { + if (!GLWorkerThread.isStarted()) { + GLWorkerThread.start(); + } + } + } + try { + GLWorkerThread.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + break; + + default: + throw new InternalError("Illegal single-threading mode " + mode); + } + } + + /** This is a workaround for AWT-related deadlocks which only seem + to show up in the context of applets */ + public static boolean isAWTMode() { + return (mode == AWT); + } + + private static void printWorkaroundNotice() { + if (singleThreaded && Debug.verbose()) { + System.err.println("Using " + + (mode == AWT ? "AWT" : "OpenGL worker") + + " thread for performing OpenGL work in javax.media.opengl implementation"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java new file mode 100644 index 000000000..37e4aac70 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingPlugin.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl; + +import javax.media.opengl.*; + +public interface ThreadingPlugin { + /** Indicates whether the current thread is the single thread on + which this implementation of the javax.media.opengl APIs + performs all of its OpenGL-related work. This method should only + be called if the single-thread model is in effect. */ + public boolean isOpenGLThread() throws GLException; + + /** Executes the passed Runnable on the single thread used for all + OpenGL work in this javax.media.opengl API implementation. It is + not specified exactly which thread is used for this + purpose. This method should only be called if the single-thread + model is in use and if the current thread is not the OpenGL + thread (i.e., if <code>isOpenGLThread()</code> returns + false). It is up to the end user to check to see whether the + current thread is the OpenGL thread and either execute the + Runnable directly or perform the work inside it. */ + public void invokeOnOpenGLThread(Runnable r) throws GLException; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java new file mode 100755 index 000000000..07bf2f2db --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTThreadingPlugin.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import javax.media.opengl.*; + +import java.awt.event.*; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.opengl.impl.*; + +public class AWTThreadingPlugin implements ThreadingPlugin { + + public AWTThreadingPlugin() {} + + public boolean isOpenGLThread() throws GLException { + switch (ThreadingImpl.getMode()) { + case ThreadingImpl.AWT: + if (Java2D.isOGLPipelineActive()) { + // FIXME: ideally only the QFT would be considered to be the + // "OpenGL thread", but we can not currently run all of + // JOGL's OpenGL work on that thread. See the FIXME in + // invokeOnOpenGLThread. + return (Java2D.isQueueFlusherThread() || + (ThreadingImpl.isX11() && EventQueue.isDispatchThread())); + } else { + return EventQueue.isDispatchThread(); + } + case ThreadingImpl.WORKER: + if (Java2D.isOGLPipelineActive()) { + // FIXME: ideally only the QFT would be considered to be the + // "OpenGL thread", but we can not currently run all of + // JOGL's OpenGL work on that thread. See the FIXME in + // invokeOnOpenGLThread. + return (Java2D.isQueueFlusherThread() || + (ThreadingImpl.isX11() && GLWorkerThread.isWorkerThread())); + } else { + return GLWorkerThread.isWorkerThread(); + } + default: + throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode()); + } + } + + public void invokeOnOpenGLThread(Runnable r) throws GLException { + switch (ThreadingImpl.getMode()) { + case ThreadingImpl.AWT: + // FIXME: ideally should run all OpenGL work on the Java2D QFT + // thread when it's enabled, but unfortunately there are + // deadlock issues on X11 platforms when making our + // heavyweight OpenGL contexts current on the QFT because we + // perform the JAWT lock inside the makeCurrent() + // implementation, which attempts to grab the AWT lock on the + // QFT which is not allowed. For now, on X11 platforms, + // continue to perform this work on the EDT. + if (Java2D.isOGLPipelineActive() && !ThreadingImpl.isX11()) { + Java2D.invokeWithOGLContextCurrent(null, r); + } else { + try { + EventQueue.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + } + break; + + case ThreadingImpl.WORKER: + if (!GLWorkerThread.isStarted()) { + synchronized (GLWorkerThread.class) { + if (!GLWorkerThread.isStarted()) { + GLWorkerThread.start(); + } + } + } + try { + GLWorkerThread.invokeAndWait(r); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (InterruptedException e) { + throw new GLException(e); + } + break; + + default: + throw new InternalError("Illegal single-threading mode " + ThreadingImpl.getMode()); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java new file mode 100644 index 000000000..e5570a8ee --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.impl.awt; + +import com.jogamp.nativewindow.impl.jawt.*; + +import com.jogamp.opengl.impl.*; + +import javax.media.opengl.*; + +import java.lang.reflect.*; +import java.awt.GraphicsEnvironment; + +public class AWTUtil { + // See whether we're running in headless mode + private static boolean headlessMode; + private static Class j2dClazz = null; + private static Method isOGLPipelineActive = null; + private static Method isQueueFlusherThread = null; + private static boolean j2dOk = false; + + static { + lockedToolkit = false; + headlessMode = GraphicsEnvironment.isHeadless(); + if(!headlessMode) { + try { + j2dClazz = Class.forName("com.jogamp.opengl.impl.awt.Java2D"); + isOGLPipelineActive = j2dClazz.getMethod("isOGLPipelineActive", null); + isQueueFlusherThread = j2dClazz.getMethod("isQueueFlusherThread", null); + j2dOk = true; + } catch (Exception e) {} + } + } + + private static boolean lockedToolkit; + + public static synchronized void lockToolkit() throws GLException { + if (lockedToolkit) { + throw new GLException("Toolkit already locked"); + } + lockedToolkit = true; + + if (headlessMode) { + // Workaround for running (to some degree) in headless + // environments but still supporting rendering via pbuffers + // For full correctness, would need to implement a Lock class + return; + } + + if(j2dOk) { + try { + if( !((Boolean)isOGLPipelineActive.invoke(null, null)).booleanValue() || + !((Boolean)isQueueFlusherThread.invoke(null, null)).booleanValue() ) { + JAWTUtil.lockToolkit(); + } + } catch (Exception e) { j2dOk=false; } + } + if(!j2dOk) { + JAWTUtil.lockToolkit(); + } + } + + public static synchronized void unlockToolkit() { + if (lockedToolkit) { + lockedToolkit = false; + if (headlessMode) { + // Workaround for running (to some degree) in headless + // environments but still supporting rendering via pbuffers + // For full correctness, would need to implement a Lock class + return; + } + + if(j2dOk) { + try { + if( !((Boolean)isOGLPipelineActive.invoke(null, null)).booleanValue() || + !((Boolean)isQueueFlusherThread.invoke(null, null)).booleanValue() ) { + JAWTUtil.unlockToolkit(); + } + } catch (Exception e) { j2dOk=false; } + } + if(!j2dOk) { + JAWTUtil.unlockToolkit(); + } + } + } + + public static boolean isToolkitLocked() { + return JAWTUtil.isToolkitLocked(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java new file mode 100755 index 000000000..b871c66a7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2D.java @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import com.jogamp.opengl.impl.*; + +import java.awt.*; +import java.awt.image.*; +import java.lang.reflect.*; +import java.security.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.awt.*; + +/** Defines integration with the Java2D OpenGL pipeline. This + integration is only supported in 1.6 and is highly experimental. */ + +public class Java2D { + private static boolean DEBUG = Debug.debug("Java2D"); + private static boolean VERBOSE = Debug.verbose(); + private static boolean isHeadless; + private static boolean isOGLPipelineActive; + private static Method invokeWithOGLContextCurrentMethod; + private static Method isQueueFlusherThreadMethod; + private static Method getOGLViewportMethod; + private static Method getOGLScissorBoxMethod; + private static Method getOGLSurfaceIdentifierMethod; + // This one is currently optional and is only in very recent Mustang builds + private static Method getOGLTextureTypeMethod; + + // The following methods and fields are needed for proper support of + // Frame Buffer Objects in the Java2D/OpenGL pipeline + // (-Dsun.java2d.opengl.fbobject=true) + private static boolean fbObjectSupportInitialized; + private static Method invokeWithOGLSharedContextCurrentMethod; + private static Method getOGLSurfaceTypeMethod; + + // Publicly-visible constants for OpenGL surface types + public static final int UNDEFINED = getOGLUtilitiesIntField("UNDEFINED"); + public static final int WINDOW = getOGLUtilitiesIntField("WINDOW"); + public static final int PBUFFER = getOGLUtilitiesIntField("PBUFFER"); + public static final int TEXTURE = getOGLUtilitiesIntField("TEXTURE"); + public static final int FLIP_BACKBUFFER = getOGLUtilitiesIntField("FLIP_BACKBUFFER"); + public static final int FBOBJECT = getOGLUtilitiesIntField("FBOBJECT"); + + // If FBOs are enabled in the Java2D/OpenGL pipeline, all contexts + // created by JOGL must share textures and display lists with the + // Java2D contexts in order to access the frame buffer object for + // potential rendering, and to simultaneously support sharing of + // textures and display lists with one another. Java2D has the + // notion of a single shared context with which all other contexts + // (on the same display device?) share textures and display lists; + // this is an approximation to that notion which will be refined + // later. + private static boolean initializedJ2DFBOShareContext; + private static GLContext j2dFBOShareContext; + + // Accessors for new methods in sun.java2d.opengl.CGLSurfaceData + // class on OS X for enabling bridge + // public static long createOGLContextOnSurface(Graphics g, long ctx); + // public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx); + // public static void destroyOGLContext(long ctx); + private static Method createOGLContextOnSurfaceMethod; + private static Method makeOGLContextCurrentOnSurfaceMethod; + private static Method destroyOGLContextMethod; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + if (DEBUG && VERBOSE) { + System.err.println("Checking for Java2D/OpenGL support"); + } + try { + isHeadless = true; + // Figure out whether the default graphics configuration is an + // OpenGL graphics configuration + GraphicsConfiguration cfg = + GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice(). + getDefaultConfiguration(); + // If we get here, we aren't running in headless mode + isHeadless = false; + String name = cfg.getClass().getName(); + if (DEBUG && VERBOSE) { + System.err.println("Java2D support: default GraphicsConfiguration = " + name); + } + isOGLPipelineActive = (name.startsWith("sun.java2d.opengl")); + + if (isOGLPipelineActive) { + try { + // Try to get methods we need to integrate + Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + invokeWithOGLContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLContextCurrent", + new Class[] { + Graphics.class, + Runnable.class + }); + invokeWithOGLContextCurrentMethod.setAccessible(true); + + isQueueFlusherThreadMethod = utils.getDeclaredMethod("isQueueFlusherThread", + new Class[] {}); + isQueueFlusherThreadMethod.setAccessible(true); + + getOGLViewportMethod = utils.getDeclaredMethod("getOGLViewport", + new Class[] { + Graphics.class, + Integer.TYPE, + Integer.TYPE + }); + getOGLViewportMethod.setAccessible(true); + + getOGLScissorBoxMethod = utils.getDeclaredMethod("getOGLScissorBox", + new Class[] { + Graphics.class + }); + getOGLScissorBoxMethod.setAccessible(true); + + getOGLSurfaceIdentifierMethod = utils.getDeclaredMethod("getOGLSurfaceIdentifier", + new Class[] { + Graphics.class + }); + getOGLSurfaceIdentifierMethod.setAccessible(true); + + // Try to get additional methods required for proper FBO support + fbObjectSupportInitialized = true; + try { + invokeWithOGLSharedContextCurrentMethod = utils.getDeclaredMethod("invokeWithOGLSharedContextCurrent", + new Class[] { + GraphicsConfiguration.class, + Runnable.class + }); + invokeWithOGLSharedContextCurrentMethod.setAccessible(true); + + getOGLSurfaceTypeMethod = utils.getDeclaredMethod("getOGLSurfaceType", + new Class[] { + Graphics.class + }); + getOGLSurfaceTypeMethod.setAccessible(true); + } catch (Exception e) { + fbObjectSupportInitialized = false; + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL FBO support"); + } + } + + // Try to get an additional method for FBO support in recent Mustang builds + try { + getOGLTextureTypeMethod = utils.getDeclaredMethod("getOGLTextureType", + new Class[] { + Graphics.class + }); + getOGLTextureTypeMethod.setAccessible(true); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("GL_ARB_texture_rectangle FBO support disabled"); + } + } + + // Try to set up APIs for enabling the bridge on OS X, + // where it isn't possible to create generalized + // external GLDrawables + Class cglSurfaceData = null; + try { + cglSurfaceData = Class.forName("sun.java2d.opengl.CGLSurfaceData"); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Unable to find class sun.java2d.opengl.CGLSurfaceData for OS X"); + } + } + if (cglSurfaceData != null) { + // FIXME: for now, assume that FBO support is not enabled on OS X + fbObjectSupportInitialized = false; + + // We need to find these methods in order to make the bridge work on OS X + createOGLContextOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("createOGLContextOnSurface", + new Class[] { + Graphics.class, + Long.TYPE + }); + createOGLContextOnSurfaceMethod.setAccessible(true); + + makeOGLContextCurrentOnSurfaceMethod = cglSurfaceData.getDeclaredMethod("makeOGLContextCurrentOnSurface", + new Class[] { + Graphics.class, + Long.TYPE + }); + makeOGLContextCurrentOnSurfaceMethod.setAccessible(true); + + destroyOGLContextMethod = cglSurfaceData.getDeclaredMethod("destroyOGLContext", + new Class[] { + Long.TYPE + }); + destroyOGLContextMethod.setAccessible(true); + } + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + System.err.println("Disabling Java2D/JOGL integration"); + } + isOGLPipelineActive = false; + } + } + } catch (HeadlessException e) { + // The AWT is running in headless mode, so the Java 2D / JOGL bridge is clearly disabled + } + + if (DEBUG) { + System.err.println("JOGL/Java2D integration " + (isOGLPipelineActive ? "enabled" : "disabled")); + } + return null; + } + }); + } + + public static boolean isOGLPipelineActive() { + return isOGLPipelineActive; + } + + public static boolean isFBOEnabled() { + return fbObjectSupportInitialized; + } + + public static boolean isQueueFlusherThread() { + checkActive(); + + try { + return ((Boolean) isQueueFlusherThreadMethod.invoke(null, new Object[] {})).booleanValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Makes current the OpenGL context associated with the passed + Graphics object and runs the given Runnable on the Queue + Flushing Thread in one atomic action. */ + public static void invokeWithOGLContextCurrent(Graphics g, Runnable r) throws GLException { + checkActive(); + + try { + // FIXME: this may need adjustment + // This seems to be needed in many applications which don't + // initialize an OpenGL context before this and which would + // otherwise cause initFBOShareContext to be called from the + // Queue Flusher Thread, which isn't allowed + initFBOShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice()); + + AWTUtil.lockToolkit(); + try { + invokeWithOGLContextCurrentMethod.invoke(null, new Object[] {g, r}); + } finally { + AWTUtil.unlockToolkit(); + } + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Makes current the "shared" OpenGL context associated with the + given GraphicsConfiguration object, allowing JOGL to share + server-side OpenGL objects like textures and display lists with + this context when necessary. This is needed when Java2D's FBO + support is enabled, because in order to render into that FBO, + JOGL must share textures and display lists with it. Returns + false if the passed GraphicsConfiguration was not an OpenGL + GraphicsConfiguration. */ + public static boolean invokeWithOGLSharedContextCurrent(GraphicsConfiguration g, Runnable r) throws GLException { + checkActive(); + + try { + AWTUtil.lockToolkit(); + try { + return ((Boolean) invokeWithOGLSharedContextCurrentMethod.invoke(null, new Object[] {g, r})).booleanValue(); + } finally { + AWTUtil.unlockToolkit(); + } + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the OpenGL viewport associated with the given Graphics + object, assuming that the Graphics object is associated with a + component of the specified width and height. The user should + call glViewport() with the returned rectangle's bounds in order + to get correct rendering results. Should only be called from the + Queue Flusher Thread. */ + public static Rectangle getOGLViewport(Graphics g, + int componentWidth, + int componentHeight) { + checkActive(); + + try { + return (Rectangle) getOGLViewportMethod.invoke(null, new Object[] {g, + new Integer(componentWidth), + new Integer(componentHeight)}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the OpenGL scissor region associated with the given + Graphics object, taking into account all clipping regions, etc. + To avoid destroying Java2D's previous rendering results, this + method should be called and the resulting rectangle's bounds + passed to a call to glScissor(). Should only be called from the + Queue Flusher Thread. */ + public static Rectangle getOGLScissorBox(Graphics g) { + checkActive(); + + try { + return (Rectangle) getOGLScissorBoxMethod.invoke(null, new Object[] {g}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns an opaque "surface identifier" associated with the given + Graphics object. If this changes from invocation to invocation, + the underlying OpenGL drawable for the Graphics object has + changed and a new external GLDrawable and GLContext should be + created (and the old ones destroyed). Should only be called from + the Queue Flusher Thread.*/ + public static Object getOGLSurfaceIdentifier(Graphics g) { + checkActive(); + + try { + return getOGLSurfaceIdentifierMethod.invoke(null, new Object[] {g}); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the underlying surface type for the given Graphics + object. This indicates, in particular, whether Java2D is + currently rendering into a pbuffer or FBO. */ + public static int getOGLSurfaceType(Graphics g) { + checkActive(); + + try { + // FIXME: fallback path for pre-b73 (?) Mustang builds -- remove + // once fbobject support is in OGLUtilities + if (!fbObjectSupportInitialized) { + return 0; + } + + return ((Integer) getOGLSurfaceTypeMethod.invoke(null, new Object[] { g })).intValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns the underlying texture target of the given Graphics + object assuming it is rendering to an FBO. Returns either + GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB. */ + public static int getOGLTextureType(Graphics g) { + checkActive(); + + if (getOGLTextureTypeMethod == null) { + return GL.GL_TEXTURE_2D; + } + + try { + return ((Integer) getOGLTextureTypeMethod.invoke(null, new Object[] { g })).intValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** Returns either the given GLContext or a substitute one with + which clients should share textures and display lists. Needed + when the Java2D/OpenGL pipeline is active and FBOs are being + used for rendering. FIXME: may need to alter the API in the + future to indicate which GraphicsDevice the source context is + associated with. */ + public static GLContext filterShareContext(GLContext shareContext) { + if (isHeadless) + return shareContext; + + // FIXME: this may need adjustment + initFBOShareContext(GraphicsEnvironment. + getLocalGraphicsEnvironment(). + getDefaultScreenDevice()); + if (j2dFBOShareContext != null) { + return j2dFBOShareContext; + } + return shareContext; + } + + /** Returns the GLContext associated with the Java2D "share + context", with which all contexts created by JOGL must share + textures and display lists when the FBO option is enabled for + the Java2D/OpenGL pipeline. */ + public static GLContext getShareContext(GraphicsDevice device) { + initFBOShareContext(device); + // FIXME: for full generality probably need to have multiple of + // these, one per GraphicsConfiguration seen? + return j2dFBOShareContext; + } + + //---------------------------------------------------------------------- + // Mac OS X-specific methods + // + + /** (Mac OS X-specific) Creates a new OpenGL context on the surface + associated with the given Graphics object, sharing textures and + display lists with the specified (CGLContextObj) share context. */ + public static long createOGLContextOnSurface(Graphics g, long shareCtx) { + checkActive(); + + try { + return ((Long) createOGLContextOnSurfaceMethod.invoke(null, new Object[] { g, new Long(shareCtx) })).longValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** (Mac OS X-specific) Makes the given OpenGL context current on + the surface associated with the given Graphics object. */ + public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) { + checkActive(); + + try { + return ((Boolean) makeOGLContextCurrentOnSurfaceMethod.invoke(null, new Object[] { g, new Long(ctx) })).booleanValue(); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + /** (Mac OS X-specific) Destroys the given OpenGL context. */ + public static void destroyOGLContext(long ctx) { + checkActive(); + + try { + destroyOGLContextMethod.invoke(null, new Object[] { new Long(ctx) }); + } catch (InvocationTargetException e) { + throw new GLException(e.getTargetException()); + } catch (Exception e) { + throw (InternalError) new InternalError().initCause(e); + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static void checkActive() { + if (!isOGLPipelineActive()) { + throw new GLException("Java2D OpenGL pipeline not active (or necessary support not present)"); + } + } + + private static int getOGLUtilitiesIntField(final String name) { + Integer i = (Integer) AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class utils = Class.forName("sun.java2d.opengl.OGLUtilities"); + Field f = utils.getField(name); + f.setAccessible(true); + return f.get(null); + } catch (Exception e) { + if (DEBUG && VERBOSE) { + e.printStackTrace(); + } + return null; + } + } + }); + if (i == null) + return 0; + if (DEBUG && VERBOSE) { + System.err.println("OGLUtilities." + name + " = " + i.intValue()); + } + return i.intValue(); + } + + private static void initFBOShareContext(final GraphicsDevice device) { + // Note 1: this must not be done in the static initalizer due to + // deadlock problems. + + // Note 2: the first execution of this method must not be from the + // Java2D Queue Flusher Thread. + + if (isOGLPipelineActive() && + isFBOEnabled() && + !initializedJ2DFBOShareContext) { + + // FIXME: this technique is probably not adequate in multi-head + // situations. Ideally we would keep track of a given share + // context on a per-GraphicsConfiguration basis or something + // similar rather than keeping one share context in a global + // variable. + initializedJ2DFBOShareContext = true; + if (DEBUG) { + System.err.println("Starting initialization of J2D FBO share context"); + } + invokeWithOGLSharedContextCurrent(device.getDefaultConfiguration(), new Runnable() { + public void run() { + j2dFBOShareContext = GLDrawableFactory.getFactory(GLProfile.getDefault()).createExternalGLContext(); + } + }); + if (DEBUG) { + System.err.println("Ending initialization of J2D FBO share context"); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java new file mode 100644 index 000000000..07bc54b6a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/Java2DGLContext.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.awt; + +import com.jogamp.opengl.impl.*; +import java.awt.Graphics; + +/** Provides a construct by which the shared GLJPanel code can + * interact with a few methods in the Mac OS X-specific Java2D/JOGL + * bridge implementation. + */ + +public interface Java2DGLContext { + public void setGraphics(Graphics g); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java new file mode 100755 index 000000000..48f80977c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLContext.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public abstract class EGLContext extends GLContextImpl { + private long eglContext; + private boolean eglQueryStringInitialized; + private boolean eglQueryStringAvailable; + private EGLExt eglExt; + // Table that holds the addresses of the native C-language entry points for + // EGL extension functions. + private EGLExtProcAddressTable eglExtProcAddressTable; + + public EGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public EGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getEGLExt(); + } + + public EGLExt getEGLExt() { + if (eglExt == null) { + eglExt = new EGLExtImpl(this); + } + return eglExt; + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return eglExtProcAddressTable; + } + + public final EGLExtProcAddressTable getEGLExtProcAddressTable() { + return eglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return null; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return null; } + + public long getContext() { + return eglContext; + } + + protected int makeCurrentImpl() throws GLException { + if(EGL.EGL_NO_DISPLAY==((EGLDrawable)drawable).getDisplay() ) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (eglContext == 0) { + create(); + created = true; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context 0x" + + Long.toHexString(eglContext) + " for " + getClass().getName()); + } + } + if (EGL.eglGetCurrentContext() != eglContext) { + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + ((EGLDrawable)drawable).getSurface(), + ((EGLDrawable)drawableRead).getSurface(), + eglContext)) { + throw new GLException("Error making context 0x" + + Long.toHexString(eglContext) + " current: error code " + EGL.eglGetError()); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + EGL.EGL_NO_SURFACE, + EGL.EGL_NO_SURFACE, + EGL.EGL_NO_CONTEXT)) { + throw new GLException("Error freeing OpenGL context 0x" + + Long.toHexString(eglContext) + ": error code " + EGL.eglGetError()); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void destroyImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (eglContext != 0) { + if (!EGL.eglDestroyContext(((EGLDrawable)drawable).getDisplay(), eglContext)) { + throw new GLException("Error destroying OpenGL context 0x" + + Long.toHexString(eglContext) + ": error code " + EGL.eglGetError()); + } + eglContext = 0; + GLContextShareSet.contextDestroyed(this); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + return 0; // FIXME + } + + protected void destroyContextARBImpl(long _context) { + // FIXME + } + + protected void create() throws GLException { + long eglDisplay = ((EGLDrawable)drawable).getDisplay(); + EGLGraphicsConfiguration config = ((EGLDrawable)drawable).getGraphicsConfiguration(); + GLProfile glProfile = drawable.getGLProfile(); + long eglConfig = config.getNativeConfig(); + long shareWith = EGL.EGL_NO_CONTEXT; + + if (eglDisplay == 0) { + throw new GLException("Error: attempted to create an OpenGL context without a display connection"); + } + if (eglConfig == 0) { + throw new GLException("Error: attempted to create an OpenGL context without a graphics configuration"); + } + + try { + // might be unavailable on EGL < 1.2 + if(!EGL.eglBindAPI(EGL.EGL_OPENGL_ES_API)) { + throw new GLException("eglBindAPI to ES failed , error 0x"+Integer.toHexString(EGL.eglGetError())); + } + } catch (GLException glex) { + if (DEBUG) { + glex.printStackTrace(); + } + } + + EGLContext other = (EGLContext) GLContextShareSet.getShareContext(this); + if (other != null) { + shareWith = other.getContext(); + if (shareWith == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + + int[] contextAttrs = new int[] { + EGL.EGL_CONTEXT_CLIENT_VERSION, -1, + EGL.EGL_NONE + }; + if (glProfile.usesNativeGLES2()) { + contextAttrs[1] = 2; + } else if (glProfile.usesNativeGLES1()) { + contextAttrs[1] = 1; + } else { + throw new GLException("Error creating OpenGL context - invalid GLProfile: "+glProfile); + } + eglContext = EGL.eglCreateContext(eglDisplay, eglConfig, shareWith, contextAttrs, 0); + if (eglContext == 0) { + throw new GLException("Error creating OpenGL context: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", "+glProfile+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + GLContextShareSet.contextCreated(this); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created OpenGL context 0x" + + Long.toHexString(eglContext) + + ",\n\twrite surface 0x" + Long.toHexString(((EGLDrawable)drawable).getSurface()) + + ",\n\tread surface 0x" + Long.toHexString(((EGLDrawable)drawableRead).getSurface())+ + ",\n\t"+this+ + ",\n\tsharing with 0x" + Long.toHexString(shareWith)); + } + if (!EGL.eglMakeCurrent(((EGLDrawable)drawable).getDisplay(), + ((EGLDrawable)drawable).getSurface(), + ((EGLDrawable)drawableRead).getSurface(), + eglContext)) { + throw new GLException("Error making context 0x" + + Long.toHexString(eglContext) + " current: error code " + EGL.eglGetError()); + } + setGLFunctionAvailability(true, glProfile.usesNativeGLES2()?2:1, 0, CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + } + + public boolean isCreated() { + return (eglContext != 0); + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing EGL extension address table"); + } + eglQueryStringInitialized = false; + eglQueryStringAvailable = false; + + if (eglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + eglExtProcAddressTable = new EGLExtProcAddressTable(); + } + resetProcAddressTable(getEGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public synchronized String getPlatformExtensionsString() { + if (!eglQueryStringInitialized) { + eglQueryStringAvailable = + getDrawableImpl().getDynamicLookupHelper().dynamicLookupFunction("eglQueryString") != 0; + eglQueryStringInitialized = true; + } + if (eglQueryStringAvailable) { + GLDrawableFactoryImpl factory = getDrawableImpl().getFactoryImpl(); + factory.lockToolkit(); + try { + String ret = EGL.eglQueryString(((EGLDrawable)drawable).getDisplay(), + EGL.EGL_EXTENSIONS); + if (DEBUG) { + System.err.println("!!! EGL extensions: " + ret); + } + return ret; + } finally { + factory.unlockToolkit(); + } + } else { + return ""; + } + } + + protected void setSwapIntervalImpl(int interval) { + if (EGL.eglSwapInterval(((EGLDrawable)drawable).getDisplay(), interval)) { + currentSwapInterval = interval ; + } + } + + public abstract void bindPbufferToTexture(); + + public abstract void releasePbufferFromTexture(); + + //---------------------------------------------------------------------- + // Currently unimplemented stuff + // + + public void copy(GLContext source, int mask) throws GLException { + throw new GLException("Not yet implemented"); + } + + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java new file mode 100755 index 000000000..dcfe06bdc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.os.DynamicLookupHelper; +import com.jogamp.opengl.impl.GLDrawableImpl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import javax.media.opengl.*; + +public abstract class EGLDrawable extends GLDrawableImpl { + protected boolean ownEGLDisplay = false; // for destruction + protected boolean ownEGLSurface = false; // for destruction + private EGLGraphicsConfiguration eglConfig; + protected long eglDisplay; + protected long eglSurface; + + protected EGLDrawable(EGLDrawableFactory factory, + NativeWindow component) throws GLException { + super(factory, component, false); + eglSurface=EGL.EGL_NO_SURFACE; + eglDisplay=0; + } + + public long getDisplay() { + return eglDisplay; + } + + public long getSurface() { + return eglSurface; + } + + public EGLGraphicsConfiguration getGraphicsConfiguration() { + return eglConfig; + } + + public GLCapabilities getChosenGLCapabilities() { + return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilities)eglConfig.getChosenCapabilities(); + } + + public abstract GLContext createContext(GLContext shareWith); + + protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + + private void recreateSurface() { + // create a new EGLSurface .. + if(EGL.EGL_NO_SURFACE!=eglSurface) { + EGL.eglDestroySurface(eglDisplay, eglSurface); + } + + if(DEBUG) { + System.err.println("createSurface using eglDisplay 0x"+Long.toHexString(eglDisplay)+", "+eglConfig); + } + + eglSurface = createSurface(eglDisplay, eglConfig.getNativeConfig(), component.getSurfaceHandle()); + if (EGL.EGL_NO_SURFACE==eglSurface) { + throw new GLException("Creation of window surface failed: "+eglConfig+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + + if(DEBUG) { + System.err.println("setSurface using component: handle 0x"+Long.toHexString(component.getSurfaceHandle())+" -> 0x"+Long.toHexString(eglSurface)); + } + } + + protected void setRealizedImpl() { + if (realized) { + if ( NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface() ) { + throw new GLException("Couldn't lock surface"); + } + // lockSurface() also resolved the window/surface handles + try { + AbstractGraphicsConfiguration aConfig = component.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if(aDevice instanceof EGLGraphicsDevice) { + // just fetch the data .. trust but verify .. + eglDisplay = aDevice.getHandle(); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice from "+aDevice); + } + if(aConfig instanceof EGLGraphicsConfiguration) { + eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. + if (null == eglConfig) { + throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); + } + + int[] tmp = new int[1]; + if ( 0 != component.getSurfaceHandle() && + EGL.eglQuerySurface(eglDisplay, component.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { + // component holds static EGLSurface + eglSurface = component.getSurfaceHandle(); + if(DEBUG) { + System.err.println("setSurface re-using component's EGLSurface: handle 0x"+Long.toHexString(eglSurface)); + } + } else { + // EGLSurface is ours .. + ownEGLSurface=true; + + eglConfig.updateGraphicsConfiguration(); + + recreateSurface(); + } + } else { + throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + } + } else { + // create a new EGL config .. + ownEGLDisplay=true; + // EGLSurface is ours .. + ownEGLSurface=true; + + long nDisplay=0; + if( NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { + nDisplay = component.getSurfaceHandle(); // don't even ask .. + } else { + nDisplay = aDevice.getHandle(); // 0 == EGL.EGL_DEFAULT_DISPLAY + } + eglDisplay = EGL.eglGetDisplay(nDisplay); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + if(DEBUG) { + System.err.println("eglDisplay("+Long.toHexString(nDisplay)+" <surfaceHandle>): failed, using EGL_DEFAULT_DISPLAY"); + } + nDisplay = EGL.EGL_DEFAULT_DISPLAY; + eglDisplay = EGL.eglGetDisplay(nDisplay); + } + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: nhandle 0x"+Long.toHexString(nDisplay)+", "+aDevice+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("eglDisplay("+Long.toHexString(nDisplay)+"): 0x"+Long.toHexString(eglDisplay)); + } + if (!EGL.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay); + DefaultGraphicsScreen s = new DefaultGraphicsScreen(e, aConfig.getScreen().getIndex()); + GLCapabilities caps = (GLCapabilities) aConfig.getChosenCapabilities(); // yes, use the already choosen Capabilities (x11,win32,..) + eglConfig = (EGLGraphicsConfiguration) GraphicsConfigurationFactory.getFactory(e).chooseGraphicsConfiguration(caps, null, s); + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); + } else if(DEBUG) { + System.err.println("Chosen eglConfig: "+eglConfig); + } + recreateSurface(); + } + } finally { + unlockSurface(); + } + } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + // Destroy the window surface + if (!EGL.eglDestroySurface(eglDisplay, eglSurface)) { + throw new GLException("Error destroying window surface (eglDestroySurface)"); + } + eglSurface = EGL.EGL_NO_SURFACE; + if (ownEGLDisplay && EGL.EGL_NO_DISPLAY!=eglDisplay) { + EGL.eglTerminate(eglDisplay); + } + eglDisplay=EGL.EGL_NO_DISPLAY; + eglConfig=null; + } + } + + public int getWidth() { + int[] tmp = new int[1]; + if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { + throw new GLException("Error querying surface width"); + } + return tmp[0]; + } + + public int getHeight() { + int[] tmp = new int[1]; + if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { + throw new GLException("Error querying surface height"); + } + return tmp[0]; + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return EGLDynamicLookupHelper.getDynamicLookupHelper(getGLProfile()); + } + + public String toString() { + return getClass().getName()+"[realized "+getRealized()+ + ",\n\tfactory "+getFactory()+ + ",\n\twindow "+getNativeWindow()+ + ",\n\teglSurface 0x"+Long.toHexString(eglSurface)+ + ",\n\teglConfig "+eglConfig+ + ",\n\trequested "+getRequestedGLCapabilities()+ + ",\n\tchosen "+getChosenGLCapabilities()+"]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java new file mode 100755 index 000000000..4fccf22f8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class EGLDrawableFactory extends GLDrawableFactoryImpl { + + static { + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new EGLGraphicsConfigurationFactory(); + + // Check for other underlying stuff .. + if(NativeWindowFactory.TYPE_X11.equals(NativeWindowFactory.getNativeWindowType(true))) { + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.x11.glx.X11GLXGraphicsConfigurationFactory"); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + } + + public EGLDrawableFactory() { + super(); + } + + + protected final GLDrawableImpl getSharedDrawable() { return null; } + protected final GLContextImpl getSharedContext() { return null; } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new EGLOnscreenDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + throw new GLException("Not yet implemented"); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + return true; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(NativeWindow target) { + return new EGLPbufferDrawable(this, target); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + NullWindow nw = new NullWindow(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(capabilities, chooser)); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + AbstractGraphicsScreen absScreen = DefaultGraphicsScreen.createScreenDevice(0); + return new EGLExternalContext(absScreen); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + return false; + } + + public GLDrawable createExternalGLDrawable() { + throw new GLException("Not yet implemented"); + } + + public void loadGLULibrary() { + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("Unimplemented on this platform"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java new file mode 100755 index 000000000..9e34dc9e9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.os.DynamicLookupHelper; +import com.jogamp.common.os.NativeLibrary; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import java.security.*; + +/** + * Abstract implementation of the DynamicLookupHelper for EGL, + * which decouples it's dependencies to EGLDrawableFactory. + * + * Currently two implementations exist, one for ES1 and one for ES2. + */ +public abstract class EGLDynamicLookupHelper implements DynamicLookupHelper { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("EGL"); + protected static final boolean DEBUG_LOOKUP; + + private static final EGLDynamicLookupHelper eglES1DynamicLookupHelper; + private static final EGLDynamicLookupHelper eglES2DynamicLookupHelper; + private List/*<NativeLibrary>*/ glesLibraries; + + static { + AccessControlContext localACC=AccessController.getContext(); + DEBUG_LOOKUP = com.jogamp.opengl.impl.Debug.isPropertyDefined("jogl.debug.DynamicLookup", true, localACC); + + EGLDynamicLookupHelper tmp=null; + try { + tmp = new EGLES1DynamicLookupHelper(); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES1DynamicLookupHelper = tmp; + + tmp=null; + try { + tmp = new EGLES2DynamicLookupHelper(); + } catch (GLException gle) { + if(DEBUG) { + gle.printStackTrace(); + } + } + eglES2DynamicLookupHelper = tmp; + } + + public static EGLDynamicLookupHelper getDynamicLookupHelper(GLProfile glp) { + if (glp.usesNativeGLES2()) { + if(null==eglES2DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES2 not available"); + } + return eglES2DynamicLookupHelper; + } else if (glp.usesNativeGLES1()) { + if(null==eglES1DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES1 not available"); + } + return eglES1DynamicLookupHelper; + } else { + throw new GLException("Unsupported: "+glp); + } + } + + public static EGLDynamicLookupHelper getDynamicLookupHelper(int esProfile) { + if (2==esProfile) { + if(null==eglES2DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES2 not available"); + } + return eglES2DynamicLookupHelper; + } else if (1==esProfile) { + if(null==eglES1DynamicLookupHelper) { + throw new GLException("EGLDynamicLookupHelper for ES1 not available"); + } + return eglES1DynamicLookupHelper; + } else { + throw new GLException("Unsupported: ES"+esProfile); + } + } + + protected EGLDynamicLookupHelper() { + loadGLESLibrary(getESProfile()); + EGL.resetProcAddressTable(this); + } + + /** Must return the proper ES profile number, 1 for ES1 and 2 for ES2 */ + protected abstract int getESProfile(); + + /** Must return at least one OpenGL ES library name */ + protected abstract List/*<String>*/ getGLESLibNames(); + + /** May return OpenGL ES library name(s) */ + protected List/*<String>*/ getEGLLibNames() { + List/*<String>*/ eglLibNames = new ArrayList(); + + // EGL + eglLibNames.add("EGL"); + // for windows distributions using the 'unlike' lib prefix, + // where our tool does not add it. + eglLibNames.add("libEGL"); + + return eglLibNames; + } + + private NativeLibrary loadFirstAvailable(List/*<String>*/ libNames, ClassLoader loader) { + for (Iterator iter = libNames.iterator(); iter.hasNext(); ) { + NativeLibrary lib = NativeLibrary.open((String) iter.next(), loader, false /*global*/); + if (lib != null) { + return lib; + } + } + return null; + } + + private boolean loadEGLLibrary(ClassLoader loader, List/*<String>*/ eglLibNames) { + NativeLibrary lib = null; + if(null!=eglLibNames && eglLibNames.size()>0) { + // EGL libraries .. + lib = loadFirstAvailable(eglLibNames, loader); + if ( null != lib ) { + glesLibraries.add(lib); + } + } + return null!=lib; + } + + private void loadGLESLibrary(int esProfile) { + List/*<String>*/ glesLibNames = getGLESLibNames(); + List/*<String>*/ eglLibNames = getEGLLibNames(); + boolean eglLoaded = false; + + ClassLoader loader = getClass().getClassLoader(); + NativeLibrary lib = null; + + glesLibraries = new ArrayList(); + + // ES libraries .. + lib = loadFirstAvailable(glesLibNames, loader); + if ( null == lib ) { + /*** FIXME: Have to think about this .. + // try again with EGL loaded first .. + if ( !eglLoaded && loadEGLLibrary(loader, eglLibNames) ) { + eglLoaded = true ; + lib = loadFirstAvailable(glesLibNames, loader); + } + if ( null == lib ) { + throw new GLException("Unable to dynamically load OpenGL ES library for profile ES" + esProfile); + } */ + throw new GLException("Unable to dynamically load OpenGL ES library for profile ES" + esProfile); + } + glesLibraries.add(lib); + + if ( !eglLoaded && !loadEGLLibrary(loader, eglLibNames) ) { + throw new GLException("Unable to dynamically load EGL library for profile ES" + esProfile); + } + + if (esProfile==2) { + GLJNILibLoader.loadES2(); + } else if (esProfile==1) { + GLJNILibLoader.loadES1(); + } else { + throw new GLException("Unsupported: ES"+esProfile); + } + } + + private long dynamicLookupFunctionOnLibs(String glFuncName) { + String funcName=glFuncName; + long addr = dynamicLookupFunctionOnLibsImpl(funcName); + if( 0==addr && NativeWindowFactory.TYPE_WINDOWS.equals(NativeWindowFactory.getNativeWindowType(false)) ) { + // Hack: try some C++ decoration here for Imageon's emulation libraries .. + final int argAlignment=4; // 4 byte alignment of each argument + final int maxArguments=12; // experience .. + for(int arg=0; 0==addr && arg<=maxArguments; arg++) { + funcName = "_"+glFuncName+"@"+(arg*argAlignment); + addr = dynamicLookupFunctionOnLibsImpl(funcName); + } + } + if(DEBUG_LOOKUP) { + if(0!=addr) { + System.err.println("Lookup-Native: "+glFuncName+" / "+funcName+" 0x"+Long.toHexString(addr)); + } else { + System.err.println("Lookup-Native: "+glFuncName+" / "+funcName+" ** FAILED ** "); + } + } + return addr; + } + + private long dynamicLookupFunctionOnLibsImpl(String glFuncName) { + // Look up this function name in all known libraries + for (Iterator iter = glesLibraries.iterator(); iter.hasNext(); ) { + NativeLibrary lib = (NativeLibrary) iter.next(); + long addr = lib.dynamicLookupFunction(glFuncName); + if (addr != 0) { + return addr; + } + } + return 0; + } + + private long eglGetProcAddressHandle = 0; + + public long dynamicLookupFunction(String glFuncName) { + if(null==glFuncName) { + return 0; + } + + // bootstrap eglGetProcAddress + if(0==eglGetProcAddressHandle) { + eglGetProcAddressHandle = dynamicLookupFunctionOnLibs("eglGetProcAddress"); + if(0==eglGetProcAddressHandle) { + GLException e = new GLException("Couldn't find eglGetProcAddress function entry"); + if(DEBUG) { + e.printStackTrace(); + } + throw e; + } + } + + if(glFuncName.equals("eglGetProcAddress")) { + return eglGetProcAddressHandle; + } + + long addr = EGL.eglGetProcAddress(eglGetProcAddressHandle, glFuncName); + if(DEBUG_LOOKUP) { + if(0!=addr) { + System.err.println("Lookup-EGL: <"+glFuncName+"> 0x"+Long.toHexString(addr)); + } + } + if(0==addr) { + addr = dynamicLookupFunctionOnLibs(glFuncName); + } + return addr; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java new file mode 100755 index 000000000..e5740a4f0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import java.util.*; + +/** + * Implementation of the EGLDynamicLookupHelper for ES1. + */ +public class EGLES1DynamicLookupHelper extends EGLDynamicLookupHelper { + + protected EGLES1DynamicLookupHelper() { + super(); + } + + protected int getESProfile() { + return 1; + } + + protected List/*<String>*/ getGLESLibNames() { + List/*<String>*/ glesLibNames = new ArrayList(); + + glesLibNames.add("GLES_CM"); + glesLibNames.add("GLES_CL"); + glesLibNames.add("GLESv1_CM"); + // for windows distributions using the 'unlike' lib prefix, + // where our tool does not add it. + glesLibNames.add("libGLES_CM"); + glesLibNames.add("libGLES_CL"); + glesLibNames.add("libGLESv1_CM"); + + return glesLibNames; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java new file mode 100755 index 000000000..c4fc66630 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import java.util.*; + +/** + * Implementation of the EGLDynamicLookupHelper for ES2. + */ +public class EGLES2DynamicLookupHelper extends EGLDynamicLookupHelper { + + protected EGLES2DynamicLookupHelper() { + super(); + } + + protected int getESProfile() { + return 2; + } + + protected List/*<String>*/ getGLESLibNames() { + List/*<String>*/ glesLibNames = new ArrayList(); + + glesLibNames.add("GLES20"); + glesLibNames.add("GLESv2"); + glesLibNames.add("GLESv2_CM"); + // for windows distributions using the 'unlike' lib prefix + // where our tool does not add it. + glesLibNames.add("libGLES20"); + glesLibNames.add("libGLESv2"); + glesLibNames.add("libGLESv2_CM"); + + return glesLibNames; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java new file mode 100755 index 000000000..5a8454ea7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLExternalContext.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import javax.media.nativewindow.*; + +public class EGLExternalContext extends EGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + public EGLExternalContext(AbstractGraphicsScreen screen) { + super(null, null); + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_IS_ARB_CREATED|CTX_PROFILE_ES|CTX_PROFILE_CORE|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java new file mode 100644 index 000000000..2d5154442 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfiguration.java @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.nio.PointerBuffer; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class EGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public long getNativeConfig() { + return config; + } + + public int getNativeConfigID() { + return configID; + } + + public EGLGraphicsConfiguration(AbstractGraphicsScreen absScreen, + GLCapabilities capsChosen, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + long cfg, int cfgID) { + super(absScreen, capsChosen, capsRequested); + this.chooser = chooser; + config = cfg; + configID = cfgID; + } + + public static EGLGraphicsConfiguration create(GLCapabilities capsRequested, AbstractGraphicsScreen absScreen, int cfgID) { + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) { + throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice"); + } + long dpy = absDevice.getHandle(); + if (dpy == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+absDevice); + } + GLProfile glp = capsRequested.getGLProfile(); + long cfg = EGLConfigId2EGLConfig(glp, dpy, cfgID); + GLCapabilities caps = EGLConfig2Capabilities(glp, dpy, cfg, false, capsRequested.isOnscreen(), capsRequested.isPBuffer()); + return new EGLGraphicsConfiguration(absScreen, caps, capsRequested, new DefaultGLCapabilitiesChooser(), cfg, cfgID); + } + + public Object clone() { + return super.clone(); + } + + protected void updateGraphicsConfiguration() { + EGLGraphicsConfiguration newConfig = (EGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(getRequestedCapabilities(), + chooser, + getScreen()); + if(null!=newConfig) { + // FIXME: setScreen( ... ); + setChosenCapabilities(newConfig.getChosenCapabilities()); + config = newConfig.getNativeConfig(); + configID = newConfig.getNativeConfigID(); + if(DEBUG) { + System.err.println("!!! updateGraphicsConfiguration: "+this); + } + } + } + + public static long EGLConfigId2EGLConfig(GLProfile glp, long display, int configID) { + int[] attrs = new int[] { + EGL.EGL_CONFIG_ID, configID, + EGL.EGL_NONE + }; + PointerBuffer configs = PointerBuffer.allocateDirect(1); + int[] numConfigs = new int[1]; + if (!EGL.eglChooseConfig(display, + attrs, 0, + configs, 1, + numConfigs, 0)) { + return 0; + } + if (numConfigs[0] == 0) { + return 0; + } + return configs.get(0); + } + + public static boolean EGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & EGL.EGL_WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & EGL.EGL_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & EGL.EGL_PIXMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, + boolean relaxed, boolean onscreen, boolean usePBuffer) { + GLCapabilities caps = new GLCapabilities(glp); + int[] val = new int[1]; + + // Read the actual configuration into the choosen caps + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_RED_SIZE, val, 0)) { + caps.setRedBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_GREEN_SIZE, val, 0)) { + caps.setGreenBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_BLUE_SIZE, val, 0)) { + caps.setBlueBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_ALPHA_SIZE, val, 0)) { + caps.setAlphaBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_STENCIL_SIZE, val, 0)) { + caps.setStencilBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_DEPTH_SIZE, val, 0)) { + caps.setDepthBits(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SAMPLES, val, 0)) { + caps.setSampleBuffers(val[0]>0?true:false); + caps.setNumSamples(val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_TYPE, val, 0)) { + caps.setBackgroundOpaque(val[0] != EGL.EGL_TRANSPARENT_RGB); + } + if(!caps.isBackgroundOpaque()) { + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_RED_VALUE, val, 0)) { + caps.setTransparentRedValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_GREEN_VALUE, val, 0)) { + caps.setTransparentGreenValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_BLUE_VALUE, val, 0)) { + caps.setTransparentBlueValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } + /** Not defined in EGL + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_TRANSPARENT_ALPHA_VALUE, val, 0)) { + caps.setTransparentAlphaValue(val[0]==EGL.EGL_DONT_CARE?-1:val[0]); + } */ + } + if(EGL.eglGetConfigAttrib(display, config, EGL.EGL_SURFACE_TYPE, val, 0)) { + if(EGLConfigDrawableTypeVerify(val[0], onscreen, usePBuffer)) { + caps.setDoubleBuffered(onscreen); + caps.setOnscreen(onscreen); + caps.setPBuffer(usePBuffer); + } else if(relaxed) { + caps.setDoubleBuffered( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); + caps.setOnscreen( 0 != (val[0] & EGL.EGL_WINDOW_BIT) ); + caps.setPBuffer ( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("EGL_SURFACE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val[0] & EGL.EGL_WINDOW_BIT) )+", pbuffer "+( 0 != (val[0] & EGL.EGL_PBUFFER_BIT) )+", pixmap "+( 0 != (val[0] & EGL.EGL_PIXMAP_BIT) )+")"); + } + return null; + } + } else { + throw new GLException("Could not determine EGL_SURFACE_TYPE !!!"); + } + + return caps; + } + + public static int[] GLCapabilities2AttribList(GLCapabilities caps) { + int[] attrs = new int[32]; + int idx=0; + + attrs[idx++] = EGL.EGL_SURFACE_TYPE; + attrs[idx++] = caps.isOnscreen() ? ( EGL.EGL_WINDOW_BIT ) : ( caps.isPBuffer() ? EGL.EGL_PBUFFER_BIT : EGL.EGL_PIXMAP_BIT ) ; + + attrs[idx++] = EGL.EGL_RED_SIZE; + attrs[idx++] = caps.getRedBits(); + + attrs[idx++] = EGL.EGL_GREEN_SIZE; + attrs[idx++] = caps.getGreenBits(); + + attrs[idx++] = EGL.EGL_BLUE_SIZE; + attrs[idx++] = caps.getBlueBits(); + + attrs[idx++] = EGL.EGL_ALPHA_SIZE; + attrs[idx++] = caps.getAlphaBits() > 0 ? caps.getAlphaBits() : EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_STENCIL_SIZE; + attrs[idx++] = caps.getStencilBits() > 0 ? caps.getStencilBits() : EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_DEPTH_SIZE; + attrs[idx++] = caps.getDepthBits(); + + attrs[idx++] = EGL.EGL_SAMPLES; + attrs[idx++] = caps.getSampleBuffers() ? caps.getNumSamples() : 1; + + attrs[idx++] = EGL.EGL_TRANSPARENT_TYPE; + attrs[idx++] = caps.isBackgroundOpaque() ? EGL.EGL_NONE : EGL.EGL_TRANSPARENT_TYPE; + + // 20 + + if(!caps.isBackgroundOpaque()) { + attrs[idx++] = EGL.EGL_TRANSPARENT_RED_VALUE; + attrs[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_TRANSPARENT_GREEN_VALUE; + attrs[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():EGL.EGL_DONT_CARE; + + attrs[idx++] = EGL.EGL_TRANSPARENT_BLUE_VALUE; + attrs[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():EGL.EGL_DONT_CARE; + + /** Not define in EGL + attrs[idx++] = EGL.EGL_TRANSPARENT_ALPHA_VALUE; + attrs[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():EGL.EGL_DONT_CARE; */ + } + + // 26 + + attrs[idx++] = EGL.EGL_RENDERABLE_TYPE; + if(caps.getGLProfile().usesNativeGLES1()) { + attrs[idx++] = EGL.EGL_OPENGL_ES_BIT; + } + else if(caps.getGLProfile().usesNativeGLES2()) { + attrs[idx++] = EGL.EGL_OPENGL_ES2_BIT; + } else { + attrs[idx++] = EGL.EGL_OPENGL_BIT; + } + + // 28 + + attrs[idx++] = EGL.EGL_NONE; + + return attrs; + } + + public static int[] CreatePBufferSurfaceAttribList(int width, int height, int texFormat) { + int[] attrs = new int[16]; + int idx=0; + + attrs[idx++] = EGL.EGL_WIDTH; + attrs[idx++] = width; + + attrs[idx++] = EGL.EGL_HEIGHT; + attrs[idx++] = height; + + attrs[idx++] = EGL.EGL_TEXTURE_FORMAT; + attrs[idx++] = texFormat; + + attrs[idx++] = EGL.EGL_TEXTURE_TARGET; + attrs[idx++] = EGL.EGL_NO_TEXTURE==texFormat ? EGL.EGL_NO_TEXTURE : EGL.EGL_TEXTURE_2D; + + attrs[idx++] = EGL.EGL_NONE; + + return attrs; + } + + public String toString() { + return getClass().toString()+"["+getScreen()+", eglConfigID 0x"+Integer.toHexString(configID)+ + ",\n\trequested " + getRequestedCapabilities()+ + ",\n\tchosen " + getChosenCapabilities()+ + "]"; + + } + + private GLCapabilitiesChooser chooser; + private long config; + private int configID; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..33e301ee9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.egl; + +import com.jogamp.common.nio.PointerBuffer; +import java.io.PrintStream; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; + +import javax.media.opengl.*; + + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on X11 platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class EGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = GraphicsConfigurationFactory.DEBUG || com.jogamp.opengl.impl.Debug.debug("EGL"); + + public EGLGraphicsConfigurationFactory() { + // become the selector for KD/EGL .. + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.egl.EGLGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (absScreen == null) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only AbstractGraphicsDevice objects"); + } + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + return chooseGraphicsConfigurationStatic((GLCapabilities) capabilities, + (GLCapabilitiesChooser) chooser, + absScreen); + } + + public static EGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + GLProfile glp = capabilities.getGLProfile(); + + if(null==absScreen) { + throw new GLException("Null AbstractGraphicsScreen"); + } + AbstractGraphicsDevice absDevice = absScreen.getDevice(); + + if(null==absDevice || !(absDevice instanceof EGLGraphicsDevice)) { + throw new GLException("GraphicsDevice must be a valid EGLGraphicsDevice"); + } + long eglDisplay = absDevice.getHandle(); + + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Invalid EGL display: "+absDevice); + } + + GLCapabilities caps2 = (GLCapabilities) capabilities.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + + EGLGraphicsConfiguration res = eglChooseConfig(eglDisplay, caps2, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + if(DEBUG) { + System.err.println("eglChooseConfig failed with given capabilities "+caps2); + } + + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + + PointerBuffer configs = PointerBuffer.allocateDirect(10); + int[] numConfigs = new int[1]; + + if(!EGL.eglGetConfigs(eglDisplay, configs, configs.capacity(), numConfigs, 0)) { + throw new GLException("Graphics configuration fetch (eglGetConfigs) failed"); + } + if (numConfigs[0] == 0) { + throw new GLException("Graphics configuration fetch (eglGetConfigs) - no EGLConfig found"); + } + GLCapabilities[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], + caps2.isOnscreen(), caps2.isPBuffer()); + if(DEBUG) { + System.err.println("EGL Get Configs: "+numConfigs[0]+", Caps "+caps.length); + printCaps("eglGetConfigs", caps, System.err); + } + int chosen = -1; + try { + chosen = chooser.chooseCapabilities(caps2, caps, -1); + } catch (NativeWindowException e) { throw new GLException(e); } + if(chosen<0) { + throw new GLException("Graphics configuration chooser failed"); + } + if(DEBUG) { + System.err.println("Chosen "+caps[chosen]); + } + res = eglChooseConfig(eglDisplay, caps[chosen], capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + if(DEBUG) { + System.err.println("eglChooseConfig failed with eglGetConfig/choosen capabilities "+caps[chosen]); + } + + // Last try .. add a fixed embedded profile [ATI, Nokia, Intel, ..] + // + // rgb888 - d16, s4 + GLCapabilities fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(8); + fixedCaps.setGreenBits(8); + fixedCaps.setBlueBits(8); + fixedCaps.setDepthBits(16); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); + if(DEBUG) { + System.err.println("trying fixed caps (1): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + + // + // rgb565 - d16, s0 + fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(5); + fixedCaps.setGreenBits(6); + fixedCaps.setBlueBits(5); + fixedCaps.setDepthBits(16); + if(DEBUG) { + System.err.println("trying fixed caps (2): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + + // + // rgb565 - d16, s4 + fixedCaps = new GLCapabilities(glp); + fixedCaps.setRedBits(5); + fixedCaps.setGreenBits(6); + fixedCaps.setBlueBits(5); + fixedCaps.setDepthBits(16); + fixedCaps.setSampleBuffers(true); + fixedCaps.setNumSamples(4); + if(DEBUG) { + System.err.println("trying fixed caps (3): "+fixedCaps); + } + res = eglChooseConfig(eglDisplay, fixedCaps, capabilities, chooser, absScreen); + if(null!=res) { + return res; + } + throw new GLException("Graphics configuration failed [direct caps, eglGetConfig/chooser and fixed-caps(1-3)]"); + } + + protected static EGLGraphicsConfiguration eglChooseConfig(long eglDisplay, + GLCapabilities capsChosen0, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GLProfile glp = capsChosen0.getGLProfile(); + int[] attrs = EGLGraphicsConfiguration.GLCapabilities2AttribList(capsChosen0); + PointerBuffer configs = PointerBuffer.allocateDirect(1); + int[] numConfigs = new int[1]; + if (!EGL.eglChooseConfig(eglDisplay, + attrs, 0, + configs, configs.capacity(), + numConfigs, 0)) { + throw new GLException("Graphics configuration selection (eglChooseConfig) failed for "+capsChosen0); + } + if (numConfigs[0] > 0) { + if(DEBUG) { + GLCapabilities[] caps = eglConfigs2GLCaps(glp, eglDisplay, configs, numConfigs[0], + capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); + System.err.println("EGL Choose Configs: "+numConfigs[0]+", Caps "+caps.length); + printCaps("eglChooseConfig", caps, System.err); + } + int[] val = new int[1]; + // get the configID + if(!EGL.eglGetConfigAttrib(eglDisplay, configs.get(0), EGL.EGL_CONFIG_ID, val, 0)) { + if(DEBUG) { + // FIXME: this happens on a ATI PC Emulation .. + System.err.println("EGL couldn't retrieve ConfigID for already chosen eglConfig "+capsChosen0+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return null; + } + GLCapabilities capsChosen1 = EGLGraphicsConfiguration.EGLConfig2Capabilities(glp, eglDisplay, configs.get(0), + true, capsChosen0.isOnscreen(), capsChosen0.isPBuffer()); + if(null!=capsChosen1) { + if(DEBUG) { + System.err.println("eglChooseConfig found: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", eglConfig ID 0x"+Integer.toHexString(val[0])+ + ", "+capsChosen0+" -> "+capsChosen1); + } + return new EGLGraphicsConfiguration(absScreen, capsChosen1, capsRequested, chooser, configs.get(0), val[0]); + } + if(DEBUG) { + System.err.println("eglChooseConfig couldn't verify: eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", eglConfig ID 0x"+Integer.toHexString(val[0])+ + ", for "+capsChosen0); + } + } else { + if(DEBUG) { + System.err.println("EGL Choose Configs: None using eglDisplay 0x"+Long.toHexString(eglDisplay)+ + ", "+capsChosen0); + } + } + return null; + } + + protected static GLCapabilities[] eglConfigs2GLCaps(GLProfile glp, long eglDisplay, PointerBuffer configs, int num, + boolean onscreen, boolean usePBuffer) { + GLCapabilities[] caps = new GLCapabilities[num]; + for(int i=0; i<num; i++) { + caps[i] = EGLGraphicsConfiguration.EGLConfig2Capabilities(glp, eglDisplay, configs.get(i), + true, onscreen, usePBuffer); + } + return caps; + } + + protected static void printCaps(String prefix, GLCapabilities[] caps, PrintStream out) { + for(int i=0; i<caps.length; i++) { + out.println(prefix+"["+i+"] "+caps[i]); + } + } + + protected static EGLGraphicsConfiguration createOffscreenGraphicsConfiguration(GLCapabilities caps, GLCapabilitiesChooser chooser) { + if(caps.isOnscreen()) { + throw new GLException("Error: Onscreen set: "+caps); + } + caps.setDoubleBuffered(false); // FIXME DBLBUFOFFSCRN + long eglDisplay = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL default display: error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("eglDisplay(EGL_DEFAULT_DISPLAY): 0x"+Long.toHexString(eglDisplay)); + } + if (!EGL.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + EGLGraphicsDevice e = new EGLGraphicsDevice(eglDisplay); + DefaultGraphicsScreen s = new DefaultGraphicsScreen(e, 0); + EGLGraphicsConfiguration eglConfig = chooseGraphicsConfigurationStatic(caps, chooser, s); + if (null == eglConfig) { + EGL.eglTerminate(eglDisplay); + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+s); + } else if(DEBUG) { + System.err.println("Chosen eglConfig: "+eglConfig); + } + return eglConfig; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java new file mode 100755 index 000000000..b74991671 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenContext.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public class EGLOnscreenContext extends EGLContext { + public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + return super.makeCurrentImpl(); + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java new file mode 100644 index 000000000..3864fc39c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class EGLOnscreenDrawable extends EGLDrawable { + protected EGLOnscreenDrawable(EGLDrawableFactory factory, NativeWindow component) throws GLException { + super(factory, component); + } + + public GLContext createContext(GLContext shareWith) { + return new EGLOnscreenContext(this, shareWith); + } + + protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { + return EGL.eglCreateWindowSurface(eglDpy, eglNativeCfg, surfaceHandle, null); + } + + protected void swapBuffersImpl() { + boolean didLock = false; + if (!isSurfaceLocked()) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + EGL.eglSwapBuffers(eglDisplay, eglSurface); + } finally { + if (didLock) { + unlockSurface(); + } + } + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java new file mode 100755 index 000000000..5c634b9bd --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferContext.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; +import java.nio.*; +import java.util.*; + +public class EGLPbufferContext extends EGLContext { + public EGLPbufferContext(EGLPbufferDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + public int getFloatingPointMode() { + return 0; // FIXME ?? + } + + public void bindPbufferToTexture() { + throw new GLException("Not yet implemented"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Not yet implemented"); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java new file mode 100644 index 000000000..03b02b77e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLPbufferDrawable.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.egl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.egl.*; +import com.jogamp.opengl.impl.*; + +public class EGLPbufferDrawable extends EGLDrawable { + private int texFormat; + protected static final boolean useTexture = false; // No yet .. + + protected EGLPbufferDrawable(EGLDrawableFactory factory, NativeWindow target) { + super(factory, target); + ownEGLDisplay = true; + + // get choosen ones .. + GLCapabilities caps = (GLCapabilities) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + + if(useTexture) { + this.texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + this.texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + setRealized(true); + + if (DEBUG) { + System.out.println("Created pbuffer: " + this); + } + + } + + protected long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle) { + NativeWindow nw = getNativeWindow(); + int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(nw.getWidth(), nw.getHeight(), texFormat); + long surf = EGL.eglCreatePbufferSurface(eglDpy, eglNativeCfg, attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+nw.getWidth()+"x"+nw.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ((SurfaceChangeable)nw).setSurfaceHandle(surf); + return surf; + } + + public GLContext createContext(GLContext shareWith) { + return new EGLPbufferContext(this, shareWith); + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java new file mode 100755 index 000000000..2eb3ca5df --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/ProjectDouble.java @@ -0,0 +1,1041 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-13 22:20:29 -0700 (Fri, 13 Mar 2009) $ $Revision: 1867 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ +package com.jogamp.opengl.impl.gl2; + +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** + * Project.java + * <p/> + * <p/> + * Created 11-jan-2004 + * + * @author Erik Duijs + * @author Kenneth Russell + */ +public class ProjectDouble { + private static final double[] IDENTITY_MATRIX = + new double[] { + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 }; + + // Note that we have cloned parts of the implementation in order to + // support incoming Buffers. The reason for this is to avoid loading + // non-direct buffer subclasses unnecessarily, because doing so can + // cause performance decreases on direct buffer operations, at least + // on the current HotSpot JVM. It would be nicer (and make the code + // simpler) to simply have the array-based entry points delegate to + // the versions taking Buffers by wrapping the arrays. + + // Array-based implementation + private final double[] matrix = new double[16]; + + private final double[][] tempMatrix = new double[4][4]; + private final double[] in = new double[4]; + private final double[] out = new double[4]; + + private final double[] forward = new double[3]; + private final double[] side = new double[3]; + private final double[] up = new double[3]; + + // Buffer-based implementation + private DoubleBuffer locbuf; + private final DoubleBuffer matrixBuf; + + private final DoubleBuffer tempMatrixBuf; + private final DoubleBuffer inBuf; + private final DoubleBuffer outBuf; + + private final DoubleBuffer forwardBuf; + private final DoubleBuffer sideBuf; + private final DoubleBuffer upBuf; + + public ProjectDouble() { + // Use direct buffers to avoid loading indirect buffer + // implementations for applications trying to avoid doing so. + // Slice up one big buffer because some NIO implementations + // allocate a huge amount of memory to back even the smallest of + // buffers. + DoubleBuffer locbuf = InternalBufferUtil.newDoubleBuffer(128); + int pos = 0; + int sz = 16; + matrixBuf = slice(locbuf, pos, sz); + pos += sz; + tempMatrixBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 4; + inBuf = slice(locbuf, pos, sz); + pos += sz; + outBuf = slice(locbuf, pos, sz); + pos += sz; + sz = 3; + forwardBuf = slice(locbuf, pos, sz); + pos += sz; + sideBuf = slice(locbuf, pos, sz); + pos += sz; + upBuf = slice(locbuf, pos, sz); + } + + public void destroy() { + if(locbuf!=null) { + locbuf.clear(); + locbuf=null; + } + } + + private static DoubleBuffer slice(DoubleBuffer buf, int pos, int len) { + buf.position(pos); + buf.limit(pos + len); + return buf.slice(); + } + + /** + * Make matrix an identity matrix + */ + private void __gluMakeIdentityd(DoubleBuffer m) { + int oldPos = m.position(); + m.put(IDENTITY_MATRIX); + m.position(oldPos); + } + + /** + * Make matrix an identity matrix + */ + private void __gluMakeIdentityd(double[] m) { + for (int i = 0; i < 16; i++) { + m[i] = IDENTITY_MATRIX[i]; + } + } + + /** + * Method __gluMultMatrixVecd + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecd(double[] matrix, int matrix_offset, double[] in, double[] out) { + for (int i = 0; i < 4; i++) { + out[i] = + in[0] * matrix[0*4+i+matrix_offset] + + in[1] * matrix[1*4+i+matrix_offset] + + in[2] * matrix[2*4+i+matrix_offset] + + in[3] * matrix[3*4+i+matrix_offset]; + } + } + + /** + * Method __gluMultMatrixVecd + * + * @param matrix + * @param in + * @param out + */ + private void __gluMultMatrixVecd(DoubleBuffer matrix, DoubleBuffer in, DoubleBuffer out) { + int inPos = in.position(); + int outPos = out.position(); + int matrixPos = matrix.position(); + for (int i = 0; i < 4; i++) { + out.put(i + outPos, + in.get(0+inPos) * matrix.get(0*4+i+matrixPos) + + in.get(1+inPos) * matrix.get(1*4+i+matrixPos) + + in.get(2+inPos) * matrix.get(2*4+i+matrixPos) + + in.get(3+inPos) * matrix.get(3*4+i+matrixPos)); + } + } + + /** + * @param src + * @param inverse + * + * @return + */ + private boolean __gluInvertMatrixd(double[] src, double[] inverse) { + int i, j, k, swap; + double t; + double[][] temp = tempMatrix; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp[i][j] = src[i*4+j]; + } + } + __gluMakeIdentityd(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp[j][i]) > Math.abs(temp[i][i])) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp[i][k]; + temp[i][k] = temp[swap][k]; + temp[swap][k] = t; + + t = inverse[i*4+k]; + inverse[i*4+k] = inverse[swap*4+k]; + inverse[swap*4+k] = t; + } + } + + if (temp[i][i] == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp[i][i]; + for (k = 0; k < 4; k++) { + temp[i][k] /= t; + inverse[i*4+k] /= t; + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp[j][i]; + for (k = 0; k < 4; k++) { + temp[j][k] -= temp[i][k] * t; + inverse[j*4+k] -= inverse[i*4+k]*t; + } + } + } + } + return true; + } + + /** + * @param src + * @param inverse + * + * @return + */ + private boolean __gluInvertMatrixd(DoubleBuffer src, DoubleBuffer inverse) { + int i, j, k, swap; + double t; + + int srcPos = src.position(); + int invPos = inverse.position(); + + DoubleBuffer temp = tempMatrixBuf; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + temp.put(i*4+j, src.get(i*4+j + srcPos)); + } + } + __gluMakeIdentityd(inverse); + + for (i = 0; i < 4; i++) { + // + // Look for largest element in column + // + swap = i; + for (j = i + 1; j < 4; j++) { + if (Math.abs(temp.get(j*4+i)) > Math.abs(temp.get(i*4+i))) { + swap = j; + } + } + + if (swap != i) { + // + // Swap rows. + // + for (k = 0; k < 4; k++) { + t = temp.get(i*4+k); + temp.put(i*4+k, temp.get(swap*4+k)); + temp.put(swap*4+k, t); + + t = inverse.get(i*4+k + invPos); + inverse.put(i*4+k + invPos, inverse.get(swap*4+k + invPos)); + inverse.put(swap*4+k + invPos, t); + } + } + + if (temp.get(i*4+i) == 0) { + // + // No non-zero pivot. The matrix is singular, which shouldn't + // happen. This means the user gave us a bad matrix. + // + return false; + } + + t = temp.get(i*4+i); + for (k = 0; k < 4; k++) { + temp.put(i*4+k, temp.get(i*4+k) / t); + inverse.put(i*4+k + invPos, inverse.get(i*4+k + invPos) / t); + } + for (j = 0; j < 4; j++) { + if (j != i) { + t = temp.get(j*4+i); + for (k = 0; k < 4; k++) { + temp.put(j*4+k, temp.get(j*4+k) - temp.get(i*4+k) * t); + inverse.put(j*4+k + invPos, inverse.get(j*4+k + invPos) - inverse.get(i*4+k + invPos) * t); + } + } + } + } + return true; + } + + + /** + * @param a + * @param b + * @param r + */ + private void __gluMultMatricesd(double[] a, int a_offset, double[] b, int b_offset, double[] r) { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r[i*4+j] = + a[i*4+0+a_offset]*b[0*4+j+b_offset] + + a[i*4+1+a_offset]*b[1*4+j+b_offset] + + a[i*4+2+a_offset]*b[2*4+j+b_offset] + + a[i*4+3+a_offset]*b[3*4+j+b_offset]; + } + } + } + + + /** + * @param a + * @param b + * @param r + */ + private void __gluMultMatricesd(DoubleBuffer a, DoubleBuffer b, DoubleBuffer r) { + int aPos = a.position(); + int bPos = b.position(); + int rPos = r.position(); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + r.put(i*4+j + rPos, + a.get(i*4+0+aPos)*b.get(0*4+j+bPos) + + a.get(i*4+1+aPos)*b.get(1*4+j+bPos) + + a.get(i*4+2+aPos)*b.get(2*4+j+bPos) + + a.get(i*4+3+aPos)*b.get(3*4+j+bPos)); + } + } + } + + /** + * Normalize vector + * + * @param v + */ + private static void normalize(double[] v) { + double r; + + r = Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if ( r == 0.0 ) + return; + + r = 1.0 / r; + + v[0] *= r; + v[1] *= r; + v[2] *= r; + + return; + } + + /** + * Normalize vector + * + * @param v + */ + private static void normalize(DoubleBuffer v) { + double r; + + int vPos = v.position(); + + r = Math.sqrt(v.get(0+vPos) * v.get(0+vPos) + + v.get(1+vPos) * v.get(1+vPos) + + v.get(2+vPos) * v.get(2+vPos)); + if ( r == 0.0 ) + return; + + r = 1.0 / r; + + v.put(0+vPos, v.get(0+vPos) * r); + v.put(1+vPos, v.get(1+vPos) * r); + v.put(2+vPos, v.get(2+vPos) * r); + + return; + } + + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(double[] v1, double[] v2, double[] result) { + result[0] = v1[1] * v2[2] - v1[2] * v2[1]; + result[1] = v1[2] * v2[0] - v1[0] * v2[2]; + result[2] = v1[0] * v2[1] - v1[1] * v2[0]; + } + + /** + * Calculate cross-product + * + * @param v1 + * @param v2 + * @param result + */ + private static void cross(DoubleBuffer v1, DoubleBuffer v2, DoubleBuffer result) { + int v1Pos = v1.position(); + int v2Pos = v2.position(); + int rPos = result.position(); + + result.put(0+rPos, v1.get(1+v1Pos) * v2.get(2+v2Pos) - v1.get(2+v1Pos) * v2.get(1+v2Pos)); + result.put(1+rPos, v1.get(2+v1Pos) * v2.get(0+v2Pos) - v1.get(0+v1Pos) * v2.get(2+v2Pos)); + result.put(2+rPos, v1.get(0+v1Pos) * v2.get(1+v2Pos) - v1.get(1+v1Pos) * v2.get(0+v2Pos)); + } + + /** + * Method gluOrtho2D. + * + * @param left + * @param right + * @param bottom + * @param top + */ + public void gluOrtho2D(GL2 gl, double left, double right, double bottom, double top) { + gl.glOrtho(left, right, bottom, top, -1, 1); + } + + /** + * Method gluPerspective. + * + * @param fovy + * @param aspect + * @param zNear + * @param zFar + */ + public void gluPerspective(GL2 gl, double fovy, double aspect, double zNear, double zFar) { + double sine, cotangent, deltaZ; + double radians = fovy / 2 * Math.PI / 180; + + deltaZ = zFar - zNear; + sine = Math.sin(radians); + + if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) { + return; + } + + cotangent = Math.cos(radians) / sine; + + __gluMakeIdentityd(matrixBuf); + + matrixBuf.put(0 * 4 + 0, cotangent / aspect); + matrixBuf.put(1 * 4 + 1, cotangent); + matrixBuf.put(2 * 4 + 2, - (zFar + zNear) / deltaZ); + matrixBuf.put(2 * 4 + 3, -1); + matrixBuf.put(3 * 4 + 2, -2 * zNear * zFar / deltaZ); + matrixBuf.put(3 * 4 + 3, 0); + + gl.glMultMatrixd(matrixBuf); + } + + /** + * Method gluLookAt + * + * @param eyex + * @param eyey + * @param eyez + * @param centerx + * @param centery + * @param centerz + * @param upx + * @param upy + * @param upz + */ + public void gluLookAt(GL2 gl, + double eyex, + double eyey, + double eyez, + double centerx, + double centery, + double centerz, + double upx, + double upy, + double upz) { + DoubleBuffer forward = this.forwardBuf; + DoubleBuffer side = this.sideBuf; + DoubleBuffer up = this.upBuf; + + forward.put(0, centerx - eyex); + forward.put(1, centery - eyey); + forward.put(2, centerz - eyez); + + up.put(0, upx); + up.put(1, upy); + up.put(2, upz); + + normalize(forward); + + /* Side = forward x up */ + cross(forward, up, side); + normalize(side); + + /* Recompute up as: up = side x forward */ + cross(side, forward, up); + + __gluMakeIdentityd(matrixBuf); + matrixBuf.put(0 * 4 + 0, side.get(0)); + matrixBuf.put(1 * 4 + 0, side.get(1)); + matrixBuf.put(2 * 4 + 0, side.get(2)); + + matrixBuf.put(0 * 4 + 1, up.get(0)); + matrixBuf.put(1 * 4 + 1, up.get(1)); + matrixBuf.put(2 * 4 + 1, up.get(2)); + + matrixBuf.put(0 * 4 + 2, -forward.get(0)); + matrixBuf.put(1 * 4 + 2, -forward.get(1)); + matrixBuf.put(2 * 4 + 2, -forward.get(2)); + + gl.glMultMatrixd(matrixBuf); + gl.glTranslated(-eyex, -eyey, -eyez); + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(double objx, + double objy, + double objz, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double[] win_pos, + int win_pos_offset ) { + + double[] in = this.in; + double[] out = this.out; + + in[0] = objx; + in[1] = objy; + in[2] = objz; + in[3] = 1.0; + + __gluMultMatrixVecd(modelMatrix, modelMatrix_offset, in, out); + __gluMultMatrixVecd(projMatrix, projMatrix_offset, out, in); + + if (in[3] == 0.0) + return false; + + in[3] = (1.0 / in[3]) * 0.5; + + // Map x, y and z to range 0-1 + in[0] = in[0] * in[3] + 0.5f; + in[1] = in[1] * in[3] + 0.5f; + in[2] = in[2] * in[3] + 0.5f; + + // Map x,y to viewport + win_pos[0+win_pos_offset] = in[0] * viewport[2+viewport_offset] + viewport[0+viewport_offset]; + win_pos[1+win_pos_offset] = in[1] * viewport[3+viewport_offset] + viewport[1+viewport_offset]; + win_pos[2+win_pos_offset] = in[2]; + + return true; + } + + /** + * Method gluProject + * + * @param objx + * @param objy + * @param objz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param win_pos + * + * @return + */ + public boolean gluProject(double objx, + double objy, + double objz, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + DoubleBuffer win_pos) { + + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + in.put(0, objx); + in.put(1, objy); + in.put(2, objz); + in.put(3, 1.0); + + __gluMultMatrixVecd(modelMatrix, in, out); + __gluMultMatrixVecd(projMatrix, out, in); + + if (in.get(3) == 0.0) + return false; + + in.put(3, (1.0 / in.get(3)) * 0.5); + + // Map x, y and z to range 0-1 + in.put(0, in.get(0) * in.get(3) + 0.5f); + in.put(1, in.get(1) * in.get(3) + 0.5f); + in.put(2, in.get(2) * in.get(3) + 0.5f); + + // Map x,y to viewport + int vPos = viewport.position(); + int wPos = win_pos.position(); + win_pos.put(0+wPos, in.get(0) * viewport.get(2+vPos) + viewport.get(0+vPos)); + win_pos.put(1+wPos, in.get(1) * viewport.get(3+vPos) + viewport.get(1+vPos)); + win_pos.put(2+wPos, in.get(2)); + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(double winx, + double winy, + double winz, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double[] obj_pos, + int obj_pos_offset) { + double[] in = this.in; + double[] out = this.out; + + __gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!__gluInvertMatrixd(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = 1.0; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecd(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + out[3] = 1.0 / out[3]; + + obj_pos[0+obj_pos_offset] = out[0] * out[3]; + obj_pos[1+obj_pos_offset] = out[1] * out[3]; + obj_pos[2+obj_pos_offset] = out[2] * out[3]; + + return true; + } + + + /** + * Method gluUnproject + * + * @param winx + * @param winy + * @param winz + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param obj_pos + * + * @return + */ + public boolean gluUnProject(double winx, + double winy, + double winz, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + DoubleBuffer obj_pos) { + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + __gluMultMatricesd(modelMatrix, projMatrix, matrixBuf); + + if (!__gluInvertMatrixd(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, 1.0); + + // Map x and y from window coordinates + int vPos = viewport.position(); + int oPos = obj_pos.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecd(matrixBuf, in, out); + + if (out.get(3) == 0.0) + return false; + + out.put(3, 1.0 / out.get(3)); + + obj_pos.put(0+oPos, out.get(0) * out.get(3)); + obj_pos.put(1+oPos, out.get(1) * out.get(3)); + obj_pos.put(2+oPos, out.get(2) * out.get(3)); + + return true; + } + + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(double winx, + double winy, + double winz, + double clipw, + double[] modelMatrix, + int modelMatrix_offset, + double[] projMatrix, + int projMatrix_offset, + int[] viewport, + int viewport_offset, + double near, + double far, + double[] obj_pos, + int obj_pos_offset ) { + double[] in = this.in; + double[] out = this.out; + + __gluMultMatricesd(modelMatrix, modelMatrix_offset, projMatrix, projMatrix_offset, matrix); + + if (!__gluInvertMatrixd(matrix, matrix)) + return false; + + in[0] = winx; + in[1] = winy; + in[2] = winz; + in[3] = clipw; + + // Map x and y from window coordinates + in[0] = (in[0] - viewport[0+viewport_offset]) / viewport[2+viewport_offset]; + in[1] = (in[1] - viewport[1+viewport_offset]) / viewport[3+viewport_offset]; + in[2] = (in[2] - near) / (far - near); + + // Map to range -1 to 1 + in[0] = in[0] * 2 - 1; + in[1] = in[1] * 2 - 1; + in[2] = in[2] * 2 - 1; + + __gluMultMatrixVecd(matrix, 0, in, out); + + if (out[3] == 0.0) + return false; + + obj_pos[0+obj_pos_offset] = out[0]; + obj_pos[1+obj_pos_offset] = out[1]; + obj_pos[2+obj_pos_offset] = out[2]; + obj_pos[3+obj_pos_offset] = out[3]; + return true; + } + + /** + * Method gluUnproject4 + * + * @param winx + * @param winy + * @param winz + * @param clipw + * @param modelMatrix + * @param projMatrix + * @param viewport + * @param near + * @param far + * @param obj_pos + * + * @return + */ + public boolean gluUnProject4(double winx, + double winy, + double winz, + double clipw, + DoubleBuffer modelMatrix, + DoubleBuffer projMatrix, + IntBuffer viewport, + double near, + double far, + DoubleBuffer obj_pos) { + DoubleBuffer in = this.inBuf; + DoubleBuffer out = this.outBuf; + + __gluMultMatricesd(modelMatrix, projMatrix, matrixBuf); + + if (!__gluInvertMatrixd(matrixBuf, matrixBuf)) + return false; + + in.put(0, winx); + in.put(1, winy); + in.put(2, winz); + in.put(3, clipw); + + // Map x and y from window coordinates + int vPos = viewport.position(); + in.put(0, (in.get(0) - viewport.get(0+vPos)) / viewport.get(2+vPos)); + in.put(1, (in.get(1) - viewport.get(1+vPos)) / viewport.get(3+vPos)); + in.put(2, (in.get(2) - near) / (far - near)); + + // Map to range -1 to 1 + in.put(0, in.get(0) * 2 - 1); + in.put(1, in.get(1) * 2 - 1); + in.put(2, in.get(2) * 2 - 1); + + __gluMultMatrixVecd(matrixBuf, in, out); + + if (out.get(3) == 0.0) + return false; + + int oPos = obj_pos.position(); + obj_pos.put(0+oPos, out.get(0)); + obj_pos.put(1+oPos, out.get(1)); + obj_pos.put(2+oPos, out.get(2)); + obj_pos.put(3+oPos, out.get(3)); + return true; + } + + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + */ + public void gluPickMatrix(GL2 gl, + double x, + double y, + double deltaX, + double deltaY, + IntBuffer viewport) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + int vPos = viewport.position(); + gl.glTranslated((viewport.get(2+vPos) - 2 * (x - viewport.get(0+vPos))) / deltaX, + (viewport.get(3+vPos) - 2 * (y - viewport.get(1+vPos))) / deltaY, + 0); + gl.glScaled(viewport.get(2) / deltaX, viewport.get(3) / deltaY, 1.0); + } + + /** + * Method gluPickMatrix + * + * @param x + * @param y + * @param deltaX + * @param deltaY + * @param viewport + * @param viewport_offset + */ + public void gluPickMatrix(GL2 gl, + double x, + double y, + double deltaX, + double deltaY, + int[] viewport, + int viewport_offset) { + if (deltaX <= 0 || deltaY <= 0) { + return; + } + + /* Translate and scale the picked region to the entire window */ + gl.glTranslated((viewport[2+viewport_offset] - 2 * (x - viewport[0+viewport_offset])) / deltaX, + (viewport[3+viewport_offset] - 2 * (y - viewport[1+viewport_offset])) / deltaY, + 0); + gl.glScaled(viewport[2+viewport_offset] / deltaX, viewport[3+viewport_offset] / deltaY, 1.0); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java new file mode 100644 index 000000000..a542dcf19 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/Util.java @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.impl.gl2; + +import com.jogamp.opengl.impl.*; + +import java.nio.IntBuffer; +import javax.media.opengl.*; + +/** + * Util.java + * <p/> + * <p/> + * Created 7-jan-2004 + * + * @author Erik Duijs + */ +class Util { + + /** + * temp int[] of one for getting an int from some GL functions + */ + private int[] scratch = new int[1]; + + /** + * Return ceiling of integer division + * + * @param a + * @param b + * + * @return int + */ + protected static int ceil(int a, int b) { + return (a % b == 0 ? a / b : a / b + 1); + } + + /** + * Method compPerPix. + * + * @param format + * + * @return int + */ + protected static int compPerPix(int format) { + /* Determine number of components per pixel */ + switch ( format ) { + case GL2.GL_COLOR_INDEX: + case GL2.GL_STENCIL_INDEX: + case GL2.GL_DEPTH_COMPONENT: + case GL2.GL_RED: + case GL2.GL_GREEN: + case GL2.GL_BLUE: + case GL2.GL_ALPHA: + case GL2.GL_LUMINANCE: + return 1; + case GL2.GL_LUMINANCE_ALPHA: + return 2; + case GL2.GL_RGB: + case GL2.GL_BGR: + return 3; + case GL2.GL_RGBA: + case GL2.GL_BGRA: + return 4; + default : + return -1; + } + } + + /** + * Method nearestPower. + * <p/> + * Compute the nearest power of 2 number. This algorithm is a little strange, but it works quite well. + * + * @param value + * + * @return int + */ + protected static int nearestPower(int value) { + int i; + + i = 1; + + /* Error! */ + if ( value == 0 ) + return -1; + + for ( ; ; ) { + if ( value == 1 ) { + return i; + } else if ( value == 3 ) { + return i << 2; + } + value >>= 1; + i <<= 1; + } + } + + /** + * Method bytesPerPixel. + * + * @param format + * @param type + * + * @return int + */ + protected static int bytesPerPixel(int format, int type) { + int n, m; + + switch ( format ) { + case GL2.GL_COLOR_INDEX: + case GL2.GL_STENCIL_INDEX: + case GL2.GL_DEPTH_COMPONENT: + case GL2.GL_RED: + case GL2.GL_GREEN: + case GL2.GL_BLUE: + case GL2.GL_ALPHA: + case GL2.GL_LUMINANCE: + n = 1; + break; + case GL2.GL_LUMINANCE_ALPHA: + n = 2; + break; + case GL2.GL_RGB: + case GL2.GL_BGR: + n = 3; + break; + case GL2.GL_RGBA: + case GL2.GL_BGRA: + n = 4; + break; + default : + n = 0; + } + + switch ( type ) { + case GL2.GL_UNSIGNED_BYTE: + m = 1; + break; + case GL2.GL_BYTE: + m = 1; + break; + case GL2.GL_BITMAP: + m = 1; + break; + case GL2.GL_UNSIGNED_SHORT: + m = 2; + break; + case GL2.GL_SHORT: + m = 2; + break; + case GL2.GL_UNSIGNED_INT: + m = 4; + break; + case GL2.GL_INT: + m = 4; + break; + case GL2.GL_FLOAT: + m = 4; + break; + default : + m = 0; + } + + return n * m; + } + + /** + * Convenience method for returning an int, rather than getting it out of a buffer yourself. + * + * @param what + * + * @return int + */ + protected int glGetIntegerv(GL gl, int what) { + gl.glGetIntegerv(what, scratch, 0); + return scratch[0]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java b/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java new file mode 100755 index 000000000..3e3b6ae87 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/gl2/fixme/GLObjectTracker.java @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.gl2; + +import com.jogamp.opengl.impl.*; + +import java.nio.*; +import javax.media.opengl.*; + +/** + * Tracks the creation of server-side OpenGL objects which can be + * shared between contexts. Ordinarily, when an OpenGL context is + * deleted and no other contexts are sharing server-side objects with + * it, all of the server-side objects are automatically deleted by the + * OpenGL implementation. It is not necessary for the end user to + * explicitly delete these objects. However, when the Java2D/OpenGL + * pipeline is active and frame buffer objects are being used for + * rendering, it is necessary for all OpenGL contexts created by JOGL + * to share server-side objects with the Java2D OpenGL context. This + * means that these objects "leak" into the namespace used by Java2D. + * In order to prevent memory leaks and to present the same + * programming model to the end user, it is necessary to track the + * creation and destruction of all of these server-side OpenGL objects + * and to explicitly release them when all of the JOGL-created + * contexts which can see them have been released. <P> + * + * The {@link #ref ref} and {@link #unref unref} methods should be + * used during the creation and destruction of OpenGL contexts by JOGL + * in order to update the liveness of the objects being tracked. The + * various other methods should be called by the OpenGL binding in the + * various named methods. + */ + +public class GLObjectTracker { + private static final boolean DEBUG = Debug.debug("GLObjectTracker"); + + //---------------------------------------------------------------------- + // Adders + // + + // glGenBuffers + public synchronized void addBuffers(int n, IntBuffer ids) { + add(getList(BUFFERS), n, ids); + } + + // glGenBuffers + public synchronized void addBuffers(int n, int[] ids, int ids_offset) { + add(getList(BUFFERS), n, ids, ids_offset); + } + + // glGenBuffersARB + public synchronized void addBuffersARB(int n, IntBuffer ids) { + add(getList(BUFFERS_ARB), n, ids); + } + + // glGenBuffersARB + public synchronized void addBuffersARB(int n, int[] ids, int ids_offset) { + add(getList(BUFFERS_ARB), n, ids, ids_offset); + } + + // glGenFencesAPPLE + public synchronized void addFencesAPPLE(int n, IntBuffer ids) { + add(getList(FENCES_APPLE), n, ids); + } + + // glGenFencesAPPLE + public synchronized void addFencesAPPLE(int n, int[] ids, int ids_offset) { + add(getList(FENCES_APPLE), n, ids, ids_offset); + } + + // glGenFencesNV + public synchronized void addFencesNV(int n, IntBuffer ids) { + add(getList(FENCES_NV), n, ids); + } + + // glGenFencesNV + public synchronized void addFencesNV(int n, int[] ids, int ids_offset) { + add(getList(FENCES_NV), n, ids, ids_offset); + } + + // glGenFragmentShadersATI + public synchronized void addFragmentShadersATI(int start, int n) { + add(getList(FRAGMENT_SHADERS_ATI), start, n); + } + + // glGenFramebuffersEXT + public synchronized void addFramebuffersEXT(int n, IntBuffer ids) { + add(getList(FRAMEBUFFERS_EXT), n, ids); + } + + // glGenFramebuffersEXT + public synchronized void addFramebuffersEXT(int n, int[] ids, int ids_offset) { + add(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset); + } + + // glGenLists + public synchronized void addLists(int start, int n) { + add(getList(LISTS), start, n); + } + + // glGenOcclusionQueriesNV + public synchronized void addOcclusionQueriesNV(int n, IntBuffer ids) { + add(getList(OCCLUSION_QUERIES_NV), n, ids); + } + + // glGenOcclusionQueriesNV + public synchronized void addOcclusionQueriesNV(int n, int[] ids, int ids_offset) { + add(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset); + } + + // glCreateProgram + public synchronized void addProgramObject(int obj) { + add(getList(PROGRAM_OBJECTS), obj, 1); + } + + // glCreateProgramObjectARB + public synchronized void addProgramObjectARB(int obj) { + add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glGenProgramsARB + public synchronized void addProgramsARB(int n, IntBuffer ids) { + add(getList(PROGRAMS_ARB), n, ids); + } + + // glGenProgramsARB + public synchronized void addProgramsARB(int n, int[] ids, int ids_offset) { + add(getList(PROGRAMS_ARB), n, ids, ids_offset); + } + + // glGenProgramsNV + public synchronized void addProgramsNV(int n, IntBuffer ids) { + add(getList(PROGRAMS_NV), n, ids); + } + + // glGenProgramsNV + public synchronized void addProgramsNV(int n, int[] ids, int ids_offset) { + add(getList(PROGRAMS_NV), n, ids, ids_offset); + } + + // glGenQueries + public synchronized void addQueries(int n, IntBuffer ids) { + add(getList(QUERIES), n, ids); + } + + // glGenQueries + public synchronized void addQueries(int n, int[] ids, int ids_offset) { + add(getList(QUERIES), n, ids, ids_offset); + } + + // glGenQueriesARB + public synchronized void addQueriesARB(int n, IntBuffer ids) { + add(getList(QUERIES_ARB), n, ids); + } + + // glGenQueriesARB + public synchronized void addQueriesARB(int n, int[] ids, int ids_offset) { + add(getList(QUERIES_ARB), n, ids, ids_offset); + } + + // glGenRenderbuffersEXT + public synchronized void addRenderbuffersEXT(int n, IntBuffer ids) { + add(getList(RENDERBUFFERS_EXT), n, ids); + } + + // glGenRenderbuffersEXT + public synchronized void addRenderbuffersEXT(int n, int[] ids, int ids_offset) { + add(getList(RENDERBUFFERS_EXT), n, ids, ids_offset); + } + + // glCreateShader + public synchronized void addShaderObject(int obj) { + add(getList(SHADER_OBJECTS), obj, 1); + } + + // glCreateShaderObjectARB + public synchronized void addShaderObjectARB(int obj) { + add(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glGenTextures + public synchronized void addTextures(int n, IntBuffer ids) { + add(getList(TEXTURES), n, ids); + } + + // glGenTextures + public synchronized void addTextures(int n, int[] ids, int ids_offset) { + add(getList(TEXTURES), n, ids, ids_offset); + } + + // glGenVertexArraysAPPLE + public synchronized void addVertexArraysAPPLE(int n, IntBuffer ids) { + add(getList(VERTEX_ARRAYS_APPLE), n, ids); + } + + // glGenVertexArraysAPPLE + public synchronized void addVertexArraysAPPLE(int n, int[] ids, int ids_offset) { + add(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset); + } + + // glGenVertexShadersEXT + public synchronized void addVertexShadersEXT(int start, int n) { + add(getList(VERTEX_SHADERS_EXT), start, n); + } + + //---------------------------------------------------------------------- + // Removers + // + + // glDeleteBuffers + public synchronized void removeBuffers(int n, IntBuffer ids) { + remove(getList(BUFFERS), n, ids); + } + + // glDeleteBuffers + public synchronized void removeBuffers(int n, int[] ids, int ids_offset) { + remove(getList(BUFFERS), n, ids, ids_offset); + } + + // glDeleteBuffersARB + public synchronized void removeBuffersARB(int n, IntBuffer ids) { + remove(getList(BUFFERS_ARB), n, ids); + } + + // glDeleteBuffersARB + public synchronized void removeBuffersARB(int n, int[] ids, int ids_offset) { + remove(getList(BUFFERS_ARB), n, ids, ids_offset); + } + + // glDeleteFencesAPPLE + public synchronized void removeFencesAPPLE(int n, IntBuffer ids) { + remove(getList(FENCES_APPLE), n, ids); + } + + // glDeleteFencesAPPLE + public synchronized void removeFencesAPPLE(int n, int[] ids, int ids_offset) { + remove(getList(FENCES_APPLE), n, ids, ids_offset); + } + + // glDeleteFencesNV + public synchronized void removeFencesNV(int n, IntBuffer ids) { + remove(getList(FENCES_NV), n, ids); + } + + // glDeleteFencesNV + public synchronized void removeFencesNV(int n, int[] ids, int ids_offset) { + remove(getList(FENCES_NV), n, ids, ids_offset); + } + + // glDeleteFragmentShaderATI + public synchronized void removeFragmentShaderATI(int obj) { + remove(getList(FRAGMENT_SHADERS_ATI), obj, 1); + } + + // glDeleteFramebuffersEXT + public synchronized void removeFramebuffersEXT(int n, IntBuffer ids) { + remove(getList(FRAMEBUFFERS_EXT), n, ids); + } + + // glDeleteFramebuffersEXT + public synchronized void removeFramebuffersEXT(int n, int[] ids, int ids_offset) { + remove(getList(FRAMEBUFFERS_EXT), n, ids, ids_offset); + } + + // glDeleteLists + public synchronized void removeLists(int start, int n) { + remove(getList(LISTS), start, n); + } + + // glDeleteOcclusionQueriesNV + public synchronized void removeOcclusionQueriesNV(int n, IntBuffer ids) { + remove(getList(OCCLUSION_QUERIES_NV), n, ids); + } + + // glDeleteOcclusionQueriesNV + public synchronized void removeOcclusionQueriesNV(int n, int[] ids, int ids_offset) { + remove(getList(OCCLUSION_QUERIES_NV), n, ids, ids_offset); + } + + // glDeleteProgram + public synchronized void removeProgramObject(int obj) { + remove(getList(PROGRAM_OBJECTS), obj, 1); + } + + // glDeleteObjectARB + public synchronized void removeProgramOrShaderObjectARB(int obj) { + remove(getList(PROGRAM_AND_SHADER_OBJECTS_ARB), obj, 1); + } + + // glDeleteProgramsARB + public synchronized void removeProgramsARB(int n, IntBuffer ids) { + remove(getList(PROGRAMS_ARB), n, ids); + } + + // glDeleteProgramsARB + public synchronized void removeProgramsARB(int n, int[] ids, int ids_offset) { + remove(getList(PROGRAMS_ARB), n, ids, ids_offset); + } + + // glDeleteProgramsNV + public synchronized void removeProgramsNV(int n, IntBuffer ids) { + remove(getList(PROGRAMS_NV), n, ids); + } + + // glDeleteProgramsNV + public synchronized void removeProgramsNV(int n, int[] ids, int ids_offset) { + remove(getList(PROGRAMS_NV), n, ids, ids_offset); + } + + // glDeleteQueries + public synchronized void removeQueries(int n, IntBuffer ids) { + remove(getList(QUERIES), n, ids); + } + + // glDeleteQueries + public synchronized void removeQueries(int n, int[] ids, int ids_offset) { + remove(getList(QUERIES), n, ids, ids_offset); + } + + // glDeleteQueriesARB + public synchronized void removeQueriesARB(int n, IntBuffer ids) { + remove(getList(QUERIES_ARB), n, ids); + } + + // glDeleteQueriesARB + public synchronized void removeQueriesARB(int n, int[] ids, int ids_offset) { + remove(getList(QUERIES_ARB), n, ids, ids_offset); + } + + // glDeleteRenderbuffersEXT + public synchronized void removeRenderbuffersEXT(int n, IntBuffer ids) { + remove(getList(RENDERBUFFERS_EXT), n, ids); + } + + // glDeleteRenderbuffersEXT + public synchronized void removeRenderbuffersEXT(int n, int[] ids, int ids_offset) { + remove(getList(RENDERBUFFERS_EXT), n, ids, ids_offset); + } + + // glDeleteShader + public synchronized void removeShaderObject(int obj) { + remove(getList(SHADER_OBJECTS), obj, 1); + } + + // glDeleteTextures + public synchronized void removeTextures(int n, IntBuffer ids) { + remove(getList(TEXTURES), n, ids); + } + + // glDeleteTextures + public synchronized void removeTextures(int n, int[] ids, int ids_offset) { + remove(getList(TEXTURES), n, ids, ids_offset); + } + + // glDeleteVertexArraysAPPLE + public synchronized void removeVertexArraysAPPLE(int n, IntBuffer ids) { + remove(getList(VERTEX_ARRAYS_APPLE), n, ids); + } + + // glDeleteVertexArraysAPPLE + public synchronized void removeVertexArraysAPPLE(int n, int[] ids, int ids_offset) { + remove(getList(VERTEX_ARRAYS_APPLE), n, ids, ids_offset); + } + + // glDeleteVertexShaderEXT + public synchronized void removeVertexShaderEXT(int obj) { + remove(getList(VERTEX_SHADERS_EXT), obj, 1); + } + + //---------------------------------------------------------------------- + // Reference count maintenance and manual deletion + // + + public synchronized void transferAll(GLObjectTracker other) { + for (int i = 0; i < lists.length; i++) { + getList(i).addAll(other.lists[i]); + if (other.lists[i] != null) { + other.lists[i].clear(); + } + } + dirty = true; + } + + public synchronized void ref() { + ++refCount; + } + + public void unref(GLObjectTracker deletedObjectPool) { + boolean tryDelete = false; + synchronized (this) { + if (--refCount == 0) { + tryDelete = true; + } + } + if (tryDelete) { + // See whether we should try to do the work now or whether we + // have to postpone + GLContext cur = GLContext.getCurrent(); + if ((cur != null) && + (cur instanceof GLContextImpl)) { + GLContextImpl curImpl = (GLContextImpl) cur; + if (deletedObjectPool != null && + deletedObjectPool == curImpl.getDeletedObjectTracker()) { + // Should be safe to delete these objects now + try { + delete((GL2)curImpl.getGL()); + return; + } catch (GLException e) { + // Shouldn't happen, but if it does, transfer all objects + // to the deleted object pool hoping we can later clean + // them up + deletedObjectPool.transferAll(this); + throw(e); + } + } + } + // If we get here, we couldn't attempt to delete the objects + // right now; instead try to transfer them to the + // deletedObjectPool for later cleanup (FIXME: should consider + // throwing an exception if deletedObjectPool is null, since + // that shouldn't happen) + if (DEBUG) { + String s = null; + if (cur == null) { + s = "current context was null"; + } else if (!(cur instanceof GLContextImpl)) { + s = "current context was not a GLContextImpl"; + } else if (deletedObjectPool == null) { + s = "no current deletedObjectPool"; + } else if (deletedObjectPool != ((GLContextImpl) cur).getDeletedObjectTracker()) { + s = "deletedObjectTracker didn't match"; + if (((GLContextImpl) cur).getDeletedObjectTracker() == null) { + s += " (other was null)"; + } + } else { + s = "unknown reason"; + } + System.err.println("Deferred destruction of server-side OpenGL objects into " + deletedObjectPool + ": " + s); + } + + if (deletedObjectPool != null) { + deletedObjectPool.transferAll(this); + } + } + } + + public void clean(GL2 gl) { + if (dirty) { + try { + delete(gl); + dirty = false; + } catch (GLException e) { + // FIXME: not sure what to do here; probably a bad idea to be + // throwing exceptions during an otherwise-successful makeCurrent + } + } + } + + + //---------------------------------------------------------------------- + // Internals only below this point + // + + // Kinds of sharable server-side OpenGL objects this class tracks + private static final int BUFFERS = 0; + private static final int BUFFERS_ARB = 1; + private static final int FENCES_APPLE = 2; + private static final int FENCES_NV = 3; + private static final int FRAGMENT_SHADERS_ATI = 4; + private static final int FRAMEBUFFERS_EXT = 5; + private static final int LISTS = 6; + private static final int OCCLUSION_QUERIES_NV = 7; + private static final int PROGRAM_AND_SHADER_OBJECTS_ARB = 8; + private static final int PROGRAM_OBJECTS = 9; + private static final int PROGRAMS_ARB = 10; + private static final int PROGRAMS_NV = 11; + private static final int QUERIES = 12; + private static final int QUERIES_ARB = 13; + private static final int RENDERBUFFERS_EXT = 14; + private static final int SHADER_OBJECTS = 15; + private static final int TEXTURES = 16; + private static final int VERTEX_ARRAYS_APPLE = 17; + private static final int VERTEX_SHADERS_EXT = 18; + private static final int NUM_OBJECT_TYPES = 19; + + static abstract class Deleter { + public abstract void delete(GL2 gl, int obj); + } + + static class ObjectList { + private static final int MIN_CAPACITY = 4; + + private int size; + private int capacity; + private int[] data; + private Deleter deleter; + private String name; + + public ObjectList(Deleter deleter) { + this.deleter = deleter; + clear(); + } + + public void add(int obj) { + if (size == capacity) { + int newCapacity = 2 * capacity; + int[] newData = new int[newCapacity]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + capacity = newCapacity; + } + + data[size++] = obj; + } + + public void addAll(ObjectList other) { + if (other == null) { + return; + } + for (int i = 0; i < other.size; i++) { + add(other.data[i]); + } + } + + public boolean remove(int value) { + for (int i = 0; i < size; i++) { + if (data[i] == value) { + if (i < size - 1) { + System.arraycopy(data, i+1, data, i, size - i - 1); + } + --size; + if ((size < capacity / 4) && + (capacity > MIN_CAPACITY)) { + int newCapacity = capacity / 4; + if (newCapacity < MIN_CAPACITY) { + newCapacity = MIN_CAPACITY; + } + int[] newData = new int[newCapacity]; + System.arraycopy(data, 0, newData, 0, size); + data = newData; + capacity = newCapacity; + } + return true; + } + } + return false; + } + + public void setName(String name) { + if (DEBUG) { + this.name = name; + } + } + + public void delete(GL2 gl) { + // Just in case we start throwing exceptions during deletion, + // make sure we make progress rather than going into an infinite + // loop + while (size > 0) { + int obj = data[size - 1]; + --size; + if (DEBUG) { + System.err.println("Deleting server-side OpenGL object " + obj + + ((name != null) ? (" (" + name + ")") : "")); + } + deleter.delete(gl, obj); + } + } + + public void clear() { + size = 0; + capacity = MIN_CAPACITY; + data = new int[capacity]; + } + } + + private ObjectList[] lists = new ObjectList[NUM_OBJECT_TYPES]; + private int refCount; + private boolean dirty; + + private void add(ObjectList list, int n, IntBuffer ids) { + int pos = ids.position(); + for (int i = 0; i < n; i++) { + list.add(ids.get(pos + i)); + } + } + + private void add(ObjectList list, int n, int[] ids, int ids_offset) { + for (int i = 0; i < n; i++) { + list.add(ids[i + ids_offset]); + } + } + + private void add(ObjectList list, int start, int n) { + for (int i = 0; i < n; i++) { + list.add(start + i); + } + } + + private void remove(ObjectList list, int n, IntBuffer ids) { + int pos = ids.position(); + for (int i = 0; i < n; i++) { + list.remove(ids.get(pos + i)); + } + } + + private void remove(ObjectList list, int n, int[] ids, int ids_offset) { + for (int i = 0; i < n; i++) { + list.remove(ids[i + ids_offset]); + } + } + + private void remove(ObjectList list, int start, int n) { + for (int i = 0; i < n; i++) { + list.remove(start + i); + } + } + + private ObjectList getList(int which) { + ObjectList list = lists[which]; + if (list == null) { + Deleter deleter = null; + String name = null; + // Figure out which deleter we need + switch (which) { + case BUFFERS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteBuffers(1, new int[] { obj }, 0); + } + }; + name = "buffer"; + break; + case BUFFERS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteBuffersARB(1, new int[] { obj }, 0); + } + }; + name = "ARB buffer"; + break; + case FENCES_APPLE: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFencesAPPLE(1, new int[] { obj }, 0); + } + }; + name = "APPLE fence"; + break; + case FENCES_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFencesNV(1, new int[] { obj }, 0); + } + }; + name = "NV fence"; + break; + case FRAGMENT_SHADERS_ATI: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFragmentShaderATI(obj); + } + }; + name = "ATI fragment shader"; + break; + case FRAMEBUFFERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteFramebuffersEXT(1, new int[] { obj }, 0); + } + }; + name = "EXT framebuffer"; + break; + case LISTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteLists(obj, 1); + } + }; + name = "display list"; + break; + case OCCLUSION_QUERIES_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteOcclusionQueriesNV(1, new int[] { obj }, 0); + } + }; + name = "NV occlusion query"; + break; + case PROGRAM_AND_SHADER_OBJECTS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteObjectARB(obj); + } + }; + name = "ARB program or shader object"; + break; + case PROGRAM_OBJECTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgram(obj); + } + }; + name = "program object"; + break; + case PROGRAMS_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgramsARB(1, new int[] { obj }, 0); + } + }; + name = "ARB program object"; + break; + case PROGRAMS_NV: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteProgramsNV(1, new int[] { obj }, 0); + } + }; + name = "NV program"; + break; + case QUERIES: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteQueries(1, new int[] { obj }, 0); + } + }; + name = "query"; + break; + case QUERIES_ARB: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteQueriesARB(1, new int[] { obj }, 0); + } + }; + name = "ARB query"; + break; + case RENDERBUFFERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteRenderbuffersEXT(1, new int[] { obj }, 0); + } + }; + name = "EXT renderbuffer"; + break; + case SHADER_OBJECTS: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteShader(obj); + } + }; + name = "shader object"; + break; + case TEXTURES: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteTextures(1, new int[] { obj }, 0); + } + }; + name = "texture"; + break; + case VERTEX_ARRAYS_APPLE: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteVertexArraysAPPLE(1, new int[] { obj }, 0); + } + }; + name = "APPLE vertex array"; + break; + case VERTEX_SHADERS_EXT: + deleter = new Deleter() { + public void delete(GL2 gl, int obj) { + gl.glDeleteVertexShaderEXT(obj); + } + }; + name = "EXT vertex shader"; + break; + default: + throw new InternalError("Unexpected OpenGL object type " + which); + } + + list = new ObjectList(deleter); + list.setName(name); + lists[which] = list; + } + return list; + } + + private void delete(GL2 gl) { + for (int i = 0; i < lists.length; i++) { + ObjectList list = lists[i]; + if (list != null) { + list.delete(gl); + lists[i] = null; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java new file mode 100644 index 000000000..d7e6a23c1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/GLUquadricImpl.java @@ -0,0 +1,1212 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** $Date: 2009-03-04 17:23:34 -0800 (Wed, 04 Mar 2009) $ $Revision: 1856 $ +** $Header$ +*/ + +/* + * Copyright (c) 2002-2004 LWJGL Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'LWJGL' nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ + +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.impl.glu; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.jogamp.opengl.util.ImmModeSink; +import java.nio.*; + +/** + * GLUquadricImpl.java + * + * + * Created 22-dec-2003 (originally Quadric.java) + * @author Erik Duijs + * @author Kenneth Russell, Sven Gothel + */ + +public class GLUquadricImpl implements GLUquadric { + private boolean useGLSL; + private int drawStyle; + private int orientation; + private boolean textureFlag; + private int normals; + private boolean immModeSinkEnabled; + private boolean immModeSinkImmediate; + public int normalType; + public GL gl; + + public static final boolean USE_NORM = true; + public static final boolean USE_TEXT = false; + + private ImmModeSink immModeSink=null; + + public GLUquadricImpl(GL gl, boolean useGLSL) { + this.gl=gl; + this.useGLSL = useGLSL; + drawStyle = GLU.GLU_FILL; + orientation = GLU.GLU_OUTSIDE; + textureFlag = false; + normals = GLU.GLU_SMOOTH; + normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; + immModeSinkImmediate=true; + immModeSinkEnabled=!gl.isGL2(); + replaceImmModeSink(); + } + + public void enableImmModeSink(boolean val) { + if(gl.isGL2()) { + immModeSinkEnabled=val; + } else { + immModeSinkEnabled=true; + } + if(null==immModeSink && immModeSinkEnabled) { + replaceImmModeSink(); + } + } + + public boolean isImmModeSinkEnabled() { + return immModeSinkEnabled; + } + + public void setImmMode(boolean val) { + if(immModeSinkEnabled) { + immModeSinkImmediate=val; + } else { + immModeSinkImmediate=true; + } + } + + public boolean getImmMode() { + return immModeSinkImmediate; + } + + public ImmModeSink replaceImmModeSink() { + if(!immModeSinkEnabled) return null; + + ImmModeSink res = immModeSink; + if(useGLSL) { + immModeSink = ImmModeSink.createGLSL (gl, GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType,// normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture + } else { + immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType,// normal + USE_TEXT?2:0, GL.GL_FLOAT); // texture + } + return res; + } + + public void resetImmModeSink(GL gl) { + if(immModeSinkEnabled) { + immModeSink.reset(gl); + } + } + + /** + * specifies the draw style for quadrics. + * + * The legal values are as follows: + * + * GLU.FILL: Quadrics are rendered with polygon primitives. The polygons + * are drawn in a counterclockwise fashion with respect to + * their normals (as defined with glu.quadricOrientation). + * + * GLU.LINE: Quadrics are rendered as a set of lines. + * + * GLU.SILHOUETTE: Quadrics are rendered as a set of lines, except that edges + * separating coplanar faces will not be drawn. + * + * GLU.POINT: Quadrics are rendered as a set of points. + * + * @param drawStyle The drawStyle to set + */ + public void setDrawStyle(int drawStyle) { + this.drawStyle = drawStyle; + } + + /** + * specifies what kind of normals are desired for quadrics. + * The legal values are as follows: + * + * GLU.NONE: No normals are generated. + * + * GLU.FLAT: One normal is generated for every facet of a quadric. + * + * GLU.SMOOTH: One normal is generated for every vertex of a quadric. This + * is the default. + * + * @param normals The normals to set + */ + public void setNormals(int normals) { + this.normals = normals; + } + + /** + * specifies what kind of orientation is desired for. + * The orientation values are as follows: + * + * GLU.OUTSIDE: Quadrics are drawn with normals pointing outward. + * + * GLU.INSIDE: Normals point inward. The default is GLU.OUTSIDE. + * + * Note that the interpretation of outward and inward depends on the quadric + * being drawn. + * + * @param orientation The orientation to set + */ + public void setOrientation(int orientation) { + this.orientation = orientation; + } + + /** + * specifies if texture coordinates should be generated for + * quadrics rendered with qobj. If the value of textureCoords is true, + * then texture coordinates are generated, and if textureCoords is false, + * they are not.. The default is false. + * + * The manner in which texture coordinates are generated depends upon the + * specific quadric rendered. + * + * @param textureFlag The textureFlag to set + */ + public void setTextureFlag(boolean textureFlag) { + this.textureFlag = textureFlag; + } + + /** + * Returns the drawStyle. + * @return int + */ + public int getDrawStyle() { + return drawStyle; + } + + /** + * Returns the normals. + * @return int + */ + public int getNormals() { + return normals; + } + + /** + * Returns the orientation. + * @return int + */ + public int getOrientation() { + return orientation; + } + + /** + * Returns the textureFlag. + * @return boolean + */ + public boolean getTextureFlag() { + return textureFlag; + } + + + /** + * draws a cylinder oriented along the z axis. The base of the + * cylinder is placed at z = 0, and the top at z=height. Like a sphere, a + * cylinder is subdivided around the z axis into slices, and along the z axis + * into stacks. + * + * Note that if topRadius is set to zero, then this routine will generate a + * cone. + * + * If the orientation is set to GLU.OUTSIDE (with glu.quadricOrientation), then + * any generated normals point away from the z axis. Otherwise, they point + * toward the z axis. + * + * If texturing is turned on (with glu.quadricTexture), then texture + * coordinates are generated so that t ranges linearly from 0.0 at z = 0 to + * 1.0 at z = height, and s ranges from 0.0 at the +y axis, to 0.25 at the +x + * axis, to 0.5 at the -y axis, to 0.75 at the -x axis, and back to 1.0 at the + * +y axis. + * + * @param baseRadius Specifies the radius of the cylinder at z = 0. + * @param topRadius Specifies the radius of the cylinder at z = height. + * @param height Specifies the height of the cylinder. + * @param slices Specifies the number of subdivisions around the z axis. + * @param stacks Specifies the number of subdivisions along the z axis. + */ + public void drawCylinder(GL gl, float baseRadius, float topRadius, float height, int slices, int stacks) { + + float da, r, dr, dz; + float x, y, z, nz, nsign; + int i, j; + + if (orientation == GLU.GLU_INSIDE) { + nsign = -1.0f; + } else { + nsign = 1.0f; + } + + da = 2.0f * PI / slices; + dr = (topRadius - baseRadius) / stacks; + dz = height / stacks; + nz = (baseRadius - topRadius) / height; + // Z component of normal vectors + + if (drawStyle == GLU.GLU_POINT) { + glBegin(gl, GL.GL_POINTS); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + + z = 0.0f; + r = baseRadius; + for (j = 0; j <= stacks; j++) { + glVertex3f(gl, (x * r), (y * r), z); + z += dz; + r += dr; + } + } + glEnd(gl); + } else if (drawStyle == GLU.GLU_LINE || drawStyle == GLU.GLU_SILHOUETTE) { + // Draw rings + if (drawStyle == GLU.GLU_LINE) { + z = 0.0f; + r = baseRadius; + for (j = 0; j <= stacks; j++) { + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * r), (y * r), z); + } + glEnd(gl); + z += dz; + r += dr; + } + } else { + // draw one ring at each end + if (baseRadius != 0.0) { + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); + } + glEnd(gl); + glBegin(gl, GL.GL_LINE_LOOP); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * topRadius), (y * topRadius), height); + } + glEnd(gl); + } + } + // draw length lines + glBegin(gl, GL.GL_LINES); + for (i = 0; i < slices; i++) { + x = cos((i * da)); + y = sin((i * da)); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + glVertex3f(gl, (x * baseRadius), (y * baseRadius), 0.0f); + glVertex3f(gl, (x * topRadius), (y * topRadius), (height)); + } + glEnd(gl); + } else if (drawStyle == GLU.GLU_FILL) { + float ds = 1.0f / slices; + float dt = 1.0f / stacks; + float t = 0.0f; + z = 0.0f; + r = baseRadius; + for (j = 0; j < stacks; j++) { + float s = 0.0f; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (i = 0; i <= slices; i++) { + if (i == slices) { + x = sin(0.0f); + y = cos(0.0f); + } else { + x = sin((i * da)); + y = cos((i * da)); + } + if (nsign == 1.0f) { + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t); + glVertex3f(gl, (x * r), (y * r), z); + normal3f(gl, (x * nsign), (y * nsign), (nz * nsign)); + TXTR_COORD(gl, s, t + dt); + glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); + } else { + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t); + glVertex3f(gl, (x * r), (y * r), z); + normal3f(gl, x * nsign, y * nsign, nz * nsign); + TXTR_COORD(gl, s, t + dt); + glVertex3f(gl, (x * (r + dr)), (y * (r + dr)), (z + dz)); + } + s += ds; + } // for slices + glEnd(gl); + r += dr; + t += dt; + z += dz; + } // for stacks + } + } + + /** + * renders a disk on the z = 0 plane. The disk has a radius of + * outerRadius, and contains a concentric circular hole with a radius of + * innerRadius. If innerRadius is 0, then no hole is generated. The disk is + * subdivided around the z axis into slices (like pizza slices), and also + * about the z axis into rings (as specified by slices and loops, + * respectively). + * + * With respect to orientation, the +z side of the disk is considered to be + * "outside" (see glu.quadricOrientation). This means that if the orientation + * is set to GLU.OUTSIDE, then any normals generated point along the +z axis. + * Otherwise, they point along the -z axis. + * + * If texturing is turned on (with glu.quadricTexture), texture coordinates are + * generated linearly such that where r=outerRadius, the value at (r, 0, 0) is + * (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5), and at + * (0, -r, 0) it is (0.5, 0). + */ + public void drawDisk(GL gl, float innerRadius, float outerRadius, int slices, int loops) + { + float da, dr; + + /* Normal vectors */ + if (normals != GLU.GLU_NONE) { + if (orientation == GLU.GLU_OUTSIDE) { + glNormal3f(gl, 0.0f, 0.0f, +1.0f); + } + else { + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + } + } + + da = 2.0f * PI / slices; + dr = (outerRadius - innerRadius) / loops; + + switch (drawStyle) { + case GLU.GLU_FILL: + { + /* texture of a gluDisk is a cut out of the texture unit square + * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1] + * (linear mapping) + */ + float dtc = 2.0f * outerRadius; + float sa, ca; + float r1 = innerRadius; + int l; + for (l = 0; l < loops; l++) { + float r2 = r1 + dr; + if (orientation == GLU.GLU_OUTSIDE) { + int s; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (s = 0; s <= slices; s++) { + float a; + if (s == slices) + a = 0.0f; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(gl, 0.5f + sa * r2 / dtc, 0.5f + ca * r2 / dtc); + glVertex2f(gl, r2 * sa, r2 * ca); + TXTR_COORD(gl, 0.5f + sa * r1 / dtc, 0.5f + ca * r1 / dtc); + glVertex2f(gl, r1 * sa, r1 * ca); + } + glEnd(gl); + } + else { + int s; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (s = slices; s >= 0; s--) { + float a; + if (s == slices) + a = 0.0f; + else + a = s * da; + sa = sin(a); + ca = cos(a); + TXTR_COORD(gl, 0.5f - sa * r2 / dtc, 0.5f + ca * r2 / dtc); + glVertex2f(gl, r2 * sa, r2 * ca); + TXTR_COORD(gl, 0.5f - sa * r1 / dtc, 0.5f + ca * r1 / dtc); + glVertex2f(gl, r1 * sa, r1 * ca); + } + glEnd(gl); + } + r1 = r2; + } + break; + } + case GLU.GLU_LINE: + { + int l, s; + /* draw loops */ + for (l = 0; l <= loops; l++) { + float r = innerRadius + l * dr; + glBegin(gl, GL.GL_LINE_LOOP); + for (s = 0; s < slices; s++) { + float a = s * da; + glVertex2f(gl, r * sin(a), r * cos(a)); + } + glEnd(gl); + } + /* draw spokes */ + for (s = 0; s < slices; s++) { + float a = s * da; + float x = sin(a); + float y = cos(a); + glBegin(gl, GL.GL_LINE_STRIP); + for (l = 0; l <= loops; l++) { + float r = innerRadius + l * dr; + glVertex2f(gl, r * x, r * y); + } + glEnd(gl); + } + break; + } + case GLU.GLU_POINT: + { + int s; + glBegin(gl, GL.GL_POINTS); + for (s = 0; s < slices; s++) { + float a = s * da; + float x = sin(a); + float y = cos(a); + int l; + for (l = 0; l <= loops; l++) { + float r = innerRadius * l * dr; + glVertex2f(gl, r * x, r * y); + } + } + glEnd(gl); + break; + } + case GLU.GLU_SILHOUETTE: + { + if (innerRadius != 0.0) { + float a; + glBegin(gl, GL.GL_LINE_LOOP); + for (a = 0.0f; a < 2.0 * PI; a += da) { + float x = innerRadius * sin(a); + float y = innerRadius * cos(a); + glVertex2f(gl, x, y); + } + glEnd(gl); + } + { + float a; + glBegin(gl, GL.GL_LINE_LOOP); + for (a = 0; a < 2.0f * PI; a += da) { + float x = outerRadius * sin(a); + float y = outerRadius * cos(a); + glVertex2f(gl, x, y); + } + glEnd(gl); + } + break; + } + default: + return; + } + } + + /** + * renders a partial disk on the z=0 plane. A partial disk is similar to a + * full disk, except that only the subset of the disk from startAngle + * through startAngle + sweepAngle is included (where 0 degrees is along + * the +y axis, 90 degrees along the +x axis, 180 along the -y axis, and + * 270 along the -x axis). + * + * The partial disk has a radius of outerRadius, and contains a concentric + * circular hole with a radius of innerRadius. If innerRadius is zero, then + * no hole is generated. The partial disk is subdivided around the z axis + * into slices (like pizza slices), and also about the z axis into rings + * (as specified by slices and loops, respectively). + * + * With respect to orientation, the +z side of the partial disk is + * considered to be outside (see gluQuadricOrientation). This means that if + * the orientation is set to GLU.GLU_OUTSIDE, then any normals generated point + * along the +z axis. Otherwise, they point along the -z axis. + * + * If texturing is turned on (with gluQuadricTexture), texture coordinates + * are generated linearly such that where r=outerRadius, the value at (r, 0, 0) + * is (1, 0.5), at (0, r, 0) it is (0.5, 1), at (-r, 0, 0) it is (0, 0.5), + * and at (0, -r, 0) it is (0.5, 0). + */ + public void drawPartialDisk(GL gl, + float innerRadius, + float outerRadius, + int slices, + int loops, + float startAngle, + float sweepAngle) { + int i, j, max; + float[] sinCache = new float[CACHE_SIZE]; + float[] cosCache = new float[CACHE_SIZE]; + float angle; + float x, y; + float sintemp, costemp; + float deltaRadius; + float radiusLow, radiusHigh; + float texLow = 0, texHigh = 0; + float angleOffset; + int slices2; + int finish; + + if (slices >= CACHE_SIZE) + slices = CACHE_SIZE - 1; + if (slices < 2 + || loops < 1 + || outerRadius <= 0.0f + || innerRadius < 0.0f + || innerRadius > outerRadius) { + //gluQuadricError(qobj, GLU.GLU_INVALID_VALUE); + System.err.println("PartialDisk: GLU_INVALID_VALUE"); + return; + } + + if (sweepAngle < -360.0f) + sweepAngle = 360.0f; + if (sweepAngle > 360.0f) + sweepAngle = 360.0f; + if (sweepAngle < 0) { + startAngle += sweepAngle; + sweepAngle = -sweepAngle; + } + + if (sweepAngle == 360.0f) { + slices2 = slices; + } else { + slices2 = slices + 1; + } + + /* Compute length (needed for normal calculations) */ + deltaRadius = outerRadius - innerRadius; + + /* Cache is the vertex locations cache */ + + angleOffset = startAngle / 180.0f * PI; + for (i = 0; i <= slices; i++) { + angle = angleOffset + ((PI * sweepAngle) / 180.0f) * i / slices; + sinCache[i] = sin(angle); + cosCache[i] = cos(angle); + } + + if (sweepAngle == 360.0f) { + sinCache[slices] = sinCache[0]; + cosCache[slices] = cosCache[0]; + } + + switch (normals) { + case GLU.GLU_FLAT : + case GLU.GLU_SMOOTH : + if (orientation == GLU.GLU_OUTSIDE) { + glNormal3f(gl, 0.0f, 0.0f, 1.0f); + } else { + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + } + break; + default : + case GLU.GLU_NONE : + break; + } + + switch (drawStyle) { + case GLU.GLU_FILL : + if (innerRadius == .0f) { + finish = loops - 1; + /* Triangle strip for inner polygons */ + glBegin(gl, GL.GL_TRIANGLE_FAN); + if (textureFlag) { + glTexCoord2f(gl, 0.5f, 0.5f); + } + glVertex3f(gl, 0.0f, 0.0f, 0.0f); + radiusLow = outerRadius - deltaRadius * ((float) (loops - 1) / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + if (orientation == GLU.GLU_OUTSIDE) { + for (i = slices; i >= 0; i--) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } else { + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + glEnd(gl); + } else { + finish = loops; + } + for (j = 0; j < finish; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + radiusHigh = outerRadius - deltaRadius * ((float) (j + 1) / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + texHigh = radiusHigh / outerRadius / 2; + } + + glBegin(gl, immModeSink.GL_QUAD_STRIP); + for (i = 0; i <= slices; i++) { + if (orientation == GLU.GLU_OUTSIDE) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + + if (textureFlag) { + glTexCoord2f(gl, texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + } else { + if (textureFlag) { + glTexCoord2f(gl, texHigh * sinCache[i] + 0.5f, + texHigh * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusHigh * sinCache[i], + radiusHigh * cosCache[i], + 0.0f); + + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + } + glEnd(gl); + } + break; + case GLU.GLU_POINT : + glBegin(gl, GL.GL_POINTS); + for (i = 0; i < slices2; i++) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + } + glEnd(gl); + break; + case GLU.GLU_LINE : + if (innerRadius == outerRadius) { + glBegin(gl, GL.GL_LINE_STRIP); + + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, sinCache[i] / 2 + 0.5f, cosCache[i] / 2 + 0.5f); + } + glVertex3f(gl, innerRadius * sinCache[i], innerRadius * cosCache[i], 0.0f); + } + glEnd(gl); + break; + } + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + glEnd(gl); + } + for (i = 0; i < slices2; i++) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + glBegin(gl, GL.GL_LINE_STRIP); + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + glEnd(gl); + } + break; + case GLU.GLU_SILHOUETTE : + if (sweepAngle < 360.0f) { + for (i = 0; i <= slices; i += slices) { + sintemp = sinCache[i]; + costemp = cosCache[i]; + glBegin(gl, GL.GL_LINE_STRIP); + for (j = 0; j <= loops; j++) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sintemp, radiusLow * costemp, 0.0f); + } + glEnd(gl); + } + } + for (j = 0; j <= loops; j += loops) { + radiusLow = outerRadius - deltaRadius * ((float) j / loops); + if (textureFlag) { + texLow = radiusLow / outerRadius / 2; + } + + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= slices; i++) { + if (textureFlag) { + glTexCoord2f(gl, texLow * sinCache[i] + 0.5f, + texLow * cosCache[i] + 0.5f); + } + glVertex3f(gl, radiusLow * sinCache[i], radiusLow * cosCache[i], 0.0f); + } + glEnd(gl); + if (innerRadius == outerRadius) + break; + } + break; + default : + break; + } + } + + /** + * draws a sphere of the given radius centered around the origin. + * The sphere is subdivided around the z axis into slices and along the z axis + * into stacks (similar to lines of longitude and latitude). + * + * If the orientation is set to GLU.OUTSIDE (with glu.quadricOrientation), then + * any normals generated point away from the center of the sphere. Otherwise, + * they point toward the center of the sphere. + + * If texturing is turned on (with glu.quadricTexture), then texture + * coordinates are generated so that t ranges from 0.0 at z=-radius to 1.0 at + * z=radius (t increases linearly along longitudinal lines), and s ranges from + * 0.0 at the +y axis, to 0.25 at the +x axis, to 0.5 at the -y axis, to 0.75 + * at the -x axis, and back to 1.0 at the +y axis. + */ + public void drawSphere(GL gl, float radius, int slices, int stacks) { + // TODO + + float rho, drho, theta, dtheta; + float x, y, z; + float s, t, ds, dt; + int i, j, imin, imax; + boolean normals; + float nsign; + + normals = (this.normals != GLU.GLU_NONE); + + if (orientation == GLU.GLU_INSIDE) { + nsign = -1.0f; + } else { + nsign = 1.0f; + } + + drho = PI / stacks; + dtheta = 2.0f * PI / slices; + + if (drawStyle == GLU.GLU_FILL) { + if (!textureFlag) { + // draw +Z end as a triangle fan + glBegin(gl, GL.GL_TRIANGLE_FAN); + glNormal3f(gl, 0.0f, 0.0f, 1.0f); + glVertex3f(gl, 0.0f, 0.0f, nsign * radius); + for (j = 0; j <= slices; j++) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(drho); + y = cos(theta) * sin(drho); + z = nsign * cos(drho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + + ds = 1.0f / slices; + dt = 1.0f / stacks; + t = 1.0f; // because loop now runs from 0 + if (textureFlag) { + imin = 0; + imax = stacks; + } else { + imin = 1; + imax = stacks - 1; + } + + // draw intermediate stacks as quad strips + for (i = imin; i < imax; i++) { + rho = i * drho; + glBegin(gl, immModeSink.GL_QUAD_STRIP); + s = 0.0f; + for (j = 0; j <= slices; j++) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + TXTR_COORD(gl, s, t); + glVertex3f(gl, x * radius, y * radius, z * radius); + x = -sin(theta) * sin(rho + drho); + y = cos(theta) * sin(rho + drho); + z = nsign * cos(rho + drho); + if (normals) { + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + } + TXTR_COORD(gl, s, t - dt); + s += ds; + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + t -= dt; + } + + if (!textureFlag) { + // draw -Z end as a triangle fan + glBegin(gl, GL.GL_TRIANGLE_FAN); + glNormal3f(gl, 0.0f, 0.0f, -1.0f); + glVertex3f(gl, 0.0f, 0.0f, -radius * nsign); + rho = PI - drho; + s = 1.0f; + for (j = slices; j >= 0; j--) { + theta = (j == slices) ? 0.0f : j * dtheta; + x = -sin(theta) * sin(rho); + y = cos(theta) * sin(rho); + z = nsign * cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + s -= ds; + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + } else if ( + drawStyle == GLU.GLU_LINE + || drawStyle == GLU.GLU_SILHOUETTE) { + // draw stack lines + for (i = 1; + i < stacks; + i++) { // stack line at i==stacks-1 was missing here + rho = i * drho; + glBegin(gl, GL.GL_LINE_LOOP); + for (j = 0; j < slices; j++) { + theta = j * dtheta; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + // draw slice lines + for (j = 0; j < slices; j++) { + theta = j * dtheta; + glBegin(gl, GL.GL_LINE_STRIP); + for (i = 0; i <= stacks; i++) { + rho = i * drho; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + glEnd(gl); + } + } else if (drawStyle == GLU.GLU_POINT) { + // top and bottom-most points + glBegin(gl, GL.GL_POINTS); + if (normals) + glNormal3f(gl, 0.0f, 0.0f, nsign); + glVertex3f(gl, 0.0f, 0.0f, radius); + if (normals) + glNormal3f(gl, 0.0f, 0.0f, -nsign); + glVertex3f(gl, 0.0f, 0.0f, -radius); + + // loop over stacks + for (i = 1; i < stacks - 1; i++) { + rho = i * drho; + for (j = 0; j < slices; j++) { + theta = j * dtheta; + x = cos(theta) * sin(rho); + y = sin(theta) * sin(rho); + z = cos(rho); + if (normals) + glNormal3f(gl, x * nsign, y * nsign, z * nsign); + glVertex3f(gl, x * radius, y * radius, z * radius); + } + } + glEnd(gl); + } + } + + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static final float PI = (float)Math.PI; + private static final int CACHE_SIZE = 240; + + private final void glBegin(GL gl, int mode) { + if(immModeSinkEnabled) { + immModeSink.glBegin(mode); + } else { + gl.getGL2().glBegin(mode); + } + } + + private final void glEnd(GL gl) { + if(immModeSinkEnabled) { + immModeSink.glEnd(gl, immModeSinkImmediate); + } else { + gl.getGL2().glEnd(); + } + } + + private final void glVertex2f(GL gl, float x, float y) { + if(immModeSinkEnabled) { + immModeSink.glVertex2f(x, y); + } else { + gl.getGL2().glVertex2f(x, y); + } + } + + private final void glVertex3f(GL gl, float x, float y, float z) { + if(immModeSinkEnabled) { + immModeSink.glVertex3f(x, y, z); + } else { + gl.getGL2().glVertex3f(x, y, z); + } + } + + private final void glNormal3f_s(GL gl, float x, float y, float z) { + short a=(short)(x*0xFFFF); + short b=(short)(y*0xFFFF); + short c=(short)(z*0xFFFF); + if(immModeSinkEnabled) { + immModeSink.glNormal3s(a, b, c); + } else { + gl.getGL2().glNormal3s(a, b, c); + } + } + + private final void glNormal3f_b(GL gl, float x, float y, float z) { + byte a=(byte)(x*0xFF); + byte b=(byte)(y*0xFF); + byte c=(byte)(z*0xFF); + if(immModeSinkEnabled) { + immModeSink.glNormal3b(a, b, c); + } else { + gl.getGL2().glNormal3b(a, b, c); + } + } + + private final void glNormal3f(GL gl, float x, float y, float z) { + switch(normalType) { + case GL.GL_FLOAT: + if(immModeSinkEnabled) { + immModeSink.glNormal3f(x,y,z); + } else { + gl.getGL2().glNormal3f(x,y,z); + } + break; + case GL.GL_SHORT: + glNormal3f_s(gl, x, y, z); + break; + case GL.GL_BYTE: + glNormal3f_b(gl, x, y, z); + break; + } + } + + private final void glTexCoord2f(GL gl, float x, float y) { + if(immModeSinkEnabled) { + immModeSink.glTexCoord2f(x, y); + } else { + gl.getGL2().glTexCoord2f(x, y); + } + } + + /** + * Call glNormal3f after scaling normal to unit length. + * + * @param x + * @param y + * @param z + */ + private void normal3f(GL gl, float x, float y, float z) { + float mag; + + mag = (float)Math.sqrt(x * x + y * y + z * z); + if (mag > 0.00001F) { + x /= mag; + y /= mag; + z /= mag; + } + glNormal3f(gl, x, y, z); + } + + private final void TXTR_COORD(GL gl, float x, float y) { + if (textureFlag) glTexCoord2f(gl, x,y); + } + + private float sin(float r) { + return (float)Math.sin(r); + } + + private float cos(float r) { + return (float)Math.cos(r); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java new file mode 100755 index 000000000..7c360c574 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/Glue.java @@ -0,0 +1,114 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu; + +/** + * + * @author Administrator + */ +public class Glue { + private static String[] __gluNurbsErrors = { + " ", + "spline order un-supported", + "too few knots", + "valid knot range is empty", + "decreasing knot sequence knot", + "knot multiplicity greater than order of spline", + "gluEndCurve() must follow gluBeginCurve()", + "gluBeginCurve() must precede gluEndCurve()", + "missing or extra geometric data", + "can't draw piecewise linear trimming curves", + "missing or extra domain data", + "missing or extra domain data", + "gluEndTrim() must precede gluEndSurface()", + "gluBeginSurface() must precede gluEndSurface()", + "curve of improper type passed as trim curve", + "gluBeginSurface() must precede gluBeginTrim()", + "gluEndTrim() must follow gluBeginTrim()", + "gluBeginTrim() must follow gluEndTrim()", + "invalid or missing trim curve", + "gluBeginTrim() must precede gluPwlCurve()", + "piecewise linear trimming curve referenced twice", + "piecewise linear trimming curve and nurbs curve mixed", + "improper usage of trim data type", + "nurbs curve referenced twice", + "nurbs curve and piecewise linear trimming curve mixed", + "nurbs surface referenced twice", + "invalid property", + "gluEndSurface() must follow gluBeginSurface()", + "intersecting or misoriented trim curve", + "intersecting trim curves", + "UNUSED", + "inconnected trim curves", + "unknown knot error", + "negative vertex count encountered", + "negative byte-stride encountered", + "unknown type descriptor", + "null control point reference", + "duplicate point on piecewise linear trimming curve" + } ; + + /** Creates a new instance of Glue */ + public Glue() { + } + + public static String __gluNURBSErrorString( int errno ) { + return( __gluNurbsErrors[ errno ] ); + } + + private static String[] __gluTessErrors = { + " ", + "gluTessBeginPolygon() must precede a gluTessEndPolygon", + "gluTessBeginContour() must precede a gluTessEndContour()", + "gluTessEndPolygon() must follow a gluTessBeginPolygon()", + "gluTessEndContour() must follow a gluTessBeginContour()", + "a coordinate is too large", + "need combine callback" + }; + + public static String __gluTessErrorString( int errno ) { + return( __gluTessErrors[ errno ] ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java new file mode 100644 index 000000000..7c7e6b0d8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/error/Error.java @@ -0,0 +1,100 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.error; + +import javax.media.opengl.GL; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.impl.glu.Glue; + +/** + * + * @author Administrator + */ +public class Error { + + private static String[] glErrorStrings = { + "invalid enumerant", + "invalid value", + "invalid operation", + "stack overflow", + "stack underflow", + "out of memory", + "invalid framebuffer operation" + }; + + private static String[] gluErrorStrings = { + "invalid enumerant", + "invalid value", + "out of memory", + "", + "invalid operation" + }; + + /** Creates a new instance of Error */ + public Error() { + } + + public static String gluErrorString( int errorCode ) { + if( errorCode == 0 ) { + return( "no error" ); + } + if( (errorCode >= GL.GL_INVALID_ENUM) && (errorCode <= GL.GL_INVALID_FRAMEBUFFER_OPERATION) ) { + return( glErrorStrings[ errorCode - GL.GL_INVALID_ENUM ] ); + } + if( errorCode == 0x8031 /* GL.GL_TABLE_TOO_LARGE */ ) { + return( "table too large" ); + } + if( (errorCode >= GLU.GLU_INVALID_ENUM) && (errorCode <= GLU.GLU_INVALID_OPERATION) ) { + return( gluErrorStrings[ errorCode - GLU.GLU_INVALID_ENUM ] ); + } +// if( (errorCode >= GLU.GLU_NURBS_ERROR1) && (errorCode <= GLU.GLU_NURBS_ERROR37) ) { +// return( gluErrorStrings[ errorCode - (GLU.GLU_NURBS_ERROR1 - 1) ] ); +// } + if( (errorCode >= GLU.GLU_TESS_ERROR1) && (errorCode <= GLU.GLU_TESS_ERROR8) ) { + return( Glue.__gluTessErrorString(errorCode - (GLU.GLU_TESS_ERROR1 - 1)) ); + } + return( "error ("+errorCode+")" ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java new file mode 100755 index 000000000..42ddeea50 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2Backend.java @@ -0,0 +1,49 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class responsible for rendering + * @author Tomas Hrasky + * + */ +public class GL2Backend extends Backend { + public GL2Backend() { + super(); + curveEvaluator = new GL2CurveEvaluator(); + surfaceEvaluator = new GL2SurfaceEvaluator(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java new file mode 100755 index 000000000..adb8c51d8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2CurveEvaluator.java @@ -0,0 +1,205 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2.GLUgl2; + +/** + * Class rendering curves with OpenGL + * @author Tomáš Hráský + * + */ +class GL2CurveEvaluator implements CurveEvaluator { + + /** + * Output triangles (for callback) or render curve + */ + private boolean output_triangles; + + /** + * OpenGL object + */ + private GL2 gl; + + /** + * Not used + */ + private int vertex_flag; + + /** + * Not used + */ + private int normal_flag; + + /** + * Not used + */ + private int color_flag; + + /** + * Not used + */ + private int texcoord_flag; + + /** + * Number of bezier arc - used for color distinguishing of arcs forming NURBS curve + */ + private int poradi; + + /** + * Makes new Evaluator + */ + public GL2CurveEvaluator() { + gl = GLUgl2.getCurrentGL2(); + } + + /** + * Pushes eval bit + */ + public void bgnmap1f() { + // DONE + if (output_triangles) { + vertex_flag = 0; + normal_flag = 0; + color_flag = 0; + texcoord_flag = 0; + } else { + gl.glPushAttrib(GL2.GL_EVAL_BIT); + } + + } + + /** + * Pops all OpenGL attributes + */ + public void endmap1f() { + // DONE + if (output_triangles) { + + } else { + gl.glPopAttrib(); + } + + } + + /** + * Initializes opengl evaluator + * @param type curve type + * @param ulo lowest u + * @param uhi highest u + * @param stride control point coords + * @param order curve order + * @param ps control points + */ + public void map1f(int type, float ulo, float uhi, int stride, int order, + CArrayOfFloats ps) { + if (output_triangles) { + // TODO code for callback (output_triangles probably indicates callback) + // System.out.println("TODO curveevaluator.map1f-output_triangles"); + } else { + gl.glMap1f(type, ulo, uhi, stride, order, ps.getArray(), ps + .getPointer()); + + // DEBUG - drawing bézier control points + // gl.glColor3d(.5,.5,.5); + // gl.glPointSize(5); + // gl.glBegin(GL2.GL_POINTS); + // float[] ctrlpoints=ps.getArray(); + // for(int i=ps.getPointer();i<ps.getPointer()+order;i++){ + // gl.glVertex3d(ctrlpoints[i * 4], ctrlpoints[i * 4 + 1],0); + // } + // gl.glEnd(); + } + + } + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) { + // DONE + gl.glEnable(type); + } + + /** + * Calls glMapGrid1f + * @param nu steps + * @param u1 low u + * @param u2 high u + */ + public void mapgrid1f(int nu, float u1, float u2) { + if (output_triangles) { + // System.out.println("TODO curveevaluator.mapgrid1f"); + } else + gl.glMapGrid1f(nu, u1, u2); + // // System.out.println("upravit NU"); + // gl.glMapGrid1f(50,u1,u2); + } + + /** + * Evaluates a curve using glEvalMesh1f + * @param style Backend.N_MESHFILL/N_MESHLINE/N_MESHPOINT + * @param from lowest param + * @param to highest param + */ + public void mapmesh1f(int style, int from, int to) { + /* //DEBUG drawing control points + this.poradi++; + if (poradi % 2 == 0) + gl.glColor3f(1, 0, 0); + else + gl.glColor3f(0, 1, 0); + */ + if (output_triangles) { + // TODO code for callback + // System.out.println("TODO openglcurveevaluator.mapmesh1f output_triangles"); + } else { + switch (style) { + case Backend.N_MESHFILL: + case Backend.N_MESHLINE: + gl.glEvalMesh1(GL2.GL_LINE, from, to); + break; + case Backend.N_MESHPOINT: + gl.glEvalMesh1(GL2.GL_POINT, from, to); + break; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java new file mode 100755 index 000000000..393601ff7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GL2SurfaceEvaluator.java @@ -0,0 +1,217 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.glu.gl2.GLUgl2; + +/** + * Class rendering surfaces with OpenGL + * @author Tomas Hrasky + * + */ +class GL2SurfaceEvaluator implements SurfaceEvaluator { + + /** + * JOGL OpenGL object + */ + private GL2 gl; + + /** + * Output triangles (callback) + */ + private boolean output_triangles; + + /** + * Number of patch - used for distinguishing bezier plates forming NURBS surface with different colors + */ + private int poradi; + + /** + * Creates new evaluator + */ + public GL2SurfaceEvaluator() { + gl = GLUgl2.getCurrentGL2(); + } + + /** + * Pushes eval bit + */ + public void bgnmap2f() { + + if (output_triangles) { + // TODO outp triangles surfaceevaluator bgnmap2f + // System.out.println("TODO surfaceevaluator.bgnmap2f output triangles"); + } else { + gl.glPushAttrib(GL2.GL_EVAL_BIT); + // System.out.println("TODO surfaceevaluator.bgnmap2f glgetintegerv"); + } + + } + + /** + * Sets glPolygonMode + * @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT) + */ + public void polymode(int style) { + if (!output_triangles) { + switch (style) { + default: + case NurbsConsts.N_MESHFILL: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL); + break; + case NurbsConsts.N_MESHLINE: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); + break; + case NurbsConsts.N_MESHPOINT: + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_POINT); + break; + } + } + + } + + /** + * Pops all attributes + */ + public void endmap2f() { + // TODO Auto-generated method stub + if (output_triangles) { + // System.out.println("TODO surfaceevaluator.endmap2f output triangles"); + } else { + gl.glPopAttrib(); + // TODO use LOD + } + } + + /** + * Empty method + * @param ulo + * @param uhi + * @param vlo + * @param vhi + */ + public void domain2f(float ulo, float uhi, float vlo, float vhi) { + // DONE + } + + /** + * Defines 2D mesh + * @param nu number of steps in u direction + * @param u0 lowest u + * @param u1 highest u + * @param nv number of steps in v direction + * @param v0 lowest v + * @param v1 highest v + */ + public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) { + + if (output_triangles) { + // System.out.println("TODO openglsurfaceavaluator.mapgrid2f output_triangles"); + } else { + gl.glMapGrid2d(nu, u0, u1, nv, v0, v1); + } + + } + + /** + * Evaluates surface + * @param style surface style + * @param umin minimum U + * @param umax maximum U + * @param vmin minimum V + * @param vmax maximum V + */ + public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) { + if (output_triangles) { + // System.out.println("TODO openglsurfaceavaluator.mapmesh2f output_triangles"); + } else { + /* //DEBUG - draw control points + this.poradi++; + if (poradi % 2 == 0) + gl.glColor3f(1, 0, 0); + else if (poradi % 2 == 1) + gl.glColor3f(0, 1, 0); + */ + switch (style) { + case NurbsConsts.N_MESHFILL: + gl.glEvalMesh2(GL2.GL_FILL, umin, umax, vmin, vmax); + break; + case NurbsConsts.N_MESHLINE: + gl.glEvalMesh2(GL2.GL_LINE, umin, umax, vmin, vmax); + break; + case NurbsConsts.N_MESHPOINT: + gl.glEvalMesh2(GL2.GL_POINT, umin, umax, vmin, vmax); + break; + } + } + } + + /** + * Initializes evaluator + * @param type surface type + * @param ulo lowest u + * @param uhi highest u + * @param ustride number of objects between control points in u direction + * @param uorder surface order in u direction + * @param vlo lowest v + * @param vhi highest v + * @param vstride number of control points' coords + * @param vorder surface order in v direction + * @param pts control points + */ + public void map2f(int type, float ulo, float uhi, int ustride, int uorder, + float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) { + // TODO Auto-generated method stub + if (output_triangles) { + // System.out.println("TODO openglsurfaceevaluator.map2f output_triangles"); + } else { + gl.glMap2f(type, ulo, uhi, ustride, uorder, vlo, vhi, vstride, + vorder, pts.getArray(), pts.getPointer()); + } + } + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) { + //DONE + gl.glEnable(type); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java new file mode 100755 index 000000000..13b68138c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/gl2/nurbs/GLUgl2nurbsImpl.java @@ -0,0 +1,862 @@ +package com.jogamp.opengl.impl.glu.gl2.nurbs; +import com.jogamp.opengl.impl.glu.nurbs.*; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.lang.reflect.Method; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLUnurbs; + +/** + * Base object for working with NURBS curves and surfaces + * + * @author Tomas Hrasky + * + */ +public class GLUgl2nurbsImpl implements GLUnurbs { + + /** + * Curve type - no type + */ + public static final int CT_NONE = 0; + + /** + * Curve type - NURBS curve + */ + public static final int CT_NURBSCURVE = 1; + + /** + * Curve type - picewise linear curve + */ + public static final int CT_NPWLCURVE = 2; + + /** + * Matrixes autoloading + */ + private boolean autoloadmode; + + /** + * Using callback + */ + private int callBackFlag; + + /** + * Object for error call backs + */ + private Object errorCallback; + + /** + * List of map definitions + */ + Maplist maplist; + + /** + * Indicates validity of data + */ + private int isDataValid; + + /** + * Are we in the middle of curve processing + */ + private int inCurve; + + /** + * Current curve + */ + private O_curve currentCurve; + + /** + * Are we in trim + */ + private boolean inTrim; + + /** + * Are we playbacking curve/surface rendering + */ + private boolean playBack; + + /** + * Next curve in linked list + */ + private O_curve nextCurve; + + /** + * Is curve modified + */ + private int isCurveModified; + + /** + * Object holding rendering settings + */ + private Renderhints renderhints; + + /** + * Display list + */ + private DisplayList dl; + + /** + * Object for subdividing curves and surfaces + */ + private Subdivider subdivider; + + /** + * Object responsible for rendering + */ + private Backend backend; + + /** + * Next picewise linear curve in linked list + */ + private O_pwlcurve nextPwlcurve; + + /** + * Next trimming NURBS curve in linked list + */ + private O_nurbscurve nextNurbscurve; + + /** + * Are we in the middle of surface processing + */ + private int inSurface; + + /** + * Are there any changes in trimming + */ + private boolean isTrimModified; + + /** + * Are there any changes in surface data + */ + private boolean isDataSurfaceModified; + + /** + * Nurber of trmims of processed surface + */ + private int numTrims; + + /** + * Current processed surface + */ + private O_surface currentSurface; + + /** + * Next trimming curve + */ + private O_trim nextTrim; + + /** + * Nextr surface in linked list + */ + private O_nurbssurface nextNurbssurface; + + /** + * Are there any changes in surface + */ + private boolean isSurfaceModified; + + /** + * Initializes default GLUgl2nurbs object + */ + public GLUgl2nurbsImpl() { + // DONE + maplist = new Maplist(backend); + renderhints = new Renderhints(); + subdivider = new Subdivider(); + // original code + + redefineMaps(); + + defineMap(GL2.GL_MAP2_NORMAL, 0, 3); + defineMap(GL2.GL_MAP1_NORMAL, 0, 3); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_1, 0, 1); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_1, 0, 1); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_2, 0, 2); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_2, 0, 2); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_3, 0, 3); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_3, 0, 3); + defineMap(GL2.GL_MAP2_TEXTURE_COORD_4, 1, 4); + defineMap(GL2.GL_MAP1_TEXTURE_COORD_4, 1, 4); + defineMap(GL2.GL_MAP2_VERTEX_4, 1, 4); + defineMap(GL2.GL_MAP1_VERTEX_4, 1, 4); + defineMap(GL2.GL_MAP2_VERTEX_3, 0, 3); + defineMap(GL2.GL_MAP1_VERTEX_3, 0, 3); + defineMap(GL2.GL_MAP2_COLOR_4, 0, 4); + defineMap(GL2.GL_MAP1_COLOR_4, 0, 4); + defineMap(GL2.GL_MAP2_INDEX, 0, 1); + defineMap(GL2.GL_MAP1_INDEX, 0, 1); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_SAMPLINGMETHOD, + (float) NurbsConsts.N_PATHLENGTH); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_PIXEL_TOLERANCE, + (float) 50.0); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_ERROR_TOLERANCE, + (float) 0.50); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP1_VERTEX_4, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_3, NurbsConsts.N_S_STEPS, + (float) 100.0); + setnurbsproperty(GL2.GL_MAP2_VERTEX_4, NurbsConsts.N_S_STEPS, + (float) 100.0); + + setnurbsproperty(GL2.GL_MAP1_VERTEX_3, NurbsConsts.N_SAMPLINGMETHOD, + NurbsConsts.N_PATHLENGTH); + + set_domain_distance_u_rate(100.0); + set_domain_distance_v_rate(100.0); + set_is_domain_distance_sampling(0); + + this.autoloadmode = true; + + this.callBackFlag = 0; + + this.errorCallback = null; + } + + /** + * Sets domain distance for dom.dist. sampling in u direction + * + * @param d + * distance + */ + private void set_domain_distance_u_rate(double d) { + // DONE + subdivider.set_domain_distance_u_rate(d); + } + + /** + * Sets domain distance for dom.dist. sampling in v direction + * + * @param d + * distance + */ + private void set_domain_distance_v_rate(double d) { + // DONE + subdivider.set_domain_distance_v_rate(d); + } + + /** + * Begins new NURBS curve + */ + public void bgncurve() { + // DONE + O_curve o_curve = new O_curve(); + thread("do_bgncurve", o_curve); + } + + /** + * Calls a method with given name and passes argumet + * + * @param name + * name of a method to be called + * @param arg + * parameter to be passed to called method + */ + private void thread(String name, Object arg) { + // DONE + Class partype[] = new Class[1]; + partype[0] = arg.getClass(); + Method m; + try { + m = this.getClass().getMethod(name, partype); + if (dl != null) { + dl.append(this, m, arg); + } else { + m.invoke(this, new Object[] { arg }); + } + } catch (Throwable e) { + e.printStackTrace(); + } + + } + + /** + * Calls a method with given name + * + * @param name + * name of a method to be called + */ + private void thread2(String name) { + // DONE + try { + Method m = this.getClass().getMethod(name, (Class[]) null); + if (dl != null) { + dl.append(this, m, null); + } else { + m.invoke(this, (Object[]) null); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + /** + * Begins a NURBS curve + * + * @param o_curve + * curve object + */ + public void do_bgncurve(O_curve o_curve) { + if (inCurve > 0) { + do_nurbserror(6); + endcurve(); + } + inCurve = 1; + currentCurve = o_curve; + + currentCurve.curvetype = CT_NONE; + + if (inTrim) { + if (!nextCurve.equals(o_curve)) { + isCurveModified = 1; + nextCurve = o_curve; + } + } else { + if (!playBack) + bgnrender(); + isDataValid = 1; + } + nextCurve = o_curve.next; + // kind of solution of union + nextPwlcurve = o_curve.o_pwlcurve; + nextNurbscurve = o_curve.o_nurbscurve; + } + + /** + * Begins new surface + * + * @param o_surface + * surface object + */ + public void do_bgnsurface(O_surface o_surface) { + // DONE + if (inSurface > 0) { + do_nurbserror(27); + endsurface(); + } + inSurface = 1; + if (!playBack) + bgnrender(); + + isTrimModified = false; + isDataSurfaceModified = false; + isDataValid = 1; + numTrims = 0; + currentSurface = o_surface; + nextTrim = o_surface.o_trim; + nextNurbssurface = o_surface.o_nurbssurface; + } + + /** + * End a curve + */ + public void endcurve() { + // DONE + thread2("do_endcurve"); + } + + /** + * Ends surface + */ + public void do_endsurface() { + // DONE + if (inTrim) { + do_nurbserror(12); + endtrim(); + } + + if (inSurface <= 0) { + do_nurbserror(13); + return; + } + + inSurface = 0; + + nextNurbssurface = null; + + if (isDataValid <= 0) { + return; + } + + if (nextTrim != null) { + isTrimModified = true; + nextTrim = null; + } + + // TODO errval ?? + if (numTrims > 0) { + // System.out.println("TODO glunurbs.do_endsurface - numtrims > 0"); + } + + subdivider.beginQuilts(new GL2Backend()); + for (O_nurbssurface n = currentSurface.o_nurbssurface; n != null; n = n.next) { + subdivider.addQuilt(n.bezier_patches); + } + subdivider.endQuilts(); + subdivider.drawSurfaces(); + if (!playBack) + endrender(); + + } + + /** + * Ends a curve + */ + public void do_endcurve() { + // DONE + // // System.out.println("do_endcurve"); + if (inCurve <= 0) { + do_nurbserror(7); + return; + } + inCurve = 0; + + nextCurve = null; + + if (currentCurve.curvetype == CT_NURBSCURVE) { + // nextNurbscurve = null; + // currentCurve.o_nurbscurve=null; + } else { + // nextPwlcurve = null; + // currentCurve.o_pwlcurve=null; + } + if (!inTrim) { + if (isDataValid <= 0) { + return; + } + // TODO errval? + if (currentCurve.curvetype == CT_NURBSCURVE) { + subdivider.beginQuilts(new GL2Backend()); + + for (O_nurbscurve n = currentCurve.o_nurbscurve; n != null; n = n.next) + subdivider.addQuilt(n.bezier_curves); + + subdivider.endQuilts(); + subdivider.drawCurves(); + if (!playBack) + endrender(); + } else { + if (!playBack) + endrender(); + do_nurbserror(9); + } + } + + } + + /** + * Method for handling error codes + * + * @param i + * error code + */ + private void do_nurbserror(int i) { + // TODO nurberror + // System.out.println("TODO nurbserror " + i); + } + + /** + * Begin rendering + */ + private void bgnrender() { + // DONE + if (autoloadmode) { + loadGLMatrices(); + } + } + + /** + * Load matrices from OpenGL state machine + */ + private void loadGLMatrices() { + // TODO Auto-generated method stub + // System.out.println("TODO glunurbs.loadGLMatrices"); + } + + /** + * End rendering + */ + private void endrender() { + // DONE + } + + /** + * Make a NURBS curve + * + * @param nknots + * number of knots in knot vector + * @param knot + * knot vector + * @param stride + * number of control points coordinates + * @param ctlarray + * control points + * @param order + * order of the curve + * @param realType + * type of the curve + */ + public void nurbscurve(int nknots, float[] knot, int stride, + float[] ctlarray, int order, int realType) { + // DONE + Mapdesc mapdesc = maplist.locate(realType); + if (mapdesc == null) { + do_nurbserror(35); + isDataValid = 0; + return; + } + if (ctlarray == null) { + do_nurbserror(36); + isDataValid = 0; + return; + } + if (stride < 0) { + do_nurbserror(34); + isDataValid = 0; + return; + } + Knotvector knots = new Knotvector(nknots, stride, order, knot); + + if (!do_check_knots(knots, "curve")) + return; + + O_nurbscurve o_nurbscurve = new O_nurbscurve(realType); + o_nurbscurve.bezier_curves = new Quilt(mapdesc); + CArrayOfFloats ctrlcarr = new CArrayOfFloats(ctlarray); + o_nurbscurve.bezier_curves.toBezier(knots, ctrlcarr, mapdesc + .getNCoords()); + thread("do_nurbscurve", o_nurbscurve); + } + + /** + * Check knot vector specification + * + * @param knots + * knot vector + * @param msg + * error message + * @return knot vector is / is not valid + */ + public boolean do_check_knots(Knotvector knots, String msg) { + // DONE + int status = knots.validate(); + if (status > 0) { + do_nurbserror(status); + if (renderhints.errorchecking != NurbsConsts.N_NOMSG) + knots.show(msg); + } + return (status > 0) ? false : true; + } + + /** + * Draw a curve + * + * @param o_nurbscurve + * NURBS curve object + */ + public void do_nurbscurve(O_nurbscurve o_nurbscurve) { + // DONE + + if (inCurve <= 0) { + bgncurve(); + inCurve = 2; + } + + if (o_nurbscurve.used) { + do_nurbserror(23); + isDataValid = 0; + return; + } else + o_nurbscurve.used = true; + + if (currentCurve.curvetype == CT_NONE) { + currentCurve.curvetype = CT_NURBSCURVE; + } else if (currentCurve.curvetype != CT_NURBSCURVE) { + do_nurbserror(24); + isDataValid = 0; + return; + } + + // it was necessary to overcome problem with pointer to pointer here + + // if(!o_nurbscurve.equals(nextNurbscurve)){ + if (!o_nurbscurve.equals(currentCurve.o_nurbscurve)) { + isCurveModified = 1; + currentCurve.o_nurbscurve = o_nurbscurve; + // nextNurbscurve=o_nurbscurve; + + } + + nextNurbscurve = o_nurbscurve.next; + + if (!currentCurve.equals(o_nurbscurve.owner)) { + isCurveModified = 1; + o_nurbscurve.owner = currentCurve; + } + + if (o_nurbscurve.owner == null) + isCurveModified = 1; + + if (inCurve == 2) + endcurve(); + } + + /** + * Draw NURBS surface + * + * @param o_nurbssurface + * NURBS surface object + */ + public void do_nurbssurface(O_nurbssurface o_nurbssurface) { + // DONE + if (inSurface <= 0) { + bgnsurface(); + inSurface = 2; + } + if (o_nurbssurface.used) { + do_nurbserror(25); + isDataValid = 0; + return; + } else + o_nurbssurface.used = true; + + if (!o_nurbssurface.equals(nextNurbscurve)) { + isSurfaceModified = true; + // nextNurbssurface=o_nurbssurface; + currentSurface.o_nurbssurface = o_nurbssurface; + } + + if (!currentSurface.equals(o_nurbssurface.owner)) { + isSurfaceModified = true; + o_nurbssurface.owner = currentSurface; + } + + nextNurbssurface = o_nurbssurface.next; + + if (inSurface == 2) + endsurface(); + } + + /** + * (Re)Inicialize maps + */ + public void redefineMaps() { + // DONE + maplist.initialize(); + } + + /** + * Define a map of given properties + * + * @param type + * map type + * @param rational + * is rational + * @param ncoords + * number of control point coordinates + */ + public void defineMap(int type, int rational, int ncoords) { + // DONE + maplist.define(type, rational, ncoords); + } + + /** + * Set NURBS property + * + * @param type + * property type + * @param tag + * property tag + * @param value + * property value + */ + public void setnurbsproperty(int type, int tag, float value) { + // DONE + Mapdesc mapdesc = maplist.locate(type); + if (mapdesc == null) { + do_nurbserror(35); + return; + } + if (!mapdesc.isProperty(tag)) { + do_nurbserror(26); + return; + } + Property prop = new Property(type, tag, value); + thread("do_setnurbsproperty2", prop); + } + + /** + * Set parameters of existing property + * + * @param prop + * property + */ + public void do_setnurbsproperty2(Property prop) { + Mapdesc mapdesc = maplist.find(prop.type); + mapdesc.setProperty(prop.tag, prop.value); + } + + /** + * Set given property to rendering hints + * + * @param prop + * property to be set + */ + public void do_setnurbsproperty(Property prop) { + // DONE + renderhints.setProperty(prop); + // TODO freeproperty? + } + + /** + * Sets wheteher we use domain distance sampling + * + * @param i + * domain distance sampling flag + */ + public void set_is_domain_distance_sampling(int i) { + // DONE + subdivider.set_is_domain_distance_sampling(i); + } + + /** + * Begin new surface + */ + public void bgnsurface() { + // DONE + O_surface o_surface = new O_surface(); + // TODO nuid + // System.out.println("TODO glunurbs.bgnsurface nuid"); + thread("do_bgnsurface", o_surface); + } + + /** + * End current surface + */ + public void endsurface() { + // DONE + thread2("do_endsurface"); + } + + /** + * End surface trimming + */ + private void endtrim() { + // TODO Auto-generated method stub + // System.out.println("TODO glunurbs.endtrim"); + } + + /** + * Make NURBS surface + * + * @param sknot_count + * number of knots in s direction + * @param sknot + * knot vector in s direction + * @param tknot_count + * number of knots in t direction + * @param tknot + * knot vector in t direction + * @param s_stride + * number of coords of control points in s direction + * @param t_stride + * number of coords of control points in t direction + * @param ctlarray + * control points + * @param sorder + * order of curve in s direction + * @param torder + * order of curve in t direction + * @param type + * NURBS surface type (rational,...) + */ + public void nurbssurface(int sknot_count, float[] sknot, int tknot_count, + float[] tknot, int s_stride, int t_stride, float[] ctlarray, + int sorder, int torder, int type) { + // DONE + Mapdesc mapdesc = maplist.locate(type); + if (mapdesc == null) { + do_nurbserror(35); + isDataValid = 0; + return; + } + if (s_stride < 0 || t_stride < 0) { + do_nurbserror(34); + isDataValid = 0; + return; + } + Knotvector sknotvector = new Knotvector(sknot_count, s_stride, sorder, + sknot); + if (!do_check_knots(sknotvector, "surface")) + return; + Knotvector tknotvector = new Knotvector(tknot_count, t_stride, torder, + tknot); + if (!do_check_knots(tknotvector, "surface")) + return; + + O_nurbssurface o_nurbssurface = new O_nurbssurface(type); + o_nurbssurface.bezier_patches = new Quilt(mapdesc); + + CArrayOfFloats ctrlarr = new CArrayOfFloats(ctlarray); + o_nurbssurface.bezier_patches.toBezier(sknotvector, tknotvector, + ctrlarr, mapdesc.getNCoords()); + thread("do_nurbssurface", o_nurbssurface); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java new file mode 100644 index 000000000..501f5f585 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/BuildMipmap.java @@ -0,0 +1,1598 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.impl.InternalBufferUtil; +import java.nio.*; +import java.io.*; + +/** + * + * @author Administrator + */ +public class BuildMipmap { + + private static final boolean DEBUG = Debug.debug("BuildMipmap"); + private static final boolean VERBOSE = Debug.verbose(); + + /** Creates a new instance of BuildMipmap */ + public BuildMipmap() { + } + + public static int gluBuild1DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int widthPowerOf2, int format, int type, int userLevel, + int baseLevel, int maxLevel, ByteBuffer data ) { + int newwidth; + int level, levels; + ShortBuffer newImage = null; + int newImage_width; + ShortBuffer otherImage = null; + ShortBuffer imageTemp = null; + int memReq; + int maxsize; + int cmpts; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 ); + + newwidth = widthPowerOf2; + levels = Mipmap.computeLog( newwidth ); + + levels += userLevel; + + Mipmap.retrieveStoreModes( gl, psm ); + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( width, 1, format, + GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + + Image.fill_image( psm, width, 1, format, type, Mipmap.is_index( format ), data, newImage ); + cmpts = Mipmap.elements_per_group( format, type ); + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + // if swap_bytes was set, swapping occurred in fill_image + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = userLevel; level <= levels; level++ ) { + if( newImage_width == newwidth ) { + // user newimage for this level + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, format, + GL2.GL_UNSIGNED_SHORT, newImage ); + } + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth, 1, format, GL2.GL_UNSIGNED_SHORT ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + ScaleInternal.scale_internal( cmpts, newImage_width, 1, newImage, newwidth, 1, otherImage ); + // swap newImage and otherImage + imageTemp = otherImage; + otherImage = newImage; + newImage = imageTemp; + + newImage_width = newwidth; + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage1D( target, level, internalFormat, newImage_width, 0, + format, GL2.GL_UNSIGNED_SHORT, newImage ); + } + } + if( newwidth > 1 ) { + newwidth /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int bitmapBuild2DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int format, int type, ByteBuffer data ) { + int newwidth[] = new int[1]; + int newheight[] = new int[1]; + int level, levels; + ShortBuffer newImage = null; + int newImage_width; + int newImage_height; + ShortBuffer otherImage = null; + ShortBuffer tempImage = null; + int memReq; + int maxsize; + int cmpts; + PixelStorageModes psm = new PixelStorageModes(); + + Mipmap.retrieveStoreModes( gl, psm ); + + Mipmap.closestFit( gl, target, width, height, internalFormat, format, type, newwidth, newheight ); + + levels = Mipmap.computeLog( newwidth[0] ); + level = Mipmap.computeLog( newheight[0] ); + if( level > levels ) { + levels = level; + } + + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( width, height, + format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + newImage_height = height; + + Image.fill_image( psm, width, height, format, type, Mipmap.is_index( format ), data, newImage ); + + cmpts = Mipmap.elements_per_group( format, type ); + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 2 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + // if swap_bytes is set, swapping occurred in fill_image + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = 0; level < levels; level++ ) { + if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) { + newImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newImage_width, + newImage_height, 0, format, GL2.GL_UNSIGNED_SHORT, newImage ); + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_SHORT ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )).asShortBuffer(); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + ScaleInternal.scale_internal( cmpts, newImage_width, newImage_height, + newImage, newwidth[0], newheight[0], otherImage ); + // swap newImage and otherImage + tempImage = otherImage; + otherImage = newImage; + newImage = tempImage; + + newImage_width = newwidth[0]; + newImage_height = newheight[0]; + newImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_SHORT, newImage ); + } + if( newheight[0] > 1 ) { + newwidth[0] /= 2; + } + if( newheight[0] > 1 ) { + newheight[0] /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int gluBuild2DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int height, int widthPowerOf2, int heightPowerOf2, + int format, int type, int userLevel, int baseLevel, int maxLevel, + ByteBuffer data ) { // PointerWrapper data + int newwidth; + int newheight; + int level, levels; + int usersImage; + ByteBuffer srcImage = null; + ByteBuffer dstImage = null; + ByteBuffer tempImage = null; + int newImage_width; + int newImage_height; + short[] SWAP_IMAGE = null; + int memReq; + int maxsize; + int cmpts; + int mark=-1; + + boolean myswap_bytes; + int groups_per_line, element_size, group_size; + int rowsize, padding; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 && height >= 1 ); + + if( type == GL2.GL_BITMAP ) { + return( bitmapBuild2DMipmaps( gl, target, internalFormat, width, height, format, type, data ) ); + } + + newwidth = widthPowerOf2; + newheight = heightPowerOf2; + levels = Mipmap.computeLog( newwidth ); + level = Mipmap.computeLog( newheight ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + + Mipmap.retrieveStoreModes( gl, psm ); + myswap_bytes = psm.getUnpackSwapBytes(); + cmpts = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groups_per_line = psm.getUnpackRowLength(); + } else { + groups_per_line = width; + } + + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * cmpts; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + + mark = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size; + data.position( mark ); + + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + + level = userLevel; + + // already power of two square + if( width == newwidth && height == newheight ) { + // use usersImage for level userLevel + if( baseLevel <= level && level <= maxLevel ) { + data.rewind(); + gl.glTexImage2D( target, level, internalFormat, width, height, 0, format, type, data ); + } + if( levels == 0 ) { /* we're done. clean up and return */ + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( 0 ); + } + int nextWidth = newwidth / 2; + int nextHeight = newheight / 2; + + // clamp to 1 + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + memReq = Mipmap.image_size( nextWidth, nextHeight, format, type ); + + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + if( dstImage != null ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + HalveImage.halveImage_ubyte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + HalveImage.halveImage_byte( cmpts, width, height, data, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + HalveImage.halveImage_ushort( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + HalveImage.halveImage_short( cmpts, width, height, data, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + HalveImage.halveImage_uint( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + HalveImage.halveImage_int( cmpts, width, height, data, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + HalveImage.halveImage_float( cmpts, width, height, data, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract332(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract233rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel( 3, new Extract565(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel( 3, new Extract565rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel( 4, new Extract4444(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel( 4, new Extract5551(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel( 4, new Extract8888(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel( 4, new Extract1010102(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), width, height, data, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + } + newwidth = width / 2; + newheight = height / 2; + // clamp to 1 + if( newwidth < 1 ) { + newwidth = 1; + } + if( newheight < 1 ) { + newheight = 1; + } + + myswap_bytes = false; + rowsize = newwidth * group_size; + memReq = Mipmap.image_size( newwidth, newheight, format, type ); + // swap srcImage and dstImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + // level userLevel+1 is in srcImage; level userLevel already saved + level = userLevel + 1; + } else { // user's image is not nice powerof2 size square + memReq = Mipmap.image_size( newwidth, newheight, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + data.position( mark ); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + ScaleInternal.scale_internal_ubyte( cmpts, width, height, data, + newwidth, newheight, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + ScaleInternal.scale_internal_byte( cmpts, width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth, + newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + ScaleInternal.scale_internal_ushort( cmpts, width, height, data, newwidth, + newheight, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + ScaleInternal.scale_internal_uint( cmpts, width, height, data, newwidth, + newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + ScaleInternal.scale_internal_int( cmpts, width, height, data, newwidth, + newheight, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + ScaleInternal.scale_internal_float( cmpts, width, height, data, newwidth, + newheight, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract332(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract233rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract565(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + ScaleInternal.scaleInternalPackedPixel( 3, new Extract565rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract4444rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract5551(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract1555rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract8888rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract1010102(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + ScaleInternal.scaleInternalPackedPixel( 4, new Extract2101010rev(), width, height, data, newwidth, + newheight, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + myswap_bytes = false; + rowsize = newwidth * group_size; + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( levels != 0 ) { // use as little memory as possible + int nextWidth = newwidth / 2; + int nextHeight = newheight / 2; + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + + memReq = Mipmap.image_size( nextWidth, nextHeight, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // level userLevel is in srcImage; nothing saved yet + level = userLevel; + } + + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + if( baseLevel <= level && level <= maxLevel ) { + srcImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + "): " + gl.glGetError() ); + if (VERBOSE) { + srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) ); + writeTargaFile("glu2DMipmapJ" + level + ".tga", + srcImage, newwidth, newheight); + srcImage.clear(); + } + } + } + + level++; // update current level for the loop + for( ; level <= levels; level++ ) { + srcImage.rewind(); + dstImage.rewind(); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + HalveImage.halveImage_ubyte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_BYTE ): + HalveImage.halveImage_byte( cmpts, newwidth, newheight, srcImage, dstImage, element_size, rowsize, group_size ); + break; + case( GL2.GL_UNSIGNED_SHORT ): + HalveImage.halveImage_ushort( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_SHORT ): + HalveImage.halveImage_short( cmpts, newwidth, newheight, srcImage, dstImage.asShortBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT ): + HalveImage.halveImage_uint( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_INT ): + HalveImage.halveImage_int( cmpts, newwidth, newheight, srcImage, dstImage.asIntBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_FLOAT ): + HalveImage.halveImage_float( cmpts, newwidth, newheight, srcImage, dstImage.asFloatBuffer(), element_size, rowsize, group_size, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract332(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel( 3, new Extract233rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel( 3, new Extract565(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel( 3, new Extract565rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel( 4, new Extract4444(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract4444rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel( 4, new Extract5551(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract1555rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel( 4, new Extract8888(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract8888rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel( 4, new Extract1010102(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel( 4, new Extract2101010rev(), newwidth, newheight, srcImage, dstImage, element_size, rowsize, myswap_bytes ); + break; + default: + assert( false ); + break; + } + + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( newwidth > 1 ) { + newwidth /= 2; + rowsize /= 2; + } + if( newheight > 1 ) { + newheight /= 2; + } + // compute amount to pad per row if any + int rowPad = rowsize % psm.getUnpackAlignment(); + + // should row be padded + if( rowPad == 0 ) { + // call teximage with srcImage untouched since its not padded + if( baseLevel <= level && level <= maxLevel ) { + srcImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, srcImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + "): " + gl.glGetError() ); + if (VERBOSE) { + srcImage.limit( Mipmap.image_size( newwidth, newheight, format, type ) ); + writeTargaFile("glu2DMipmapJ" + level + ".tga", + srcImage, newwidth, newheight); + srcImage.clear(); + } + } + } + } else { + // compute length of new row in bytes, including padding + int newRowLength = rowsize + psm.getUnpackAlignment() - rowPad; + int ii, jj; + int dstTrav; + int srcTrav; + + // allocate new image for mipmap of size newRowLength x newheight + ByteBuffer newMipmapImage = null; + try { + newMipmapImage = ByteBuffer.allocateDirect( newRowLength * newheight ); + } catch( OutOfMemoryError ome ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + srcImage.rewind(); + // copy image from srcImage into newMipmapImage by rows + for( ii = 0; ii < newheight; ii++ ) { + newMipmapImage.position(newRowLength * ii); + for( jj = 0; jj < rowsize; jj++ ) { + newMipmapImage.put( srcImage.get() ); + } + } + + // and use this new image for mipmapping instead + if( baseLevel <= level && level <= maxLevel ) { + newMipmapImage.rewind(); + gl.glTexImage2D( target, level, internalFormat, newwidth, newheight, 0, format, type, newMipmapImage ); + if (DEBUG) { + System.err.println("GL Error(" + level + " padded): " + gl.glGetError() ); + if (VERBOSE) { + writeTargaFile("glu2DMipmapJ" + level + ".tga", + newMipmapImage, newwidth, newheight); + } + } + } + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, (psm.getUnpackSwapBytes() ? 1 : 0) ); + + return( 0 ); + } + + public static int fastBuild2DMipmaps( GL gl, PixelStorageModes psm, int target, + int components, int width, int height, int format, int type, ByteBuffer data ) { + int[] newwidth = new int[1]; + int[] newheight = new int[1]; + int level, levels; + ByteBuffer newImage; + int newImage_width; + int newImage_height; + ByteBuffer otherImage; + ByteBuffer imageTemp; + int memReq; + int maxsize; + int cmpts; + + Mipmap.closestFit( gl, target, width, height, components, format, type, newwidth, + newheight ); + + levels = Mipmap.computeLog( newwidth[0] ); + level = Mipmap.computeLog( newheight[0] ); + if( level > levels ) { + levels = level; + } + + cmpts = Mipmap.elements_per_group( format, type ); + + otherImage = null; + // No need to copy the user data if its packed correctly. + // Make sure that later routines don't change that data. + + if( psm.getUnpackSkipRows() == 0 && psm.getUnpackSkipPixels() == 0 ) { + newImage = data; + newImage_width = width; + newImage_height = height; + } else { + int rowsize; + int group_per_line; + int elements_per_line; + int start; + int iter; + int iter2; + int i, j; + + try { + newImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.image_size( + width, height, format, GL2.GL_UNSIGNED_BYTE ) )); + } catch( OutOfMemoryError err ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + newImage_width = width; + newImage_height = height; + + // Abbreviated version of fill_image for the restricted case. + if( psm.getUnpackRowLength() > 0 ) { + group_per_line = psm.getUnpackRowLength(); + } else { + group_per_line = width; + } + rowsize = group_per_line * cmpts; + elements_per_line = width * cmpts; + start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * cmpts; + + for( i = 0; i < height; i++ ) { + iter = start; + data.position( iter ); + for( j = 0; j < elements_per_line; j++ ) { + newImage.put( data.get() ); + } + start += rowsize; + } + } + + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, 1 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + + for( level = 0; level <= levels; level++ ) { + if( newImage_width == newwidth[0] && newImage_height == newheight[0] ) { + // use newImage for this level + newImage.rewind(); + gl.glTexImage2D( target, level, components, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_BYTE, newImage ); + } else { + if( otherImage == null ) { + memReq = Mipmap.image_size( newwidth[0], newheight[0], format, GL2.GL_UNSIGNED_BYTE ); + try { + otherImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ; + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // swap newImage and otherImage + imageTemp = otherImage; + otherImage = newImage; + newImage = imageTemp; + + newImage_width = newwidth[0]; + newImage_height = newheight[0]; + newImage.rewind(); + gl.glTexImage2D( target, level, components, newImage_width, newImage_height, + 0, format, GL2.GL_UNSIGNED_BYTE, newImage ); + } + if( newwidth[0] > 1 ) { + newwidth[0] /= 2; + } + if( newheight[0] > 1 ) { + newheight[0] /= 2; + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, ( psm.getUnpackSwapBytes() ? 1 : 0 ) ) ; + + return( 0 ); + } + + public static int gluBuild3DMipmapLevelsCore( GL gl, int target, int internalFormat, + int width, int height, int depth, int widthPowerOf2, int heightPowerOf2, + int depthPowerOf2, int format, int type, int userLevel, int baseLevel, + int maxLevel, ByteBuffer data ) { + int newWidth; + int newHeight; + int newDepth; + int level, levels; + ByteBuffer usersImage; + ByteBuffer srcImage, dstImage, tempImage; + int newImageWidth; + int newImageHeight; + int newImageDepth; + int memReq; + int maxSize; + int cmpts; + int mark=-1; + + boolean myswapBytes; + int groupsPerLine, elementSize, groupSize; + int rowsPerImage, imageSize; + int rowSize, padding; + PixelStorageModes psm = new PixelStorageModes(); + + assert( Mipmap.checkMipmapArgs( internalFormat, format, type ) == 0 ); + assert( width >= 1 && height >= 1 && depth >= 1 ); + assert( type != GL2.GL_BITMAP ); + + srcImage = dstImage = null; + + newWidth = widthPowerOf2; + newHeight = heightPowerOf2; + newDepth = depthPowerOf2; + levels = Mipmap.computeLog( newWidth ); + level = Mipmap.computeLog( newHeight ); + if( level > levels ) { + levels = level; + } + level = Mipmap.computeLog( newDepth ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + + Mipmap.retrieveStoreModes3D( gl, psm ); + myswapBytes = psm.getUnpackSwapBytes(); + cmpts = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groupsPerLine = psm.getUnpackRowLength(); + } else { + groupsPerLine = width; + } + + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * cmpts; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff + if( psm.getUnpackImageHeight() > 0 ) { + rowsPerImage = psm.getUnpackImageHeight(); + } else { + rowsPerImage = height; + } + + rowSize = groupsPerLine * groupSize; + padding = ( rowSize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowSize += psm.getUnpackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; + + usersImage = ByteBuffer.wrap(data.array()); + mark = psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize; + usersImage.position( mark ); + + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, 0 ); + + level = userLevel; + + if( width == newWidth && height == newHeight && depth == newDepth ) { + // use usersImage for level userlevel + if( baseLevel <= level && level <= maxLevel ) { + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + if( levels == 0 ) { /* we're done. clean up and return */ + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( 0 ); + } + int nextWidth = newWidth / 2; + int nextHeight = newHeight / 2; + int nextDepth = newDepth / 2; + + // clamp to one + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + if( nextDepth < 1 ) { + nextDepth = 1; + } + memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + if( dstImage != null ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth, + usersImage, dstImage, elementSize, + groupSize, rowSize, imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ubyte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_byte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ushort( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_short( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_uint( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_int( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_FLOAT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_float( cmpts, width, height, usersImage, + dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + assert( format == GL2.GL_RGB ); + HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + default: + assert( false ); + break; + } + } + newWidth = width / 2; + newHeight = height / 2; + newDepth = depth / 2; + // clamp to 1 + if( newWidth < 1 ) { + newWidth = 1; + } + if( newHeight < 1 ) { + newHeight = 1; + } + if( newDepth < 1 ) { + newDepth = 1; + } + + myswapBytes = false; + rowSize = newWidth * groupSize; + imageSize = rowSize * newHeight; + memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type ); + // swap srcImage and dstImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + // level userLevel + 1 is in srcImage; level userLevel already saved + level = userLevel + 1; + } else { + memReq = Mipmap.imageSize3D( newWidth, newHeight, newDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + + ScaleInternal.gluScaleImage3D( gl, format, width, height, depth, type, + usersImage, newWidth, newHeight, newDepth, type, dstImage ); + + myswapBytes = false; + rowSize = newWidth * groupSize; + imageSize = rowSize * newHeight; + // swap dstImage and srcImage + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( levels != 0 ) { + int nextWidth = newWidth / 2; + int nextHeight = newHeight / 2; + int nextDepth = newDepth / 2; + if( nextWidth < 1 ) { + nextWidth = 1; + } + if( nextHeight < 1 ) { + nextHeight = 1; + } + if( nextDepth < 1 ) { + nextDepth = 1; + } + memReq = Mipmap.imageSize3D( nextWidth, nextHeight, nextDepth, format, type ); + try { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + case( GL2.GL_BYTE ): + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_INT ): + case( GL2.GL_FLOAT ): + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + dstImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( memReq )); + break; + default: + return( GLU.GLU_INVALID_ENUM ); + } + } catch( OutOfMemoryError err ) { + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( GLU.GLU_OUT_OF_MEMORY ); + } + } + // level userLevel is in srcImage; nothing saved yet + level = userLevel; + } + + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE ); + if( baseLevel <= level && level <= maxLevel ) { + usersImage.position( mark ); + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + level++; + for( ; level <= levels; level++ ) { + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ubyte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_BYTE ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSByte(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_byte( cmpts, width, height, usersImage, + dstImage, elementSize, rowSize, groupSize ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_ushort( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_SHORT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSShort(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_short( cmpts, width, height, usersImage, + dstImage.asShortBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractUInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_uint( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_INT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractSInt(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_int( cmpts, width, height, usersImage, + dstImage.asIntBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_FLOAT ): + if( depth > 1 ) { + HalveImage.halveImage3D( cmpts, new ExtractFloat(), width, height, depth, + usersImage, dstImage, elementSize, groupSize, rowSize, + imageSize, myswapBytes ); + } else { + HalveImage.halveImage_float( cmpts, width, height, usersImage, + dstImage.asFloatBuffer(), elementSize, rowSize, groupSize, myswapBytes ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract332(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract233rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + HalveImage.halveImagePackedPixel3D( 3, new Extract565rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract4444rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract5551(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1555rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract8888rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + HalveImage.halveImagePackedPixel3D( 4, new Extract1010102(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + HalveImage.halveImagePackedPixel3D( 4, new Extract2101010rev(), width, height, depth, usersImage, + dstImage, elementSize, rowSize, imageSize, myswapBytes ); + break; + default: + assert( false ); + break; + } + + tempImage = srcImage; + srcImage = dstImage; + dstImage = tempImage; + + if( newWidth > 1 ) { + newWidth /= 2; + rowSize /= 2; + } + if( newHeight > 1 ) { + newHeight /= 2; + imageSize = rowSize * newHeight; + } + if( newDepth > 1 ) { + newDepth /= 2; + } + if( baseLevel <= level && level <= maxLevel ) { + usersImage.position( mark ); + gl.getGL2().glTexImage3D( target, level, internalFormat, width, height, depth, + 0, format, type, usersImage ); + } + } + gl.glPixelStorei( GL2.GL_UNPACK_ALIGNMENT, psm.getUnpackAlignment() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_ROWS, psm.getUnpackSkipRows() ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_PIXELS, psm.getUnpackSkipPixels() ); + gl.glPixelStorei( GL2.GL_UNPACK_ROW_LENGTH, psm.getUnpackRowLength() ); + gl.glPixelStorei( GL2.GL_UNPACK_SWAP_BYTES, psm.getUnpackSwapBytes() ? 1 : 0 ); + gl.glPixelStorei( GL2.GL_UNPACK_SKIP_IMAGES, psm.getUnpackSkipImages() ); + gl.glPixelStorei( GL2.GL_UNPACK_IMAGE_HEIGHT, psm.getUnpackImageHeight() ); + return( 0 ); + } + + private static final int TARGA_HEADER_SIZE = 18; + private static void writeTargaFile(String filename, ByteBuffer data, + int width, int height) { + try { + FileOutputStream fos = new FileOutputStream(new File(filename)); + ByteBuffer header = ByteBuffer.allocateDirect(TARGA_HEADER_SIZE); + header.put(0, (byte) 0).put(1, (byte) 0); + header.put(2, (byte) 2); // uncompressed type + header.put(12, (byte) (width & 0xFF)); // width + header.put(13, (byte) (width >> 8)); // width + header.put(14, (byte) (height & 0xFF)); // height + header.put(15, (byte) (height >> 8)); // height + header.put(16, (byte) 24); // pixel size + fos.write(header.array()); + fos.write(data.array()); + data.clear(); + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java new file mode 100644 index 000000000..be86585e7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract.java @@ -0,0 +1,56 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public interface Extract { + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ); + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java new file mode 100644 index 000000000..7e172b1ce --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1010102.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract1010102 implements Extract { + + /** Creates a new instance of Extract1010102 */ + public Extract1010102() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111111,11000000,00000000,00000000 == 0xFFC00000 + // 00000000,00111111,11110000,00000000 == 0x003F0000 + // 00000000,00000000,00001111,11111100 == 0x00000FFC + // 00000000,00000000,00000000,00000011 == 0x00000003 + + extractComponents[0] = (float)( ( uint & 0xFFC00000 ) >> 22 ) / 1023.0f; + extractComponents[1] = (float)( ( uint & 0x003FF000 ) >> 12 ) / 1023.0f; + extractComponents[2] = (float)( ( uint & 0x00000FFC ) >> 2 ) / 1023.0f; + extractComponents[3] = (float)( ( uint & 0x00000003 ) ) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) << 22) & 0xFFC00000 ); + uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 12) & 0x003FF000 ); + uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) << 2) & 0x00000FFC ); + uint |= (((int)((shoveComponents[3] * 3) + 0.5f) ) & 0x00000003 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java new file mode 100644 index 000000000..37895096e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract1555rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract1555rev implements Extract { + + /** Creates a new instance of Extract1555rev */ + public Extract1555rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00011111 == 0x001F + // 00000011,11100000 == 0x03E0 + // 01111100,00000000 == 0x7C00 + // 10000000,00000000 == 0x8000 + + extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x003E ) >> 5 ) / 31.0f; + extractComponents[2] = (float)( ( ushort & 0x7C00 ) >> 10) / 31.0f; + extractComponents[3] = (float)( ( ushort & 0x8000 ) >> 15); + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 00000000,00011111 == 0x001F + // 00000011,11100000 == 0x03E0 + // 01111100,00000000 == 0x7C00 + // 10000000,00000000 == 0x8000 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F ); + ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 5) & 0x000003E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 10) & 0x00007C00 ); + ushort |= (((int)((shoveComponents[3]) + 0.5f) << 15) & 0x00008000 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java new file mode 100644 index 000000000..077f3037b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract2101010rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract2101010rev implements Extract { + + /** Creates a new instance of Extract2101010 */ + public Extract2101010rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111111,11000000,00000000,00000000 == 0xFFC00000 + // 00000000,00111111,11110000,00000000 == 0x003F0000 + // 00000000,00000000,00001111,11111100 == 0x00000FFC + // 00000000,00000000,00000000,00000011 == 0x00000003 + + extractComponents[0] = (float)( ( uint & 0x000003FF ) ) / 1023.0f; + extractComponents[1] = (float)( ( uint & 0x000FFC00 ) >> 10 ) / 1023.0f; + extractComponents[2] = (float)( ( uint & 0x3FF00000 ) >> 20 ) / 1023.0f; + extractComponents[3] = (float)( ( uint & 0xC0000000 ) >> 30 ) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 1023) + 0.5f) ) & 0x000003FF ); + uint |= (((int)((shoveComponents[1] * 1023) + 0.5f) << 10) & 0x000FFC00 ); + uint |= (((int)((shoveComponents[2] * 1023) + 0.5f) << 20) & 0x3FF00000 ); + uint |= (((int)((shoveComponents[3] * 3) + 0.5f) << 30) & 0xC0000000 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java new file mode 100644 index 000000000..fa35c6fbc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract233rev.java @@ -0,0 +1,85 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract233rev implements Extract { + + /** Creates a new instance of Extract223rev */ + public Extract233rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + // 11100000 == 0xe0 + // 00011100 == 0x1c + // 00000011 == 0x03 + byte ubyte = packedPixel.get(); + extractComponents[0] = (float)((ubyte & 0x07) ) / 7.0f; + extractComponents[1] = (float)((ubyte & 0x38) >> 3) / 7.0f; + extractComponents[2] = (float)((ubyte & 0xC0) >> 6) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11100000 == 0xE0 + // 00011100 == 0x1C + // 00000011 == 0x03 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) ) & 0x07 ); + b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 3 ) & 0x38 ); + b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) << 6 ) & 0xC0 ); + packedPixel.position( index ); + packedPixel.put( b ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java new file mode 100644 index 000000000..35936466c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract332.java @@ -0,0 +1,84 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class Extract332 implements Extract { + + /** Creates a new instance of Extract332 */ + public Extract332() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + // 11100000 == 0xe0 + // 00011100 == 0x1c + // 00000011 == 0x03 + byte ubyte = packedPixel.get(); + extractComponents[0] = (float)((ubyte & 0xe0) >> 5) / 7.0f; + extractComponents[1] = (float)((ubyte & 0x1c) >> 2) / 7.0f; + extractComponents[2] = (float)((ubyte & 0x03)) / 3.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11100000 == 0xE0 + // 00011100 == 0x1C + // 00000011 == 0x03 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + byte b = (byte)( ( (int)( ( shoveComponents[0] * 7 ) + 0.5f ) << 5 ) & 0xE0 ); + b |= (byte)( ( (int)( ( shoveComponents[1] * 7 ) + 0.5f ) << 2 ) & 0x1C ); + b |= (byte)( ( (int)( ( shoveComponents[2] * 3 ) + 0.5f ) ) & 0x03 ); + packedPixel.put( index, b ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java new file mode 100644 index 000000000..bac4f57aa --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444.java @@ -0,0 +1,96 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract4444 implements Extract { + + /** Creates a new instance of Extract4444 */ + public Extract4444() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + extractComponents[0] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f; + extractComponents[1] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f; + extractComponents[2] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f; + extractComponents[3] = (float)( ( ushort & 0x000F ) ) / 15.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) << 12) & 0x0000F000 ); + ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 8) & 0x00000F00 ); + ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) << 4) & 0x000000F0 ); + ushort |= (((int)((shoveComponents[3] * 15) + 0.5f) ) & 0x0000000F ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java new file mode 100644 index 000000000..b1bea75e1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract4444rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract4444rev implements Extract { + + /** Creates a new instance of Extract4444rev */ + public Extract4444rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00001111 == 0x000F + // 00000000,11110000 == 0x00F0 + // 00001111,00000000 == 0x0F00 + // 11110000,00000000 == 0xF000 + + extractComponents[0] = (float)( ( ushort & 0x000F ) ) / 15.0f; + extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 4 ) / 15.0f; + extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 8 ) / 15.0f; + extractComponents[3] = (float)( ( ushort & 0xF000 ) >> 12 ) / 15.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 15) + 0.5f) ) & 0x0000000F ); + ushort |= (((int)((shoveComponents[1] * 15) + 0.5f) << 4) & 0x000000F0 ); + ushort |= (((int)((shoveComponents[2] * 15) + 0.5f) << 8) & 0x00000F00 ); + ushort |= (((int)((shoveComponents[3] * 15) + 0.5f) << 12) & 0x0000F000 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java new file mode 100644 index 000000000..a6247844f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract5551.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract5551 implements Extract { + + /** Creates a new instance of Extract5551 */ + public Extract5551() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x00F0 ) >> 6 ) / 31.0f; + extractComponents[2] = (float)( ( ushort & 0x0F00 ) >> 1 ) / 31.0f; + extractComponents[3] = (float)( ( ushort & 0xF000 ) ); + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 ); + ushort |= (((int)((shoveComponents[1] * 31) + 0.5f) << 6) & 0x000007C0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 1) & 0x0000003E ); + ushort |= (((int)((shoveComponents[3]) + 0.5f)) & 0x00000001 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java new file mode 100644 index 000000000..624a4f3f2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565.java @@ -0,0 +1,92 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract565 implements Extract { + + /** Creates a new instance of Extract565 */ + public Extract565() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11100000 == 0x07E0 + // 00000000,00111111 == 0x001F + + extractComponents[0] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f; + extractComponents[2] = (float)( ( ushort & 0x001F ) ) / 31.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11111000,00000000 == 0xF800 + // 00000111,11100000 == 0x07E0 + // 00000000,00111111 == 0x001F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) << 11) & 0x0000F800 ); + ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) ) & 0x0000001F ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java new file mode 100644 index 000000000..4ab6d7e98 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract565rev.java @@ -0,0 +1,92 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract565rev implements Extract { + + /** Creates a new instance of Extract565rev */ + public Extract565rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + int ushort = 0; + + if( isSwap ) { + ushort = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( packedPixel.getShort() ); + } else { + ushort = 0x0000FFFF & packedPixel.getShort(); + } + + // 00000000,00011111 == 0x001F + // 00000111,11100000 == 0x07E0 + // 11111000,00000000 == 0xF800 + + extractComponents[0] = (float)( ( ushort & 0x001F ) ) / 31.0f; + extractComponents[1] = (float)( ( ushort & 0x07E0 ) >> 5 ) / 63.0f; + extractComponents[2] = (float)( ( ushort & 0xF800 ) >> 11 ) / 31.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 00000000,00111111 == 0x001F + // 00000111,11100000 == 0x07E0 + // 11111000,00000000 == 0xF800 + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + + // due to limited precision, need to round before shoving + int ushort = (((int)((shoveComponents[0] * 31) + 0.5f) ) & 0x0000001F ); + ushort |= (((int)((shoveComponents[1] * 63) + 0.5f) << 5) & 0x000007E0 ); + ushort |= (((int)((shoveComponents[2] * 31) + 0.5f) << 11) & 0x0000F800 ); + packedPixel.asShortBuffer().put( index, (short)ushort ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java new file mode 100644 index 000000000..90d7e57c9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract8888 implements Extract { + + /** Creates a new instance of Extract8888 */ + public Extract8888() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f; + extractComponents[1] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f; + extractComponents[2] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f; + extractComponents[3] = (float)( ( uint & 0x000000FF ) ) / 255.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 255) + 0.5f) << 24) & 0xFF000000 ); + uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 16) & 0x00FF0000 ); + uint |= (((int)((shoveComponents[2] * 255) + 0.5f) << 8) & 0x0000FF00 ); + uint |= (((int)((shoveComponents[3] * 255) + 0.5f) ) & 0x000000FF ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java new file mode 100644 index 000000000..10970573b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Extract8888rev.java @@ -0,0 +1,97 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Extract8888rev implements Extract { + + /** Creates a new instance of Extract8888rev */ + public Extract8888rev() { + } + + public void extract( boolean isSwap, ByteBuffer packedPixel, float[] extractComponents ) { + long uint = 0; + + if( isSwap ) { + uint = 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( packedPixel.getInt() ); + } else { + uint = 0x00000000FFFFFFFF & packedPixel.getInt(); + } + + // 11111000,00000000 == 0xF800 + // 00000111,11000000 == 0x07C0 + // 00000000,00111110 == 0x003E + // 00000000,00000001 == 0x0001 + + extractComponents[0] = (float)( ( uint & 0x000000FF ) ) / 255.0f; + extractComponents[1] = (float)( ( uint & 0x0000FF00 ) >> 8 ) / 255.0f; + extractComponents[2] = (float)( ( uint & 0x00FF0000 ) >> 16 ) / 255.0f; + extractComponents[3] = (float)( ( uint & 0xFF000000 ) >> 24 ) / 255.0f; + } + + public void shove( float[] shoveComponents, int index, ByteBuffer packedPixel ) { + // 11110000,00000000 == 0xF000 + // 00001111,00000000 == 0x0F00 + // 00000000,11110000 == 0x00F0 + // 00000000,00001111 == 0x000F + + assert( 0.0f <= shoveComponents[0] && shoveComponents[0] <= 1.0f ); + assert( 0.0f <= shoveComponents[1] && shoveComponents[1] <= 1.0f ); + assert( 0.0f <= shoveComponents[2] && shoveComponents[2] <= 1.0f ); + assert( 0.0f <= shoveComponents[3] && shoveComponents[3] <= 1.0f ); + + // due to limited precision, need to round before shoving + long uint = (((int)((shoveComponents[0] * 255) + 0.5f) ) & 0x000000FF ); + uint |= (((int)((shoveComponents[1] * 255) + 0.5f) << 8) & 0x0000FF00 ); + uint |= (((int)((shoveComponents[2] * 255) + 0.5f) << 16) & 0x00FF0000 ); + uint |= (((int)((shoveComponents[3] * 255) + 0.5f) << 24) & 0xFF000000 ); + packedPixel.asIntBuffer().put( index, (int)uint ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java new file mode 100644 index 000000000..c42799470 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractFloat.java @@ -0,0 +1,74 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractFloat implements ExtractPrimitive { + + /** Creates a new instance of ExtractFloat */ + public ExtractFloat() { + } + + public double extract( boolean isSwap, ByteBuffer data ) { + float f = 0; + if( isSwap ) { + f = Mipmap.GLU_SWAP_4_BYTES( data.getInt() ); + } else { + f = data.getInt(); + } + assert( f <= 1.0f ); + return( f ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 1.0); + data.asFloatBuffer().put( index, (float)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java new file mode 100644 index 000000000..8b986d6d0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractPrimitive.java @@ -0,0 +1,56 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public interface ExtractPrimitive { + public double extract( boolean isSwap, ByteBuffer pointer ); + public void shove( double value, int index, ByteBuffer pointer ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java new file mode 100644 index 000000000..4f61015f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSByte.java @@ -0,0 +1,69 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class ExtractSByte implements ExtractPrimitive { + + /** Creates a new instance of ExtractUByte */ + public ExtractSByte() { + } + + public double extract( boolean isSwap, ByteBuffer sbyte ) { + byte b = sbyte.get(); + assert( b <= 127 ); + return( b ); + } + + public void shove( double value, int index, ByteBuffer data ) { + data.position( index ); + data.put( (byte)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java new file mode 100644 index 000000000..2d5ac5329 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSInt.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractSInt implements ExtractPrimitive { + + /** Creates a new instance of ExtractSInt */ + public ExtractSInt() { + } + + public double extract( boolean isSwap, ByteBuffer uint ) { + int i = 0; + if( isSwap ) { + i = Mipmap.GLU_SWAP_4_BYTES( uint.getInt() ); + } else { + i = uint.getInt(); + } + assert( i <= 0x7FFFFFFF ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < Integer.MAX_VALUE); + IntBuffer ib = data.asIntBuffer(); + ib.position( index ); + ib.put( (int)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java new file mode 100644 index 000000000..8b8d50cbf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractSShort.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractSShort implements ExtractPrimitive { + + /** Creates a new instance of ExtractSShort */ + public ExtractSShort() { + } + + public double extract( boolean isSwap, ByteBuffer ushort ) { + short s = 0; + if( isSwap ) { + s = Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() ); + } else { + s = ushort.getShort(); + } + assert( s <= 32767 ); + return( s ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 32768.0); + ShortBuffer sb = data.asShortBuffer(); + sb.position( index ); + sb.put( (short)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java new file mode 100644 index 000000000..d33213f89 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUByte.java @@ -0,0 +1,70 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.ByteBuffer; + +/** + * + * @author Administrator + */ +public class ExtractUByte implements ExtractPrimitive { + + /** Creates a new instance of ExtractUByte */ + public ExtractUByte() { + } + + public double extract( boolean isSwap, ByteBuffer ubyte ) { + int i = 0x000000FF & ubyte.get(); + assert( i <= 255 ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 256.0); + data.position( index ); + data.put( (byte)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java new file mode 100644 index 000000000..873668a43 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUInt.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractUInt implements ExtractPrimitive { + + /** Creates a new instance of ExtractUInt */ + public ExtractUInt() { + } + + public double extract( boolean isSwap, ByteBuffer uint ) { + long i = 0; + if( isSwap ) { + i = 0xFFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( uint.getInt() ); + } else { + i = 0xFFFFFFFF & uint.getInt(); + } + assert( i <= 0xFFFFFFFF ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 0xFFFFFFFF); + IntBuffer ib = data.asIntBuffer(); + ib.position( index ); + ib.put( (int)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java new file mode 100644 index 000000000..86bbb95f1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ExtractUShort.java @@ -0,0 +1,76 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class ExtractUShort implements ExtractPrimitive { + + /** Creates a new instance of ExtracUShort */ + public ExtractUShort() { + } + + public double extract( boolean isSwap, ByteBuffer ushort ) { + int i = 0; + if( isSwap ) { + i = 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( ushort.getShort() ); + } else { + i = 0x0000FFFF & ushort.getShort(); + } + assert( i <= 65535 ); + return( i ); + } + + public void shove( double value, int index, ByteBuffer data ) { + assert(0.0 <= value && value < 65536.0); + ShortBuffer sb = data.asShortBuffer(); + sb.position( index ); + sb.put( (short)value ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java new file mode 100644 index 000000000..893d33c66 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/HalveImage.java @@ -0,0 +1,1533 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import java.nio.*; + +/** + * + * @author Administrator + */ +public class HalveImage { + + private static final int BOX2 = 2; + private static final int BOX4 = 4; + private static final int BOX8 = 8; + + public static void halveImage( int components, int width, int height, + ShortBuffer datain, ShortBuffer dataout ) { + int i, j, k; + int newwidth, newheight; + int delta; + int t = 0; + short temp = 0; + + newwidth = width / 2; + newheight = height /2; + delta = width * components; + + // Piece of cake + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.get(); + datain.position( t + components ); + temp += datain.get(); + datain.position( t + delta ); + temp += datain.get(); + datain.position( t + delta + components ); + temp +=datain.get(); + temp += 2; + temp /= 4; + dataout.put( temp ); + t++; + } + t += components; + } + t += delta; + } + } + + public static void halveImage_ubyte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int i, j, k; + int newwidth, newheight; + int s; + int t; + + // Handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_ubyte( components, width, height, datain, dataout, element_size, ysize, group_size ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + s = 0; + t = 0; + + int temp = 0; + // piece of cake + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x000000FF & datain.get() ); + datain.position( t + group_size ); + temp += ( 0x000000FF & datain.get() ); + datain.position( t + ysize ); + temp += ( 0x000000FF & datain.get() ); + datain.position( t + ysize + group_size ); + temp += ( 0x000000FF & datain.get() ) + 2; + dataout.put( (byte)(temp / 4) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + + public static void halve1Dimage_ubyte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + int temp = 0; + + assert( width == 1 || height == 1 ); // Must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = ( 0x000000FF & datain.get() ); + datain.position( src + group_size ); + temp += ( 0x000000FF & datain.get() ); + temp /= 2; + dataout.put( (byte)temp ); + /* + dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + + (0x000000FF & datain.setIndexInBytes( src + group_size ).getByte())) / 2 ) ); + */ + src += element_size; + //dataout.plusPlus(); + dest++; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = ( 0x000000FF & datain.get() ); + datain.position( src + ysize ); + temp += ( 0x000000FF & datain.get() ); + temp /= 2; + dataout.put( (byte)temp ); + /* + dataout.setByte( (byte)(((0x000000FF & datain.setIndexInBytes(src).getByte()) + + (0x000000FF & datain.setIndexInBytes(src + ysize).getByte()) ) / 2 ) ); + */ + src += element_size; + //dataout.plusPlus(); + dest++; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + } + assert( src == ysize * height ); + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_byte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, int element_size, + int ysize, int group_size ) { + int i, j, k; + int newwidth, newheight; + int s = 0; + int t = 0; + byte temp = (byte)0; + + // handle case where there is only 1 column + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); + halve1Dimage_byte( components, width, height, datain, dataout, element_size, + ysize, group_size ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.get(); + datain.position( t + group_size ); + temp += datain.get(); + datain.position( t + ysize ); + temp += datain.get(); + datain.position( t + ysize + group_size ); + temp += datain.get(); + temp += 2; + temp /= 4; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + + public static void halve1Dimage_byte( int components, int width, int height, + ByteBuffer datain, ByteBuffer dataout, + int element_size, int ysize, int group_size ) { + int halfWidth = width / 2; + int halfHeight = width / 2; + int src = 0; + int dest = 0; + int jj; + byte temp = (byte)0; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = datain.get(); + datain.position( src + group_size ); + temp += datain.get(); + temp /= 2; + dataout.put( temp ); + src += element_size; + dest++; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assert only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + datain.position( src ); + temp = datain.get(); + datain.position( src + ysize ); + temp += datain.get(); + temp /= 2; + src += element_size; + dest++; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_ushort( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + int temp = 0; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_ushort( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x0000FFFF & datain.getShort() ); + datain.position( t + group_size ); + temp += ( 0x0000FFFF & datain.getShort() ); + datain.position( t + ysize ); + temp += ( 0x0000FFFF & datain.getShort() ); + datain.position( t + ysize + group_size ); + temp += ( 0x0000FFFF & datain.getShort() ); + dataout.put( (short)( ( temp + 2 ) / 4 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + group_size ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + ysize ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( t + ysize + group_size ); + temp += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + dataout.put( (short)( ( temp + 2 ) / 4 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_ushort( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < halfHeight; kk++ ) { + int[] ushort = new int[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( src + group_size ); + ushort[1] = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + } else { + datain.position( src ); + ushort[0] = (0x0000FFFF & datain.getShort() ); + datain.position( src + group_size ); + ushort[1] = (0x0000FFFF & datain.getShort() ); + } + dataout.put( (short)( (ushort[0] + ushort[1]) / 2 ) ); + src += element_size; + dest += 2; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + int[] ushort = new int[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + datain.position( src + ysize ); + ushort[0] = ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ) ); + } else { + datain.position( src ); + ushort[0] = ( 0x0000FFFF & datain.getShort() ); + datain.position( src + ysize ); + ushort[1] = ( 0x0000FFFF & datain.getShort() ); + } + dataout.put( (short)((ushort[0] + ushort[1]) / 2) ); + src += element_size; + dest += 2; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_short( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + short temp = (short)0; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_short( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getShort(); + datain.position( t + group_size ); + temp += datain.getShort(); + datain.position( t + ysize ); + temp += datain.getShort(); + datain.position( t + ysize + group_size ); + temp += datain.getShort(); + temp += 2; + temp /= 4; + dataout.put( (short)temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + short b; + int buf; + datain.position( t ); + temp = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + group_size ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + ysize ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( t + ysize + group_size ); + temp += Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + temp += 2; + temp /= 4; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_short( int components, int width, int height, + ByteBuffer datain, ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + short[] sshort = new short[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( src + group_size ); + sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + } else { + datain.position( src ); + sshort[0] = datain.getShort(); + datain.position( src + group_size ); + sshort[1] = datain.getShort(); + } + dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) ); + src += element_size; + dest += 2; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + short[] sshort = new short[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sshort[0] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + datain.position( src + ysize ); + sshort[1] = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + } else { + datain.position( src ); + sshort[0] = datain.getShort(); + datain.position( src + ysize ); + sshort[1] = datain.getShort(); + } + dataout.put( (short)(( sshort[0] + sshort[1] ) / 2) ); + src += element_size; + dest += 2; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImage_uint( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + double temp = 0; + + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_uint( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + group_size ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + ysize ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + datain.position( t + ysize + group_size ); + temp += (0x000000007FFFFFFFL & datain.getInt() ); + dataout.put( (int)( ( temp / 4 ) + 0.5 ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + // need to cast to double to hold large unsigned ints + double buf; + datain.position( t ); + buf = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + group_size ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + ysize ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( t + ysize + group_size ); + buf += ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + temp /= 4; + temp += 0.5; + dataout.put( (int)temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_uint( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // widthxheight can't be 1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < halfHeight; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + group_size ); + uint[1] = (0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { // 1 column + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); // widthxheight can't be 1 + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( uint[0] + uint[1] ) / 2.0 ) ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == components * element_size * halfWidth * halfHeight ); + } + + public static void halveImage_int( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + int temp = 0; + + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_int( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getInt(); + datain.position( t + group_size ); + temp += datain.getInt(); + datain.position( t + ysize ); + temp += datain.getInt(); + datain.position( t + ysize + group_size ); + temp += datain.getInt(); + temp = (int)( ( temp / 4.0f ) + 0.5f ); + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + long b; + float buf; + datain.position( t ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf = b; + datain.position( t + group_size ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + datain.position( t + ysize ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + datain.position( t + ysize + group_size ); + b = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + buf += b; + dataout.put( (int)( ( buf / 4.0f ) + 0.5f ) ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_int( int components, int width, int height, + ByteBuffer datain, IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + group_size ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)( ( (float)uint[0] + (float)uint[1] ) / 2.0f) ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + long[] uint = new long[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ) ); + } else { + datain.position( src ); + uint[0] = ( 0x00000000FFFFFFFF & datain.getInt() ); + datain.position( src + ysize ); + uint[1] = ( 0x00000000FFFFFFFF & datain.getInt() ); + } + dataout.put( (int)(( (float)uint[0] + (float)uint[1] ) / 2.0f) ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImage_float( int components, int width, int height, + ByteBuffer datain, FloatBuffer dataout, int element_size, + int ysize, int group_size, boolean myswap_bytes ) { + int i, j, k, l; + int newwidth, newheight; + int s = 0; + int t = 0; + float temp = 0.0f; + // handle case where there is only 1 column/row + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); // can't be 1x1 + halve1Dimage_float( components, width, height, datain, dataout, element_size, + ysize, group_size, myswap_bytes ); + return; + } + + newwidth = width / 2; + newheight = height / 2; + + // Piece of cake + if( !myswap_bytes ) { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + datain.position( t ); + temp = datain.getFloat(); + datain.position( t + group_size ); + temp += datain.getFloat(); + datain.position( t + ysize ); + temp += datain.getFloat(); + datain.position( t + ysize + group_size ); + temp /= 4.0f; + dataout.put( temp ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } else { + for( i = 0; i < newheight; i++ ) { + for( j = 0; j < newwidth; j++ ) { + for( k = 0; k < components; k++ ) { + float buf; + datain.position( t ); + buf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + group_size ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + ysize ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( t + ysize + group_size ); + buf += Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + dataout.put( buf / 4.0f ); + t += element_size; + } + t += group_size; + } + t += ysize; + } + } + } + + public static void halve1Dimage_float( int components, int width, int height, + ByteBuffer datain, FloatBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int dest = 0; + int jj; + + assert( width == 1 || height == 1 ); // must be 1D + assert( width != height ); // can't be square + + if( height == 1 ) { // 1 row + assert( width != 1 ); // can't be 1x1 + halfHeight = 1; + + for( jj = 0; jj < halfWidth; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + float[] sfloat = new float[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( src + group_size ); + sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + } else { + datain.position( src ); + sfloat[0] = datain.getFloat(); + datain.position( src + group_size ); + sfloat[1] = datain.getFloat(); + } + dataout.put( (sfloat[0] + sfloat[1]) / 2.0f ); + src += element_size; + dest += 4; + } + src += group_size; // skip to next 2 + } + int padBytes = ysize - ( width * group_size ); + src += padBytes; // for assertion only + } else if( width == 1 ) { + int padBytes = ysize - ( width * group_size ); + assert( height != 1 ); + halfWidth = 1; + // one vertical column with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + int kk; + for( kk = 0; kk < components; kk++ ) { + float[] sfloat = new float[BOX2]; + if( myswap_bytes ) { + datain.position( src ); + sfloat[0] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + datain.position( src + ysize ); + sfloat[1] = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + } else { + datain.position( src ); + sfloat[0] = datain.getFloat(); + datain.position( src + ysize ); + sfloat[1] = datain.getFloat(); + } + dataout.put( ( sfloat[0] + sfloat[1] ) / 2.0f ); + src += element_size; + dest += 4; + } + src += padBytes; // add pad bytes, if any, to get to end of row + src += ysize; + } + assert( src == ysize * height ); + } + assert( dest == ( components * element_size * halfWidth * halfHeight ) ); + } + + public static void halveImagePackedPixel( int components, Extract extract, int width, + int height, ByteBuffer datain, ByteBuffer dataout, + int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) { + if( width == 1 || height == 1 ) { + assert( !( width == 1 && height == 1 ) ); + halve1DimagePackedPixel( components, extract, width, height, datain, dataout, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } + int ii, jj; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + datain.position( src + rowSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[2] ); + datain.position( src + rowSizeInBytes + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[3] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX4; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + src += pixelSizeInBytes + pixelSizeInBytes; + } + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } + assert( src == rowSizeInBytes * height ); + assert( outIndex == halfWidth * halfHeight ); + } + + public static void halve1DimagePackedPixel( int components, Extract extract, int width, + int height, ByteBuffer datain, ByteBuffer dataout, + int pixelSizeInBytes, int rowSizeInBytes, boolean isSwap ) { + int halfWidth = width / 2; + int halfHeight = height / 2; + int src = 0; + int jj; + + assert( width == 1 || height == 1 ); + assert( width != height ); + + if( height == 1 ) { + int outIndex = 0; + + assert( width != 1 ); + halfHeight = 1; + + // one horizontal row with possible pad bytes + + for( jj = 0; jj < halfWidth; jj++ ) { + float[] totals = new float[4]; + float[][] extractTotals = new float[BOX2][4]; + int cc; + + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + pixelSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + // skip over to next group of 2 + src += pixelSizeInBytes + pixelSizeInBytes; + } + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + src += padBytes; + + assert( src == rowSizeInBytes ); + assert( outIndex == halfWidth * halfHeight ); + } else if( width == 1 ) { + int outIndex = 0; + + assert( height != 1 ); + halfWidth = 1; + // one vertical volumn with possible pad bytes per row + // average two at a time + + for( jj = 0; jj < halfHeight; jj++ ) { + float[] totals = new float[4]; + float[][] extractTotals = new float[BOX2][4]; + int cc; + // average two at a time, instead of four + datain.position( src ); + extract.extract( isSwap, datain, extractTotals[0] ); + datain.position( src + rowSizeInBytes ); + extract.extract( isSwap, datain, extractTotals[1] ); + for( cc = 0; cc < components; cc++ ) { + int kk = 0; + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } + extract.shove( totals, outIndex, dataout ); + outIndex++; + // skip over to next group of 2 + src += rowSizeInBytes + rowSizeInBytes; + } + assert( src == rowSizeInBytes ); + assert( outIndex == halfWidth * halfHeight ); + } + } + + public static void halveImagePackedPixelSlice( int components, Extract extract, + int width, int height, int depth, ByteBuffer dataIn, + ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + int ii, jj; + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + assert( (width == 1 || height == 1) && depth >= 2 ); + + if( width == height ) { + assert( width == 1 && height == 1 ); + assert( depth >= 2 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX2][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // average only 2 pixels since a column + totals[cc]= 0.0f; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= BOX2; + } // for cc + + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next group of 2 + src += imageSizeInBytes + imageSizeInBytes; + } // for ii + } else if( height == 1 ) { + assert( width != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc]+= extractTotals[kk][cc]; + } + totals[cc]/= (float)BOX4; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next horizontal square of 4 + src += imageSizeInBytes + imageSizeInBytes; + } + } + } else if( width == 1 ) { + assert( height != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; + float extractTotals[][] = new float[BOX4][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + rowSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + + // grab 4 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc]+= extractTotals[kk][cc]; + } + totals[cc]/= (float)BOX4; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next horizontal square of 4 + src += imageSizeInBytes + imageSizeInBytes; + } + } + } + } + + public static void halveImageSlice( int components, ExtractPrimitive extract, int width, + int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut, + int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + int ii, jj; + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * groupSizeInBytes ); + int outIndex = 0; + + assert( (width == 1 || height == 1) && depth >= 2 ); + + if( width == height ) { + assert( width == 1 && height == 1 ); + assert( depth >= 2 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + double[] totals = new double[4]; + double[][] extractTotals = new double[BOX2][4]; + int kk; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + + // average 2 pixels since only a column + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red]; + // totals[red] = red / 2; + for( kk = 0; kk < BOX2; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX2; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over next group of 2 + src += rowSizeInBytes; + } // for ii + + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfDepth * components ); + } else if( height == 1 ) { + assert( width != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX4][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + + // grab 4 pixels to average + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red] + + // extractTotals[2][red] + extractTotals[3][red]; + // totals[red] /= (double)BOX4; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX4; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over to next horizontal square of 4 + src += elementSizeInBytes; + } // for jj + src += padBytes; + src += rowSizeInBytes; + } // for ii + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfDepth * components ); + } else if( width == 1 ) { + assert( height != 1 ); + + for( ii = 0; ii < halfDepth; ii++ ) { + for( jj = 0; jj < halfHeight; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX4][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + + + // grab 4 pixels to average + totals[cc] = 0.0f; + // totals[red] = extractTotals[0][red] + extractTotals[1][red] + + // extractTotals[2][red] + extractTotals[3][red]; + // totals[red] /= (double)BOX4; + for( kk = 0; kk < BOX4; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX4; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + src += elementSizeInBytes; + } // for cc + // skip over to next horizontal square of 4 + src += padBytes; + src += rowSizeInBytes; + } // for jj + src += imageSizeInBytes; + } // for ii + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfDepth * components ); + } + } + + public static void halveImage3D( int components, ExtractPrimitive extract, + int width, int height, int depth, ByteBuffer dataIn, ByteBuffer dataOut, + int elementSizeInBytes, int groupSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + assert( depth > 1 ); + + // horizontal/vertical/onecolumn slice viewed from top + if( width == 1 || height == 1 ) { + assert( 1 <= depth ); + + halveImageSlice( components, extract, width, height, depth, dataIn, dataOut, + elementSizeInBytes, groupSizeInBytes, rowSizeInBytes, imageSizeInBytes, + isSwap ); + return; + } + + int ii, jj, dd; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * groupSizeInBytes ); + int outIndex = 0; + + for( dd = 0; dd < halfDepth; dd++ ) { + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + int cc; + for( cc = 0; cc < components; cc++ ) { + int kk; + double totals[] = new double[4]; + double extractTotals[][] = new double[BOX8][4]; + + dataIn.position( src ); + extractTotals[0][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes ); + extractTotals[1][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes ); + extractTotals[2][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + groupSizeInBytes ); + extractTotals[3][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + imageSizeInBytes ); + extractTotals[4][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + groupSizeInBytes + imageSizeInBytes ); + extractTotals[5][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extractTotals[6][cc] = extract.extract( isSwap, dataIn ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes + groupSizeInBytes ); + extractTotals[7][cc] = extract.extract( isSwap, dataIn ); + + totals[cc] = 0.0f; + + for( kk = 0; kk < BOX8; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (double)BOX8; + + extract.shove( totals[cc], outIndex, dataOut ); + outIndex++; + + src += elementSizeInBytes; + } // for cc + // skip over to next square of 4 + src += groupSizeInBytes; + } // for jj + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } // for ii + src += imageSizeInBytes; + } // for dd + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfHeight * halfDepth * components ); + } + + public static void halveImagePackedPixel3D( int components, Extract extract, + int width, int height, int depth, ByteBuffer dataIn, + ByteBuffer dataOut, int pixelSizeInBytes, int rowSizeInBytes, + int imageSizeInBytes, boolean isSwap ) { + if( depth == 1 ) { + assert( 1 <= width && 1 <= height ); + + halveImagePackedPixel( components, extract, width, height, dataIn, dataOut, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } else if( width == 1 || height == 1 ) { // a horizontal or vertical slice viewed from top + assert( 1 <= depth ); + + halveImagePackedPixelSlice( components, extract, width, height, depth, dataIn, + dataOut, pixelSizeInBytes, rowSizeInBytes, imageSizeInBytes, isSwap ); + return; + } + int ii, jj, dd; + + int halfWidth = width / 2; + int halfHeight = height / 2; + int halfDepth = depth / 2; + int src = 0; + int padBytes = rowSizeInBytes - ( width * pixelSizeInBytes ); + int outIndex = 0; + + for( dd = 0; dd < halfDepth; dd++ ) { + for( ii = 0; ii < halfHeight; ii++ ) { + for( jj = 0; jj < halfWidth; jj++ ) { + float totals[] = new float[4]; // 4 is max components + float extractTotals[][] = new float[BOX8][4]; + int cc; + + dataIn.position( src ); + extract.extract( isSwap, dataIn, extractTotals[0] ); + dataIn.position( src + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[1] ); + dataIn.position( src + rowSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[2] ); + dataIn.position( src + rowSizeInBytes + pixelSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[3] ); + dataIn.position( src + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[4] ); + dataIn.position( src + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[5] ); + dataIn.position( src + rowSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[6] ); + dataIn.position( src + rowSizeInBytes + pixelSizeInBytes + imageSizeInBytes ); + extract.extract( isSwap, dataIn, extractTotals[7] ); + + for( cc = 0; cc < components; cc++ ) { + int kk; + // grab 8 pixels to average + totals[cc] = 0.0f; + for( kk = 0; kk < BOX8; kk++ ) { + totals[cc] += extractTotals[kk][cc]; + } + totals[cc] /= (float)BOX8; + } + extract.shove( totals, outIndex, dataOut ); + outIndex++; + // skip over to next square of 4 + src += pixelSizeInBytes + pixelSizeInBytes; + } + // skip past pad bytes, if any, to get to next row + src += padBytes; + src += rowSizeInBytes; + } + src += imageSizeInBytes; + } + assert( src == rowSizeInBytes * height * depth ); + assert( outIndex == halfWidth * halfHeight * halfDepth ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java new file mode 100644 index 000000000..b2aaad2f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Image.java @@ -0,0 +1,1413 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Image { + + /** Creates a new instance of Image */ + public Image() { + } + + public static short getShortFromByteArray( byte[] array, int index ) { + short s; + s = (short)(array[index] << 8 ); + s |= (short)(0x00FF & array[index+1]); + return( s ); + } + + public static int getIntFromByteArray( byte[] array, int index ) { + int i; + i = ( array[index] << 24 ) & 0xFF000000; + i |= ( array[index+1] << 16 ) & 0x00FF0000; + i |= ( array[index+2] << 8 ) & 0x0000FF00; + i |= ( array[index+3] ) & 0x000000FF; + return( i ); + } + + public static float getFloatFromByteArray( byte[] array, int index ) { + int i = getIntFromByteArray( array, index ); + return( Float.intBitsToFloat(i) ); + } + + /* + * Extract array from user's data applying all pixel store modes. + * The internal format used is an array of unsigned shorts. + */ + public static void fill_image( PixelStorageModes psm, int width, int height, + int format, int type, boolean index_format, ByteBuffer userdata, + ShortBuffer newimage ) { + int components; + int element_size; + int rowsize; + int padding; + int groups_per_line; + int group_size; + int elements_per_line; + int start; + int iter = 0; + int iter2; + int i, j, k; + boolean myswap_bytes; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswap_bytes = psm.getUnpackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groups_per_line = psm.getUnpackRowLength(); + } else { + groups_per_line = width; + } + + // All formats except GL_BITMAP fall out trivially + if( type == GL2.GL_BITMAP ) { + int bit_offset; + int current_bit; + + rowsize = ( groups_per_line * components + 7 ) / 8; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + start = psm.getUnpackSkipRows() * rowsize + ( psm.getUnpackSkipPixels() * components / 8 ); + elements_per_line = width * components; + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + userdata.position( iter ); // **************************************** + bit_offset = (psm.getUnpackSkipPixels() * components) % 8; + for( j = 0; j < elements_per_line; j++ ) { + // retrieve bit + if( psm.getUnpackLsbFirst() ) { + userdata.position( iter ); + current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << bit_offset );//userdata[iter] & ( 1 << bit_offset ); + } else { + current_bit = ( userdata.get() & 0x000000FF ) & ( 1 << ( 7 - bit_offset ) ); + } + if( current_bit != 0 ) { + if( index_format ) { + newimage.position( iter2 ); + newimage.put( (short)1 ); + } else { + newimage.position( iter2 ); + newimage.put( (short)65535 ); + } + } else { + newimage.position( iter2 ); + newimage.put( (short)0 ); + } + bit_offset++; + if( bit_offset == 8 ) { + bit_offset = 0; + iter++; + } + iter2++; + } + start += rowsize; + } + } else { + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * components; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getUnpackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getUnpackAlignment() - padding; + } + start = psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size; + elements_per_line = width * components; + + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + userdata.position( iter ); //*************************************** + for( j = 0; j < elements_per_line; j++ ) { + Type_Widget widget = new Type_Widget(); + float[] extractComponents = new float[4]; + userdata.position( iter ); + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract.extract( false, userdata /*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract.extract( false, userdata /*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE ): + if( index_format ) { + newimage.put( iter2++, (short)( 0x000000FF & userdata.get() ) );//userdata[iter]; + } else { + newimage.put( iter2++, (short)( 0x000000FF & userdata.get()/*userdata[iter]*/ * 257 ) ); + } + break; + case( GL2.GL_BYTE ): + if( index_format ) { + newimage.put( iter2++, userdata.get() ); //userdata[iter]; + } else { + newimage.put( iter2++, (short)(userdata.get()/*userdata[iter]*/ * 516 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract.extract( myswap_bytes, userdata/*userdata[iter]*/, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 3; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)(extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( myswap_bytes ) { + widget.setUB1( userdata.get() ); + widget.setUB0( userdata.get() ); + } else { + widget.setUB0( userdata.get() ); + widget.setUB1( userdata.get() ); + } + if( type == GL2.GL_SHORT ) { + if( index_format ) { + newimage.put( iter2++, widget.getS0() ); + } else { + newimage.put( iter2++, (short)(widget.getS0() * 2) ); + } + } else { + newimage.put( iter2++, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract.extract( myswap_bytes, userdata, extractComponents ); + for( k = 0; k < 4; k++ ) { + newimage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( myswap_bytes ) { + widget.setUB3( userdata.get() ); + widget.setUB2( userdata.get() ); + widget.setUB1( userdata.get() ); + widget.setUB0( userdata.get() ); + } else { + widget.setUB0( userdata.get() ); + widget.setUB1( userdata.get() ); + widget.setUB2( userdata.get() ); + widget.setUB3( userdata.get() ); + } + if( type == GL2.GL_FLOAT ) { + if( index_format ) { + newimage.put( iter2++, (short)widget.getF() ); + } else { + newimage.put( iter2++, (short)(widget.getF() * 65535 ) ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( index_format ) { + newimage.put( iter2++, (short)( widget.getUI() ) ); + } else { + newimage.put( iter2++, (short)( widget.getUI() >> 16 ) ); + } + } else { + if( index_format ) { + newimage.put( iter2++, (short)( widget.getI() ) ); + } else { + newimage.put( iter2++, (short)( widget.getI() >> 15 ) ); + } + } + break; + } + iter += element_size; + } // for j + start += rowsize; + // want iter pointing at start, not within, row for assertion purposes + iter = start; + } // for i + + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == ( width * height * components ) ); + } else { + assert( iter2 == ( width * height * Mipmap.elements_per_group( format, 0 ) ) ); + } + assert( iter == ( rowsize * height + psm.getUnpackSkipRows() * rowsize + psm.getUnpackSkipPixels() * group_size ) ); + } + } + + /* + * Insert array into user's data applying all pixel store modes. + * Theinternal format is an array of unsigned shorts. + * empty_image() because it is the opposet of fill_image(). + */ + public static void empty_image( PixelStorageModes psm, int width, int height, + int format, int type, boolean index_format, + ShortBuffer oldimage, ByteBuffer userdata ) { + + int components; + int element_size; + int rowsize; + int padding; + int groups_per_line; + int group_size; + int elements_per_line; + int start; + int iter = 0; + int iter2; + int i, j, k; + boolean myswap_bytes; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswap_bytes = psm.getPackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getPackRowLength() > 0 ) { + groups_per_line = psm.getPackRowLength(); + } else { + groups_per_line = width; + } + + // all formats except GL_BITMAP fall out trivially + if( type == GL2.GL_BITMAP ) { + int bit_offset; + int current_bit; + + rowsize = ( groups_per_line * components + 7 ) / 8; + padding = ( rowsize % psm.getPackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getPackAlignment() - padding; + } + start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * components / 8; + elements_per_line = width * components; + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + bit_offset = ( psm.getPackSkipPixels() * components ) % 8; + for( j = 0; j < elements_per_line; j++ ) { + if( index_format ) { + current_bit = oldimage.get( iter2 ) & 1; + } else { + if( oldimage.get( iter2 ) < 0 ) { // must check for negative rather than 32767 + current_bit = 1; + } else { + current_bit = 0; + } + } + + if( current_bit != 0 ) { + if( psm.getPackLsbFirst() ) { + userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 1 << bit_offset ) ) ) ); + } else { + userdata.put( iter, (byte)( ( userdata.get( iter ) | ( 7 - bit_offset ) ) ) ); + } + } else { + if( psm.getPackLsbFirst() ) { + //userdata[iter] &= ~( 1 << bit_offset ); + userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 1 << bit_offset ) ) ) ); + } else { + //userdata[iter] &= ~( 1 << ( 7 - bit_offset ) ); + userdata.put( iter, (byte)( ( userdata.get( iter ) & ~( 7 - bit_offset ) ) ) ); + } + } + + bit_offset++; + if( bit_offset == 8 ) { + bit_offset = 0; + iter++; + } + iter2++; + } + start += rowsize; + } + } else { + float shoveComponents[] = new float[4]; + + element_size = Mipmap.bytes_per_element( type ); + group_size = element_size * components; + if( element_size == 1 ) { + myswap_bytes = false; + } + + rowsize = groups_per_line * group_size; + padding = ( rowsize % psm.getPackAlignment() ); + if( padding != 0 ) { + rowsize += psm.getPackAlignment() - padding; + } + start = psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size; + elements_per_line = width * components; + + iter2 = 0; + for( i = 0; i < height; i++ ) { + iter = start; + for( j = 0; j < elements_per_line; j++ ) { + Type_Widget widget = new Type_Widget(); + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userdata ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, userdata ); + break; + case( GL2.GL_UNSIGNED_BYTE ): + if( index_format ) { + //userdata[iter] = (byte)oldimage[iter2++]; + userdata.put( iter, (byte)oldimage.get(iter2++) ); + } else { + //userdata[iter] = (byte)( oldimage[iter2++] >> 8 ); + userdata.put( iter, (byte)( oldimage.get(iter2++) ) ); + } + break; + case( GL2.GL_BYTE ): + if( index_format ) { + //userdata[iter] = (byte)oldimage[iter2++]; + userdata.put( iter, (byte)oldimage.get(iter2++) ); + } else { + //userdata[iter] = (byte)( oldimage[iter2++] >> 9 ); + userdata.put( iter, (byte)( oldimage.get(iter2++) ) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1,widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get(iter2++) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter+1] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( type == GL2.GL_SHORT ) { + if( index_format ) { + widget.setS0( oldimage.get( iter2++ ) ); + } else { + widget.setS0( (short)(oldimage.get( iter2++ ) >> 1) ); + } + } else { + widget.setUS0( oldimage.get( iter2++ ) ); + } + if( myswap_bytes ) { + //userdata[iter] = widget.getUB1(); + //userdata[iter+1] = widget.getUB0(); + userdata.put( iter, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB0() ); + } else { + //userdata[iter] = widget.getUB0(); + //userdata[iter] = widget.getUB1(); + userdata.put( iter, widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 2, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldimage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswap_bytes ) { + //userdata[iter+3] = widget.getUB0(); + //userdata[iter+2] = widget.getUB1(); + //userdata[iter+1] = widget.getUB2(); + //userdata[iter ] = widget.getUB3(); + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( type == GL2.GL_FLOAT ) { + if( index_format ) { + widget.setF( oldimage.get( iter2++ ) ); + } else { + widget.setF( oldimage.get( iter2++ ) / 65535.0f ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( index_format ) { + widget.setUI( oldimage.get( iter2++ ) ); + } else { + widget.setUI( oldimage.get( iter2++ ) * 65537 ); + } + } else { + if( index_format ) { + widget.setI( oldimage.get( iter2++ ) ); + } else { + widget.setI( (oldimage.get( iter2++ ) * 65537) / 2 ); + } + } + if( myswap_bytes ) { + userdata.put( iter + 3, widget.getUB0() ); + userdata.put( iter + 2, widget.getUB1() ); + userdata.put( iter + 1, widget.getUB2() ); + userdata.put( iter , widget.getUB3() ); + } else { + userdata.put( iter , widget.getUB0() ); + userdata.put( iter + 1, widget.getUB1() ); + userdata.put( iter + 2, widget.getUB2() ); + userdata.put( iter + 3, widget.getUB3() ); + } + break; + } + iter += element_size; + } // for j + start += rowsize; + // want iter pointing at start, not within, row for assertion purposes + iter = start; + } // for i + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * components ); + } else { + assert( iter2 == width * height * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowsize * height + psm.getPackSkipRows() * rowsize + psm.getPackSkipPixels() * group_size ); + } + } + + public static void fillImage3D( PixelStorageModes psm, int width, int height, + int depth, int format, int type, boolean indexFormat, ByteBuffer userImage, + ShortBuffer newImage ) { + boolean myswapBytes; + int components; + int groupsPerLine; + int elementSize; + int groupSize; + int rowSize; + int padding; + int elementsPerLine; + int rowsPerImage; + int imageSize; + int start, rowStart; + int iter = 0; + int iter2 = 0; + int ww, hh, dd, k; + Type_Widget widget = new Type_Widget(); + float extractComponents[] = new float[4]; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + myswapBytes = psm.getUnpackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getUnpackRowLength() > 0 ) { + groupsPerLine = psm.getUnpackRowLength(); + } else { + groupsPerLine = width; + } + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * components; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff begin + if( psm.getUnpackImageHeight() > 0 ) { + rowsPerImage = psm.getUnpackImageHeight(); + } else { + rowsPerImage = height; + } + // 3dstuff end + + rowSize = groupsPerLine * groupSize; + padding = rowSize % psm.getUnpackAlignment(); + if( padding != 0 ) { + rowSize += psm.getUnpackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; // 3dstuff + + start = psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize; + elementsPerLine = width * components; + + iter2 = 0; + for( dd = 0; dd < depth; dd++ ) { + rowStart = start; + for( hh = 0; hh < height; hh++ ) { + iter = rowStart; + for( ww = 0; ww < elementsPerLine; ww++ ) { + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( indexFormat ) { + newImage.put( iter2++, (short)(0x000000FF & userImage.get( iter ) ) ); + } else { + newImage.put( iter2++, (short)((0x000000FF & userImage.get( iter ) ) * 257 ) ); + } + break; + case( GL2.GL_BYTE ): + if( indexFormat ) { + newImage.put( iter2++, userImage.get( iter ) ); + } else { + newImage.put( iter2++, (short)(userImage.get( iter ) * 516 ) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + userImage.position( iter ); + extract.extract( false, userImage, extractComponents ); + for( k = 0; k < 3; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + userImage.position( iter ); + extract.extract( false, userImage, extractComponents ); + for( k = 0; k < 3; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)(extractComponents[k] * 65535) ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( myswapBytes ) { + widget.setUB0( userImage.get( iter + 1 ) ); + widget.setUB1( userImage.get( iter ) ); + } else { + widget.setUB0( userImage.get( iter ) ); + widget.setUB1( userImage.get( iter + 1 ) ); + } + if( type == GL2.GL_SHORT ) { + if( indexFormat ) { + newImage.put( iter2++, widget.getUS0() ); + } else { + newImage.put( iter2++, (short)(widget.getUS0() * 2) ); + } + } else { + newImage.put( iter2++, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + userImage.position( iter ); + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract.extract( myswapBytes, userImage, extractComponents ); + for( k = 0; k < 4; k++ ) { + newImage.put( iter2++, (short)( extractComponents[k] * 65535 ) ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( myswapBytes ) { + widget.setUB0( userImage.get( iter + 3 ) ); + widget.setUB1( userImage.get( iter + 2 ) ); + widget.setUB2( userImage.get( iter + 1 ) ); + widget.setUB3( userImage.get( iter ) ); + } else { + widget.setUB0( userImage.get( iter ) ); + widget.setUB1( userImage.get( iter + 1 ) ); + widget.setUB2( userImage.get( iter + 2 ) ); + widget.setUB3( userImage.get( iter + 3 ) ); + } + if( type == GL2.GL_FLOAT ) { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getF() ); + } else { + newImage.put( iter2++, (short)( widget.getF() * 65535.0f ) ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getUI() ); + } else { + newImage.put( iter2++, (short)(widget.getUI() >> 16) ); + } + } else { + if( indexFormat ) { + newImage.put( iter2++, (short)widget.getI() ); + } else { + newImage.put( iter2++, (short)(widget.getI() >> 15) ); + } + } + break; + default: + assert( false ); + } + iter += elementSize; + } // for ww + rowStart += rowSize; + iter = rowStart; // for assert + } // for hh + start += imageSize; + }// for dd + + // iterators should be one byte past end + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * depth * components ); + } else { + assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowSize * height * depth + psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize ); + } + + public static void emptyImage3D( PixelStorageModes psm, int width, int height, int depth, + int format, int type, boolean indexFormat, ShortBuffer oldImage, ByteBuffer userImage ) { + boolean myswapBytes; + int components; + int groupsPerLine; + int elementSize; + int groupSize; + int rowSize; + int padding; + int start, rowStart, iter; + int elementsPerLine; + int iter2; + int ii, jj, dd, k; + int rowsPerImage; + int imageSize; + Type_Widget widget = new Type_Widget(); + float[] shoveComponents = new float[4]; + + // Create a Extract interface object + Extract extract = null; + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + extract = new Extract332(); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + extract = new Extract233rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + extract = new Extract565(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + extract = new Extract565rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + extract = new Extract4444(); + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + extract = new Extract4444rev(); + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + extract = new Extract5551(); + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + extract = new Extract1555rev(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + extract = new Extract8888(); + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + extract = new Extract8888rev(); + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + extract = new Extract1010102(); + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + extract = new Extract2101010rev(); + break; + } + + iter = 0; + + myswapBytes = psm.getPackSwapBytes(); + components = Mipmap.elements_per_group( format, type ); + if( psm.getPackRowLength() > 0 ) { + groupsPerLine = psm.getPackRowLength(); + } else { + groupsPerLine = width; + } + + elementSize = Mipmap.bytes_per_element( type ); + groupSize = elementSize * components; + if( elementSize == 1 ) { + myswapBytes = false; + } + + // 3dstuff begin + if( psm.getPackImageHeight() > 0 ) { + rowsPerImage = psm.getPackImageHeight(); + } else { + rowsPerImage = height; + } + + // 3dstuff end + + rowSize = groupsPerLine * groupSize; + padding = rowSize % psm.getPackAlignment(); + if( padding != 0 ) { + rowSize += psm.getPackAlignment() - padding; + } + + imageSize = rowsPerImage * rowSize; + + start = psm.getPackSkipRows() * rowSize + + psm.getPackSkipPixels() * groupSize + + psm.getPackSkipImages() * imageSize; + elementsPerLine = width * components; + + iter2 = 0; + for( dd = 0; dd < depth; dd++ ) { + rowStart = start; + + for( ii = 0; ii < height; ii++ ) { + iter = rowStart; + + for( jj = 0; jj < elementsPerLine; jj++ ) { + + switch( type ) { + case( GL2.GL_UNSIGNED_BYTE ): + if( indexFormat ) { + userImage.put( iter, (byte)(oldImage.get( iter2++ ) ) ); + } else { + userImage.put( iter, (byte)(oldImage.get( iter2++ ) >> 8 ) ); + } + break; + case( GL2.GL_BYTE ): + if( indexFormat ) { + userImage.put( iter, (byte)(oldImage.get(iter2++) ) ); + } else { + userImage.put( iter, (byte)(oldImage.get(iter2++) >> 9) ); + } + break; + case( GL2.GL_UNSIGNED_BYTE_3_3_2 ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userImage ); + break; + case( GL2.GL_UNSIGNED_BYTE_2_3_3_REV ): + for( k = 0; k < 3; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, userImage ); + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.putShort( iter, widget.getUB1() ); + userImage.putShort( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_6_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_5_5_5_1 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.putShort( iter, widget.getUS0() ); + } + break; + case( GL2.GL_UNSIGNED_SHORT ): + case( GL2.GL_SHORT ): + if( type == GL2.GL_SHORT ) { + if( indexFormat ) { + widget.setS0( (short)oldImage.get( iter2++ ) ); + } else { + widget.setS0( (short)(oldImage.get( iter2++ ) >> 1) ); + } + } else { + widget.setUS0( (short)oldImage.get( iter2++ ) ); + } + if( myswapBytes ) { + userImage.put( iter, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB0() ); + } else { + userImage.put( iter, widget.getUB0() ); + userImage.put( iter + 1, widget.getUB1() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_8_8_8_8_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_10_10_10_2 ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter ,widget.getUB3() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_UNSIGNED_INT_2_10_10_10_REV ): + for( k = 0; k < 4; k++ ) { + shoveComponents[k] = oldImage.get( iter2++ ) / 65535.0f; + } + extract.shove( shoveComponents, 0, widget.getBuffer() ); + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB2() ); + userImage.put( iter + 1, widget.getUB1() ); + userImage.put( iter , widget.getUB0() ); + } else { + userImage.putInt( iter, widget.getUI() ); + } + break; + case( GL2.GL_INT ): + case( GL2.GL_UNSIGNED_INT ): + case( GL2.GL_FLOAT ): + if( type == GL2.GL_FLOAT ) { + if( indexFormat ) { + widget.setF( oldImage.get( iter2++ ) ); + } else { + widget.setF( oldImage.get( iter2++ ) / 65535.0f ); + } + } else if( type == GL2.GL_UNSIGNED_INT ) { + if( indexFormat ) { + widget.setUI( oldImage.get( iter2++ ) ); + } else { + widget.setUI( oldImage.get( iter2++ ) * 65537 ); + } + } else { + if( indexFormat ) { + widget.setI( oldImage.get( iter2++ ) ); + } else { + widget.setI( ( oldImage.get( iter2++ ) * 65535 ) / 2 ); + } + } + if( myswapBytes ) { + userImage.put( iter + 3, widget.getUB0() ); + userImage.put( iter + 2, widget.getUB1() ); + userImage.put( iter + 1, widget.getUB2() ); + userImage.put( iter , widget.getUB3() ); + } else { + userImage.put( iter , widget.getUB0() ); + userImage.put( iter + 1, widget.getUB1() ); + userImage.put( iter + 2, widget.getUB2() ); + userImage.put( iter + 3, widget.getUB3() ); + } + break; + default: + assert( false ); + } + + iter += elementSize; + } // for jj + rowStart += rowSize; + } // for ii + start += imageSize; + } // for dd + + if( !Mipmap.isTypePackedPixel( type ) ) { + assert( iter2 == width * height * depth * components ); + } else { + assert( iter2 == width * height * depth * Mipmap.elements_per_group( format, 0 ) ); + } + assert( iter == rowSize * height * depth + + psm.getUnpackSkipRows() * rowSize + + psm.getUnpackSkipPixels() * groupSize + + psm.getUnpackSkipImages() * imageSize ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java new file mode 100644 index 000000000..1c0707c57 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Mipmap.java @@ -0,0 +1,868 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.glu.GLU; +import javax.media.opengl.GLException; +import java.nio.*; +import com.jogamp.opengl.impl.InternalBufferUtil; + +/** + * + * @author Administrator + */ +public class Mipmap { + + /** Creates a new instance of Mipmap */ + public Mipmap() { + } + + public static int computeLog( int value ) { + int i = 0; + // Error + if( value == 0 ) { + return( -1 ); + } + for( ;; ) { + if( (value & 1) >= 1 ) { + if( value != 1 ) { + return( -1 ); + } + return( i ); + } + value = value >> 1; + i++; + } + } + + /* Compute the nearest power of 2 number. This algorithm is a little strange + * but it works quite well. + */ + public static int nearestPower( int value ) { + int i = 1; + // Error! + if( value == 0 ) { + return( -1 ); + } + for( ;; ) { + if( value == 1 ) { + return( i ); + } else if( value == 3 ) { + return( i * 4 ); + } + value = value >> 1; + i *= 2; + } + } + + public static short GLU_SWAP_2_BYTES( short s ) { + byte b = 0; + b = (byte)( s >>> 8 ); + s = (short)( s << 8 ); + s = (short)( s | (0x00FF & b) ); + return( s ); + } + + public static int GLU_SWAP_4_BYTES( int i ) { + int t = i << 24; + t |= 0x00FF0000 & ( i << 8 ); + t |= 0x0000FF00 & ( i >>> 8 ); + t |= 0x000000FF & ( i >>> 24 ); + return( t ); + } + + public static float GLU_SWAP_4_BYTES( float f ) { + int i = Float.floatToRawIntBits( f ); + float temp = Float.intBitsToFloat( i ); + return( temp ); + } + + public static int checkMipmapArgs( int internalFormat, int format, int type ) { + if( !legalFormat( format ) || !legalType( type ) ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( format == GL2GL3.GL_STENCIL_INDEX ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( !isLegalFormatForPackedPixelType( format, type ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + return( 0 ); + } + + public static boolean legalFormat( int format ) { + switch( format ) { + case( GL2.GL_COLOR_INDEX ): + case( GL2GL3.GL_STENCIL_INDEX ): + case( GL2GL3.GL_DEPTH_COMPONENT ): + case( GL2GL3.GL_RED ): + case( GL2GL3.GL_GREEN ): + case( GL2GL3.GL_BLUE ): + case( GL2GL3.GL_ALPHA ): + case( GL2GL3.GL_RGB ): + case( GL2GL3.GL_RGBA ): + case( GL2GL3.GL_LUMINANCE ): + case( GL2GL3.GL_LUMINANCE_ALPHA ): + case( GL2GL3.GL_BGR ): + case( GL2GL3.GL_BGRA ): + return( true ); + default: + return( false ); + } + } + + public static boolean legalType( int type ) { + switch( type ) { + case( GL2.GL_BITMAP ): + case( GL2GL3.GL_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE ): + case( GL2GL3.GL_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT ): + case( GL2GL3.GL_INT ): + case( GL2GL3.GL_UNSIGNED_INT ): + case( GL2GL3.GL_FLOAT ): + case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ): + return( true ); + default: + return( false ); + } + } + + public static boolean isTypePackedPixel( int type ) { + assert( legalType( type ) ); + + if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || + type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) { + return( true ); + } + return( false ); + } + + public static boolean isLegalFormatForPackedPixelType( int format, int type ) { + // if not a packed pixel type then return true + if( isTypePackedPixel( type ) ) { + return( true ); + } + + // 3_3_2/2_3_3_REV & 5_6_5/5_6_5_REV are only compatible with RGB + if( (type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ) + & format != GL2GL3.GL_RGB ) { + return( false ); + } + + // 4_4_4_4/4_4_4_4_REV & 5_5_5_1/1_5_5_5_REV & 8_8_8_8/8_8_8_8_REV & + // 10_10_10_2/2_10_10_10_REV are only campatible with RGBA, BGRA & ARGB_EXT + if( ( type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) && + (format != GL2GL3.GL_RGBA && format != GL2GL3.GL_BGRA) ) { + return( false ); + } + return( true ); + } + + public static boolean isLegalLevels( int userLevel, int baseLevel, int maxLevel, + int totalLevels ) { + if( (baseLevel < 0) || (baseLevel < userLevel) || (maxLevel < baseLevel) || + (totalLevels < maxLevel) ) { + return( false ); + } + return( true ); + } + + /* Given user requested textures size, determine if it fits. If it doesn't then + * halve both sides and make the determination again until it does fit ( for + * IR only ). + * Note that proxy textures are not implemented in RE* even though they + * advertise the texture extension. + * Note that proxy textures are implemented but not according to spec in IMPACT* + */ + public static void closestFit( GL gl, int target, int width, int height, int internalFormat, + int format, int type, int[] newWidth, int[] newHeight ) { + // Use proxy textures if OpenGL version >= 1.1 + if( Double.parseDouble( gl.glGetString( GL.GL_VERSION ).trim().substring( 0, 3 ) ) >= 1.1 ) { + int widthPowerOf2 = nearestPower( width ); + int heightPowerOf2 = nearestPower( height ); + int[] proxyWidth = new int[1]; + boolean noProxyTextures = false; + + // Some drivers (in particular, ATI's) seem to set a GL error + // when proxy textures are used even though this is in violation + // of the spec. Guard against this and interactions with the + // DebugGL by watching for GLException. + try { + do { + // compute level 1 width & height, clamping each at 1 + int widthAtLevelOne = ( ( width > 1 ) ? (widthPowerOf2 >> 1) : widthPowerOf2 ); + int heightAtLevelOne = ( ( height > 1 ) ? (heightPowerOf2 >> 1) : heightPowerOf2 ); + int proxyTarget; + + assert( widthAtLevelOne > 0 ); + assert( heightAtLevelOne > 0 ); + + // does width x height at level 1 & all their mipmaps fit? + if( target == GL2GL3.GL_TEXTURE_2D || target == GL2GL3.GL_PROXY_TEXTURE_2D ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_2D; + gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, 0, format, type, null ); + } else if( (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_X) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_X) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Y) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_POSITIVE_Z) || + (target == GL2GL3.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_CUBE_MAP; + gl.glTexImage2D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, 0, format, type, null ); + } else { + assert( target == GL2GL3.GL_TEXTURE_1D || target == GL2GL3.GL_PROXY_TEXTURE_1D ); + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_1D; + gl.getGL2GL3().glTexImage1D( proxyTarget, 1, internalFormat, widthAtLevelOne, + 0, format, type, null ); + } + if(gl.isGL2GL3()) { + gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 ); + } else { + proxyWidth[0] = 0; + } + // does it fit? + if( proxyWidth[0] == 0 ) { // nope, so try again with theses sizes + if( widthPowerOf2 == 1 && heightPowerOf2 == 1 ) { + /* A 1x1 texture couldn't fit for some reason so break out. This + * should never happen. But things happen. The disadvantage with + * this if-statement is that we will never be aware of when this + * happens since it will silently branch out. + */ + noProxyTextures = true; + break; + } + widthPowerOf2 = widthAtLevelOne; + heightPowerOf2 = heightAtLevelOne; + } + // else it does fit + } while( proxyWidth[0] == 0 ); + } catch (GLException e) { + noProxyTextures = true; + } + // loop must terminate + // return the width & height at level 0 that fits + if( !noProxyTextures ) { + newWidth[0] = widthPowerOf2; + newHeight[0] = heightPowerOf2; + return; + } + } + int[] maxsize = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_MAX_TEXTURE_SIZE, maxsize , 0); + // clamp user's texture sizes to maximum sizes, if necessary + newWidth[0] = nearestPower( width ); + if( newWidth[0] > maxsize[0] ) { + newWidth[0] = maxsize[0]; + } + newHeight[0] = nearestPower( height ); + if( newHeight[0] > maxsize[0] ) { + newHeight[0] = maxsize[0]; + } + } + + public static void closestFit3D( GL gl, int target, int width, int height, int depth, + int internalFormat, int format, int type, int[] newWidth, int[] newHeight, + int[] newDepth ) { + int widthPowerOf2 = nearestPower( width ); + int heightPowerOf2 = nearestPower( height ); + int depthPowerOf2 = nearestPower( depth ); + int[] proxyWidth = new int[1]; + + do { + // compute level 1 width & height & depth, clamping each at 1 + int widthAtLevelOne = (widthPowerOf2 > 1) ? widthPowerOf2 >> 1 : widthPowerOf2; + int heightAtLevelOne = (heightPowerOf2 > 1) ? heightPowerOf2 >> 1 : heightPowerOf2; + int depthAtLevelOne = (depthPowerOf2 > 1) ? depthPowerOf2 >> 1 : depthPowerOf2; + int proxyTarget = 0; + assert( widthAtLevelOne > 0 ); + assert( heightAtLevelOne > 0 ); + assert( depthAtLevelOne > 0 ); + + // does width x height x depth at level 1 & all their mipmaps fit? + if( target == GL2GL3.GL_TEXTURE_3D || target == GL2GL3.GL_PROXY_TEXTURE_3D ) { + proxyTarget = GL2GL3.GL_PROXY_TEXTURE_3D; + gl.getGL2GL3().glTexImage3D( proxyTarget, 1, internalFormat, widthAtLevelOne, + heightAtLevelOne, depthAtLevelOne, 0, format, type, null ); + } + if(gl.isGL2GL3()) { + gl.getGL2GL3().glGetTexLevelParameteriv( proxyTarget, 1, GL2GL3.GL_TEXTURE_WIDTH, proxyWidth, 0 ); + } else { + proxyWidth[0] = 0; + } + // does it fit + if( proxyWidth[0] == 0 ) { + if( widthPowerOf2 == 1 && heightPowerOf2 == 1 && depthPowerOf2 == 1 ) { + newWidth[0] = newHeight[0] = newDepth[0] = 1; + return; + } + widthPowerOf2 = widthAtLevelOne; + heightPowerOf2 = heightAtLevelOne; + depthPowerOf2 = depthAtLevelOne; + } + } while( proxyWidth[0] == 0 ); + // loop must terminate + + // return the width & height at level 0 that fits + newWidth[0] = widthPowerOf2; + newHeight[0] = heightPowerOf2; + newDepth[0] = depthPowerOf2; + } + + public static int elements_per_group( int format, int type ) { + // Return the number of elements per grtoup of a specified gromat + + // If the type is packedpixels then answer is 1 + if( type == GL2GL3.GL_UNSIGNED_BYTE_3_3_2 || + type == GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5 || + type == GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 || + type == GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 || + type == GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8 || + type == GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV || + type == GL2GL3.GL_UNSIGNED_INT_10_10_10_2 || + type == GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ) { + return( 1 ); + } + + // Types are not packed pixels so get elements per group + switch( format ) { + case( GL2GL3.GL_RGB ): + case( GL2GL3.GL_BGR ): + return( 3 ); + case( GL2GL3.GL_LUMINANCE_ALPHA ): + return( 2 ); + case( GL2GL3.GL_RGBA ): + case( GL2GL3.GL_BGRA ): + return( 4 ); + default: + return( 1 ); + } + } + + public static int bytes_per_element( int type ) { + // return the number of bytes per element, based on the element type + + switch( type ) { + case( GL2.GL_BITMAP ): + case( GL2GL3.GL_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE ): + case( GL2GL3.GL_UNSIGNED_BYTE_3_3_2 ): + case( GL2GL3.GL_UNSIGNED_BYTE_2_3_3_REV ): + return( 1 ); + case( GL2GL3.GL_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5 ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_6_5_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4 ): + case( GL2GL3.GL_UNSIGNED_SHORT_4_4_4_4_REV ): + case( GL2GL3.GL_UNSIGNED_SHORT_5_5_5_1 ): + case( GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV ): + return( 2 ); + case( GL2GL3.GL_INT ): + case( GL2GL3.GL_UNSIGNED_INT ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8 ): + case( GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV ): + case( GL2GL3.GL_UNSIGNED_INT_10_10_10_2 ): + case( GL2GL3.GL_UNSIGNED_INT_2_10_10_10_REV ): + case( GL2GL3.GL_FLOAT ): + return( 4 ); + default: + return( 4 ); + } + } + + public static boolean is_index( int format ) { + return( format == GL2.GL_COLOR_INDEX || format == GL2GL3.GL_STENCIL_INDEX ); + } + + /* Compute memory required for internal packed array of data of given type and format. */ + + public static int image_size( int width, int height, int format, int type ) { + int bytes_per_row; + int components; + + assert( width > 0 ); + assert( height > 0 ); + components = elements_per_group( format, type ); + if( type == GL2.GL_BITMAP ) { + bytes_per_row = (width + 7) / 8; + } else { + bytes_per_row = bytes_per_element( type ) * width; + } + return( bytes_per_row * height * components ); + } + + public static int imageSize3D( int width, int height, int depth, int format, int type ) { + int components = elements_per_group( format, type ); + int bytes_per_row = bytes_per_element( type ) * width; + + assert( width > 0 && height > 0 && depth > 0 ); + assert( type != GL2.GL_BITMAP ); + + return( bytes_per_row * height * depth * components ); + } + + public static void retrieveStoreModes( GL gl, PixelStorageModes psm ) { + int[] a = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0); + psm.setUnpackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0); + psm.setUnpackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0); + psm.setUnpackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0); + psm.setUnpackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0); + psm.setUnpackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0); + psm.setUnpackSwapBytes( ( a[0] == 1 ) ); + + gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0); + psm.setPackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0); + psm.setPackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0); + psm.setPackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0); + psm.setPackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0); + psm.setPackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0); + psm.setPackSwapBytes( ( a[0] == 1 ) ); + } + + public static void retrieveStoreModes3D( GL gl, PixelStorageModes psm ) { + int[] a = new int[1]; + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ALIGNMENT, a, 0); + psm.setUnpackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_ROW_LENGTH, a, 0); + psm.setUnpackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_ROWS, a, 0); + psm.setUnpackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_PIXELS, a, 0); + psm.setUnpackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_LSB_FIRST, a, 0); + psm.setUnpackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SWAP_BYTES, a, 0); + psm.setUnpackSwapBytes( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_SKIP_IMAGES, a, 0); + psm.setUnpackSkipImages( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_UNPACK_IMAGE_HEIGHT, a, 0); + psm.setUnpackImageHeight( a[0] ); + + gl.glGetIntegerv( GL2GL3.GL_PACK_ALIGNMENT, a, 0); + psm.setPackAlignment( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_ROW_LENGTH, a, 0); + psm.setPackRowLength( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_ROWS, a, 0); + psm.setPackSkipRows( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_PIXELS, a, 0 ); + psm.setPackSkipPixels( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_LSB_FIRST, a, 0 ); + psm.setPackLsbFirst( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SWAP_BYTES, a, 0 ); + psm.setPackSwapBytes( ( a[0] == 1 ) ); + gl.glGetIntegerv( GL2GL3.GL_PACK_SKIP_IMAGES, a, 0 ); + psm.setPackSkipImages( a[0] ); + gl.glGetIntegerv( GL2GL3.GL_PACK_IMAGE_HEIGHT, a, 0 ); + psm.setPackImageHeight( a[0] ); + } + + public static int gluScaleImage( GL gl, int format, int widthin, int heightin, + int typein, ByteBuffer datain, int widthout, int heightout, + int typeout, ByteBuffer dataout ) { + int datainPos = datain.position(); + int dataoutPos = dataout.position(); + try { + + int components; + ByteBuffer beforeimage; + ByteBuffer afterimage; + PixelStorageModes psm = new PixelStorageModes(); + + if( (widthin == 0) || (heightin == 0) || (widthout == 0) || (heightout == 0) ) { + return( 0 ); + } + if( (widthin < 0) || (heightin < 0) || (widthout < 0) || (heightout < 0) ) { + return( GLU.GLU_INVALID_VALUE ); + } + if( !legalFormat( format ) || !legalType( typein ) || !legalType( typeout ) ) { + return( GLU.GLU_INVALID_ENUM ); + } + if( !isLegalFormatForPackedPixelType( format, typein ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + if( !isLegalFormatForPackedPixelType( format, typeout ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + beforeimage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( image_size( widthin, heightin, format, GL2GL3.GL_UNSIGNED_SHORT ) )); + afterimage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( image_size( widthout, heightout, format, GL2GL3.GL_UNSIGNED_SHORT ) )); + if( beforeimage == null || afterimage == null ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + + retrieveStoreModes( gl, psm ); + Image.fill_image( psm, widthin, heightin, format, typein, is_index( format ), datain, beforeimage.asShortBuffer() ); + components = elements_per_group( format, 0 ); + ScaleInternal.scale_internal( components, widthin, heightin, beforeimage.asShortBuffer(), widthout, heightout, afterimage.asShortBuffer() ); + Image.empty_image( psm, widthout, heightout, format, typeout, is_index( format ), afterimage.asShortBuffer(), dataout ); + + return( 0 ); + } finally { + datain.position(datainPos); + dataout.position(dataoutPos); + } + } + + public static int gluBuild1DMipmapLevels( GL gl, int target, int internalFormat, + int width, int format, int type, int userLevel, int baseLevel, + int maxLevel, ByteBuffer data ) { + int dataPos = data.position(); + try { + + int levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + levels = computeLog( width ); + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, width, + width, format, type, userLevel, baseLevel, maxLevel, data ) ); + } finally { + data.position(dataPos); + } + } + + public static int gluBuild1DMipmaps( GL gl, int target, int internalFormat, int width, + int format, int type, ByteBuffer data ) { + int dataPos = data.position(); + + try { + int[] widthPowerOf2 = new int[1]; + int levels; + int[] dummy = new int[1]; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + closestFit( gl, target, width, 1, internalFormat, format, type, widthPowerOf2, dummy ); + levels = computeLog( widthPowerOf2[0] ); + + return( BuildMipmap.gluBuild1DMipmapLevelsCore( gl, target, internalFormat, + width, widthPowerOf2[0], format, type, 0, 0, levels, data ) ); + } finally { + data.position(dataPos); + } + } + + + public static int gluBuild2DMipmapLevels( GL gl, int target, int internalFormat, + int width, int height, int format, int type, int userLevel, + int baseLevel, int maxLevel, Object data ) { + int dataPos = 0; + + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + levels = computeLog( width ); + level = computeLog( height ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data ); + ByteBuffer buffer = null; + if( data instanceof ByteBuffer ) { + buffer = (ByteBuffer)data; + dataPos = buffer.position(); + } else if( data instanceof byte[] ) { + byte[] array = (byte[])data; + buffer = ByteBuffer.allocateDirect(array.length); + buffer.put(array); + } else if( data instanceof short[] ) { + short[] array = (short[])data; + buffer = ByteBuffer.allocateDirect( array.length * 2 ); + ShortBuffer sb = buffer.asShortBuffer(); + sb.put( array ); + } else if( data instanceof int[] ) { + int[] array = (int[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + IntBuffer ib = buffer.asIntBuffer(); + ib.put( array ); + } else if( data instanceof float[] ) { + float[] array = (float[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + FloatBuffer fb = buffer.asFloatBuffer(); + fb.put( array ); + } + + try { + return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat, + width, height, width, height, format, type, userLevel, baseLevel, + maxLevel, buffer ) ); + } finally { + buffer.position(dataPos); + } + } + + + public static int gluBuild2DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int format, int type, Object data ) { + int dataPos = 0; + + int[] widthPowerOf2 = new int[1]; + int[] heightPowerOf2 = new int[1]; + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + closestFit( gl, target, width, height, internalFormat, format, type, + widthPowerOf2, heightPowerOf2 ); + + levels = computeLog( widthPowerOf2[0] ); + level = computeLog( heightPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + + //PointerWrapper pointer = PointerWrapperFactory.getPointerWrapper( data ); + ByteBuffer buffer = null; + if( data instanceof ByteBuffer ) { + buffer = (ByteBuffer)data; + dataPos = buffer.position(); + } else if( data instanceof byte[] ) { + byte[] array = (byte[])data; + buffer = ByteBuffer.allocateDirect(array.length); + buffer.put(array); + } else if( data instanceof short[] ) { + short[] array = (short[])data; + buffer = ByteBuffer.allocateDirect( array.length * 2 ); + ShortBuffer sb = buffer.asShortBuffer(); + sb.put( array ); + } else if( data instanceof int[] ) { + int[] array = (int[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + IntBuffer ib = buffer.asIntBuffer(); + ib.put( array ); + } else if( data instanceof float[] ) { + float[] array = (float[])data; + buffer = ByteBuffer.allocateDirect( array.length * 4 ); + FloatBuffer fb = buffer.asFloatBuffer(); + fb.put( array ); + } + + try { + return( BuildMipmap.gluBuild2DMipmapLevelsCore( gl, target, internalFormat, + width, height, widthPowerOf2[0], heightPowerOf2[0], format, type, 0, + 0, levels, buffer ) ); + } finally { + buffer.position(dataPos); + } + } + + + public static int gluBuild3DMipmaps( GL gl, int target, int internalFormat, + int width, int height, int depth, int format, int type, ByteBuffer data ) { + int dataPos = data.position(); + try { + + int[] widthPowerOf2 = new int[1]; + int[] heightPowerOf2 = new int[1]; + int[] depthPowerOf2 = new int[1]; + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 || depth < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( type == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + closestFit3D( gl, target, width, height, depth, internalFormat, format, + type, widthPowerOf2, heightPowerOf2, depthPowerOf2 ); + + levels = computeLog( widthPowerOf2[0] ); + level = computeLog( heightPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + level = computeLog( depthPowerOf2[0] ); + if( level > levels ) { + levels = level; + } + + return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width, + height, depth, widthPowerOf2[0], heightPowerOf2[0], depthPowerOf2[0], + format, type, 0, 0, levels, data ) ); + } finally { + data.position(dataPos); + } + } + + public static int gluBuild3DMipmapLevels( GL gl, int target, int internalFormat, + int width, int height, int depth, int format, int type, int userLevel, + int baseLevel, int maxLevel, ByteBuffer data ) { + int dataPos = data.position(); + try { + int level, levels; + + int rc = checkMipmapArgs( internalFormat, format, type ); + if( rc != 0 ) { + return( rc ); + } + + if( width < 1 || height < 1 || depth < 1 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( type == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + levels = computeLog( width ); + level = computeLog( height ); + if( level > levels ) { + levels = level; + } + level = computeLog( depth ); + if( level > levels ) { + levels = level; + } + + levels += userLevel; + if( !isLegalLevels( userLevel, baseLevel, maxLevel, levels ) ) { + return( GLU.GLU_INVALID_VALUE ); + } + + return( BuildMipmap.gluBuild3DMipmapLevelsCore( gl, target, internalFormat, width, + height, depth, width, height, depth, format, type, userLevel, + baseLevel, maxLevel, data ) ); + } finally { + data.position(dataPos); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java new file mode 100644 index 000000000..43b5c5691 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/PixelStorageModes.java @@ -0,0 +1,426 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +/** + * + * @author Administrator + */ +public class PixelStorageModes { + + /** + * Holds value of property packAlignment. + */ + private int packAlignment; + + /** + * Holds value of property packRowLength. + */ + private int packRowLength; + + /** + * Holds value of property packSkipRows. + */ + private int packSkipRows; + + /** + * Holds value of property packSkipPixels. + */ + private int packSkipPixels; + + /** + * Holds value of property packLsbFirst. + */ + private boolean packLsbFirst; + + /** + * Holds value of property packSwapBytes. + */ + private boolean packSwapBytes; + + /** + * Holds value of property packSkipImages. + */ + private int packSkipImages; + + /** + * Holds value of property packImageHeight. + */ + private int packImageHeight; + + /** + * Holds value of property unpackAlignment. + */ + private int unpackAlignment; + + /** + * Holds value of property unpackRowLength. + */ + private int unpackRowLength; + + /** + * Holds value of property unpackSkipRows. + */ + private int unpackSkipRows; + + /** + * Holds value of property unpackSkipPixels. + */ + private int unpackSkipPixels; + + /** + * Holds value of property unpackLsbFirst. + */ + private boolean unpackLsbFirst; + + /** + * Holds value of property unpackSwapBytes. + */ + private boolean unpackSwapBytes; + + /** + * Holds value of property unpackSkipImages. + */ + private int unpackSkipImages; + + /** + * Holds value of property unpackImageHeight. + */ + private int unpackImageHeight; + + /** Creates a new instance of PixelStorageModes */ + public PixelStorageModes() { + } + + /** + * Getter for property packAlignment. + * @return Value of property packAlignment. + */ + public int getPackAlignment() { + + return this.packAlignment; + } + + /** + * Setter for property packAlignment. + * @param packAlignment New value of property packAlignment. + */ + public void setPackAlignment(int packAlignment) { + + this.packAlignment = packAlignment; + } + + /** + * Getter for property packRowLength. + * @return Value of property packRowLength. + */ + public int getPackRowLength() { + + return this.packRowLength; + } + + /** + * Setter for property packRowLength. + * @param packRowLength New value of property packRowLength. + */ + public void setPackRowLength(int packRowLength) { + + this.packRowLength = packRowLength; + } + + /** + * Getter for property packSkipRows. + * @return Value of property packSkipRows. + */ + public int getPackSkipRows() { + + return this.packSkipRows; + } + + /** + * Setter for property packSkipRows. + * @param packSkipRows New value of property packSkipRows. + */ + public void setPackSkipRows(int packSkipRows) { + + this.packSkipRows = packSkipRows; + } + + /** + * Getter for property packSkipPixels. + * @return Value of property packSkipPixels. + */ + public int getPackSkipPixels() { + + return this.packSkipPixels; + } + + /** + * Setter for property packSkipPixels. + * @param packSkipPixels New value of property packSkipPixels. + */ + public void setPackSkipPixels(int packSkipPixels) { + + this.packSkipPixels = packSkipPixels; + } + + /** + * Getter for property packLsbFirst. + * @return Value of property packLsbFirst. + */ + public boolean getPackLsbFirst() { + + return this.packLsbFirst; + } + + /** + * Setter for property packLsbFirst. + * @param packLsbFirst New value of property packLsbFirst. + */ + public void setPackLsbFirst(boolean packLsbFirst) { + + this.packLsbFirst = packLsbFirst; + } + + /** + * Getter for property packSwapBytes. + * @return Value of property packSwapBytes. + */ + public boolean getPackSwapBytes() { + + return this.packSwapBytes; + } + + /** + * Setter for property packSwapBytes. + * @param packSwapBytes New value of property packSwapBytes. + */ + public void setPackSwapBytes(boolean packSwapBytes) { + + this.packSwapBytes = packSwapBytes; + } + + /** + * Getter for property packSkipImages. + * @return Value of property packSkipImages. + */ + public int getPackSkipImages() { + + return this.packSkipImages; + } + + /** + * Setter for property packSkipImages. + * @param packSkipImages New value of property packSkipImages. + */ + public void setPackSkipImages(int packSkipImages) { + + this.packSkipImages = packSkipImages; + } + + /** + * Getter for property packImageHeight. + * @return Value of property packImageHeight. + */ + public int getPackImageHeight() { + + return this.packImageHeight; + } + + /** + * Setter for property packImageHeight. + * @param packImageHeight New value of property packImageHeight. + */ + public void setPackImageHeight(int packImageHeight) { + + this.packImageHeight = packImageHeight; + } + + /** + * Getter for property unpackAlignment. + * @return Value of property unpackAlignment. + */ + public int getUnpackAlignment() { + + return this.unpackAlignment; + } + + /** + * Setter for property unpackAlignment. + * @param unpackAlignment New value of property unpackAlignment. + */ + public void setUnpackAlignment(int unpackAlignment) { + + this.unpackAlignment = unpackAlignment; + } + + /** + * Getter for property unpackRowLength. + * @return Value of property unpackRowLength. + */ + public int getUnpackRowLength() { + + return this.unpackRowLength; + } + + /** + * Setter for property unpackRowLength. + * @param unpackRowLength New value of property unpackRowLength. + */ + public void setUnpackRowLength(int unpackRowLength) { + + this.unpackRowLength = unpackRowLength; + } + + /** + * Getter for property unpackSkipRows. + * @return Value of property unpackSkipRows. + */ + public int getUnpackSkipRows() { + + return this.unpackSkipRows; + } + + /** + * Setter for property unpackSkipRows. + * @param unpackSkipRows New value of property unpackSkipRows. + */ + public void setUnpackSkipRows(int unpackSkipRows) { + + this.unpackSkipRows = unpackSkipRows; + } + + /** + * Getter for property unpackSkipPixels. + * @return Value of property unpackSkipPixels. + */ + public int getUnpackSkipPixels() { + + return this.unpackSkipPixels; + } + + /** + * Setter for property unpackSkipPixels. + * @param unpackSkipPixels New value of property unpackSkipPixels. + */ + public void setUnpackSkipPixels(int unpackSkipPixels) { + + this.unpackSkipPixels = unpackSkipPixels; + } + + /** + * Getter for property unpackLsbFirst. + * @return Value of property unpackLsbFirst. + */ + public boolean getUnpackLsbFirst() { + + return this.unpackLsbFirst; + } + + /** + * Setter for property unpackLsbFirst. + * @param unpackLsbFirst New value of property unpackLsbFirst. + */ + public void setUnpackLsbFirst(boolean unpackLsbFirst) { + + this.unpackLsbFirst = unpackLsbFirst; + } + + /** + * Getter for property unpackSwapBytes. + * @return Value of property unpackSwapBytes. + */ + public boolean getUnpackSwapBytes() { + + return this.unpackSwapBytes; + } + + /** + * Setter for property unpackSwapBytes. + * @param unpackSwapBytes New value of property unpackSwapBytes. + */ + public void setUnpackSwapBytes(boolean unpackSwapBytes) { + + this.unpackSwapBytes = unpackSwapBytes; + } + + /** + * Getter for property unpackSkipImages. + * @return Value of property unpackSkipImages. + */ + public int getUnpackSkipImages() { + + return this.unpackSkipImages; + } + + /** + * Setter for property unpackSkipImages. + * @param unpackSkipImages New value of property unpackSkipImages. + */ + public void setUnpackSkipImages(int unpackSkipImages) { + + this.unpackSkipImages = unpackSkipImages; + } + + /** + * Getter for property unpackImageHeight. + * @return Value of property unpackImageHeight. + */ + public int getUnpackImageHeight() { + + return this.unpackImageHeight; + } + + /** + * Setter for property unpackImageHeight. + * @param unpackImageHeight New value of property unpackImageHeight. + */ + public void setUnpackImageHeight(int unpackImageHeight) { + + this.unpackImageHeight = unpackImageHeight; + } + + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java new file mode 100644 index 000000000..f0bb7fb33 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/ScaleInternal.java @@ -0,0 +1,2447 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.glu.GLU; +import java.nio.*; +import com.jogamp.opengl.impl.InternalBufferUtil; + +/** + * + * @author Administrator + */ +public class ScaleInternal { + + public static final float UINT_MAX = (float)(0x00000000FFFFFFFF); + + public static void scale_internal( int components, int widthin, int heightin, + ShortBuffer datain, int widthout, int heightout, ShortBuffer dataout ) { + float x, lowx, highx, convx, halfconvx; + float y, lowy, highy, convy, halfconvy; + float xpercent, ypercent; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, yint, xint, xindex, yindex; + int temp; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage( components, widthin, heightin, datain, dataout ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + halfconvx = convx / 2; + halfconvy = convy / 2; + for( i = 0; i < heightout; i++ ) { + y = convy * ( i + 0.5f ); + if( heightin > heightout ) { + highy = y + halfconvy; + lowy = y - halfconvy; + } else { + highy = y + 0.5f; + lowy = y - 0.5f; + } + for( j = 0; j < widthout; j++ ) { + x = convx * ( j + 0.5f ); + if( widthin > widthout ) { + highx = x + halfconvx; + lowx = x - halfconvx; + } else { + highx = x + 0.5f; + lowx = x - 0.5f; + } + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + area = 0.0f; + + y = lowy; + yint = (int)Math.floor( y ); + while( y < highy ) { + yindex = ( yint + heightin ) % heightin; + if( highy < yint + 1 ) { + ypercent = highy - y; + } else { + ypercent = yint + 1 - y; + } + + x = lowx; + xint = (int)Math.floor( x ); + + while( x < highx ) { + xindex = ( xint + widthin ) % widthin; + if( highx < xint + 1 ) { + xpercent = highx -x; + } else { + xpercent = xint + 1 - x; + } + + percent = xpercent * ypercent; + area += percent; + temp = ( xindex + ( yindex * widthin) ) * components; + for( k = 0; k < components; k++ ) { + totals[k] += datain.get( temp + k ) * percent; + } + + xint++; + x = xint; + } + yint++; + y = yint; + } + + temp = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + // totals[] should be rounded in the case of enlarging an RGB + // ramp when the type is 332 or 4444 + dataout.put( temp + k, (short)((totals[k] + 0.5f) / area) ); + } + } + } + } + + public static void scale_internal_ubyte( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ByteBuffer dataout, int element_size, int ysize, int group_size ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_ubyte( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + float f = 0.0f; + datain.position( left ); + f = ( 0x000000FF & datain.get() ) * ( 1.0f - lowx_float ); + datain.position( right ); + f += ( 0x000000FF & datain.get() ) * highx_float; + totals[k] += f; + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * x_percent; + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ) * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += ( 0x000000FF & datain.get() ); + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (byte)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_byte( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ByteBuffer dataout, int element_size, int ysize, + int group_size ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_byte( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + float f = 0.0f; + datain.position( left ); + f = datain.get() * ( 1 - lowx_float ); + datain.position( right ); + f += datain.get() * highx_float; + totals[k] += f; + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * x_percent; + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * y_percent; + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get() * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + totals[k] += datain.get(); + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (byte)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_ushort( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_ushort( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & ((int)Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * y_percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & (Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ))) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort() ) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += ( 0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += ( 0x0000FFFF & datain.getShort()) * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + float f = (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * ( 1 - lowx_float ); + datain.position( right ); + f += ((0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES(datain.getShort())) * highx_float); + totals[k] += f; + } else { + datain.position( left ); + float f = ((0x0000FFFF & datain.getShort()) * ( 1 - lowx_float )); + datain.position( right ); + f += ((0x0000FFFF & datain.getShort()) * highx_float); + totals[k] += f; + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * x_percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort() )) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * y_percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort()) ) * percent; + } else { + totals[k] += (0x0000FFFF & datain.getShort()) * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x0000FFFF & Mipmap.GLU_SWAP_2_BYTES( datain.getShort())); + } else { + totals[k] += (0x0000FFFF & datain.getShort()); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (short)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_short( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + ShortBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + int swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_short( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += datain.getShort() * ( 1 - lowx_float ); + datain.position( right ); + totals[k] += datain.getShort() * highx_float; + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort()); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getShort() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getShort() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getShort() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_2_BYTES( datain.getShort() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getShort(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (short)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_uint( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_uint( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt()) ) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += ((0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES(datain.getInt())) * highx_float); + } else { + datain.position( left ); + totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += ((0x00000000FFFFFFFF & datain.getInt()) * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * x_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * y_percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + long tempInt0 = ( 0xFFFFFFFFL & datain.getInt( temp_index ) ); + datain.position( temp_index ); + long tempInt1 = ( 0xFFFFFFFFL & datain.getInt() ); + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())) * percent; + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()) * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + totals[k] += (0x00000000FFFFFFFF & Mipmap.GLU_SWAP_4_BYTES( datain.getInt())); + } else { + totals[k] += (0x00000000FFFFFFFF & datain.getInt()); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + float value = 0.0f; + for( k = 0; k < components; k++ ) { + value = totals[k] / area; + dataout.position( outindex + k ); + if( value >= UINT_MAX ) { + dataout.put( (int)value ); + } else { + dataout.put( (int)(totals[k] / area) ); + } + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_int( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + IntBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + long swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_int( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += (datain.getInt() * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += (datain.getInt() * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getInt() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getInt() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getInt() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getInt() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getInt(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (int)(totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scale_internal_float( int components, int widthin, int heightin, + ByteBuffer datain, int widthout, int heightout, + FloatBuffer dataout, int element_size, int ysize, + int group_size, boolean myswap_bytes ) { + float x, convx; + float y, convy; + float percent; + // Max components in a format is 4, so... + float[] totals = new float[4]; + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outindex; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + float swapbuf; // unsigned buffer + + if( (widthin == (widthout * 2)) && (heightin == (heightout * 2)) ) { + HalveImage.halveImage_float( components, widthin, heightin, datain, dataout, + element_size, ysize, group_size, myswap_bytes ); + return; + } + convy = (float)heightin / heightout; + convx = (float)widthin / widthout; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convy_float; + + for( i = 0; i < heightout; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightin) + highy_int = heightin - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthout; j++ ) { + + // Ok, now apply box filter to box that goes from (lowx, lowy) + // to (highx, highy) on input data into this pixel on output + // data. + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // caulate the value for pixels in the 1st row + xindex = lowx_int * group_size; + if( ( highy_int > lowy_int ) && ( highx_int > lowx_int ) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * ysize; + percent = y_percent * ( 1 - lowx_float ); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + right = temp; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + + // calculate the value for pixels in the last row + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + + // calculate the value for the pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += ysize; + right += ysize; + for( k = 0; k < components; k++, left += element_size, right += element_size ) { + if( myswap_bytes ) { + datain.position( left ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * ( 1 - lowx_float ); + datain.position( right ); + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * highx_float; + } else { + datain.position( left ); + totals[k] += (datain.getFloat() * ( 1 - lowx_float )); + datain.position( right ); + totals[k] += (datain.getFloat() * highx_float); + } + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float) * x_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * x_percent; + } else { + totals[k] += datain.getFloat() * x_percent; + } + } + } + percent = x_percent * highy_float; + temp += ysize; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += group_size; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * y_percent; + } else { + totals[k] += datain.getFloat() * y_percent; + } + } + } + temp += group_size; + percent = y_percent * highx_float; + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + (lowy_int * ysize); + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf * percent; + } else { + totals[k] += datain.getFloat() * percent; + } + } + } + + // this is for the pixels in the body + temp0 = xindex + group_size + ( lowy_int + 1 ) * ysize; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + for( k = 0, temp_index = temp; k < components; k++, temp_index += element_size ) { + datain.position( temp_index ); + if( myswap_bytes ) { + swapbuf = Mipmap.GLU_SWAP_4_BYTES( datain.getFloat() ); + totals[k] += swapbuf; + } else { + totals[k] += datain.getFloat(); + } + } + temp += group_size; + } + temp0 += ysize; + } + + outindex = ( j + ( i * widthout ) ) * components; + for( k = 0; k < components; k++ ) { + dataout.position( outindex + k ); + dataout.put( (totals[k] / area) ); + } + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthin - 1) { + int delta = (highx_int - widthin + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + } + + public static void scaleInternalPackedPixel( int components, Extract extract, + int widthIn, int heightIn, ByteBuffer dataIn, int widthOut, + int heightOut, ByteBuffer dataOut, int pixelSizeInBytes, + int rowSizeInBytes, boolean isSwap ) { + float x, convx; + float y, convy; + float percent; + + // max components in a format is 4, so + float[] totals = new float[4]; + float[] extractTotals = new float[4]; + float[] extractMoreTotals = new float[4]; + float[] shoveTotals = new float[4]; + + float area; + int i, j, k, xindex; + + int temp, temp0; + int temp_index; + int outIndex = 0; + + int lowx_int, highx_int, lowy_int, highy_int; + float x_percent, y_percent; + float lowx_float, highx_float, lowy_float, highy_float; + float convy_float, convx_float; + int convy_int, convx_int; + int l, m; + int left, right; + + if( widthIn == widthOut * 2 && heightIn == heightOut * 2 ) { + HalveImage.halveImagePackedPixel( components, extract, widthIn, heightIn, dataIn, dataOut, + pixelSizeInBytes, rowSizeInBytes, isSwap ); + return; + } + convy = (float)heightIn / (float)heightOut; + convx = (float)widthIn / (float)widthOut; + convy_int = (int)Math.floor( convy ); + convy_float = convy - convy_int; + convx_int = (int)Math.floor( convx ); + convx_float = convx - convx_int; + + area = convx * convy; + + lowy_int = 0; + lowy_float = 0.0f; + highy_int = convy_int; + highy_float = convx_float; + + for( i = 0; i < heightOut; i++ ) { + // Clamp here to be sure we don't read beyond input buffer. + if (highy_int >= heightIn) + highy_int = heightIn - 1; + lowx_int = 0; + lowx_float = 0.0f; + highx_int = convx_int; + highx_float = convx_float; + + for( j = 0; j < widthOut; j++ ) { + // ok now apply box filter to box that goes from( lowx, lowy ) + // to ( highx, highy ) on input data into this pixel on output data + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + + // calculate that value for pixels in the 1st row + xindex = lowx_int * pixelSizeInBytes; + if( (highy_int > lowy_int) && (highx_int > lowx_int) ) { + + y_percent = 1 - lowy_float; + temp = xindex + lowy_int * rowSizeInBytes; + percent = y_percent * ( 1 - lowx_float ); + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + left = temp; + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + right = temp; + percent = y_percent * highx_float; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + // calculate the value for pixels in the last row + + y_percent = highy_float; + percent = y_percent * ( 1 - lowx_float ); + temp = xindex + highy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + percent = y_percent * highx_float; + dataIn.position( temp ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + + // calculate the value for pixels in the 1st and last column + for( m = lowy_int + 1; m < highy_int; m++ ) { + left += rowSizeInBytes; + right += rowSizeInBytes; + dataIn.position( left ); + extract.extract( isSwap, dataIn, extractTotals ); + dataIn.position( right ); + extract.extract( isSwap, dataIn, extractMoreTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += ( extractTotals[k] * ( 1 - lowx_float ) + extractMoreTotals[k] * highx_float ); + } + } + } else if( highy_int > lowy_int ) { + x_percent = highx_float - lowx_float; + percent = ( 1 - lowy_float ) * x_percent; + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp += rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * x_percent; + } + } + percent = x_percent * highy_float; + temp += rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } else if( highx_int > lowx_int ) { + y_percent = highy_float - lowy_float; + percent = ( 1 - lowx_float ) * y_percent; + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + for( l = lowx_int + 1; l < highx_int; l++ ) { + temp += pixelSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * y_percent; + } + } + temp += pixelSizeInBytes; + percent = y_percent * highx_float; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } else { + percent = ( highy_float - lowy_float ) * ( highx_float - lowx_float ); + temp = xindex + lowy_int * rowSizeInBytes; + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + } + + // this is for the pixels in the body + temp0 = xindex + pixelSizeInBytes + ( lowy_int + 1 ) * rowSizeInBytes; + for( m = lowy_int + 1; m < highy_int; m++ ) { + temp = temp0; + for( l = lowx_int + 1; l < highx_int; l++ ) { + dataIn.position( temp ); + extract.extract( isSwap, dataIn, extractTotals ); + for( k = 0; k < components; k++ ) { + totals[k] += extractTotals[k] * percent; + } + temp += pixelSizeInBytes; + } + temp0 += rowSizeInBytes; + } + + outIndex = ( j + ( i * widthOut ) ); + for( k = 0; k < components; k++ ) { + shoveTotals[k] = totals[k] / area; + } + extract.shove( shoveTotals, outIndex, dataOut ); + lowx_int = highx_int; + lowx_float = highx_float; + highx_int += convx_int; + highx_float += convx_float; + if( highx_float > 1.0f ) { + highx_float -= 1.0f; + highx_int++; + } + + // Clamp to make sure we don't run off the right edge + if (highx_int > widthIn - 1) { + int delta = (highx_int - widthIn + 1); + lowx_int -= delta; + highx_int -= delta; + } + } + lowy_int = highy_int; + lowy_float = highy_float; + highy_int += convy_int; + highy_float += convy_float; + if( highy_float > 1.0f ) { + highy_float -= 1.0f; + highy_int++; + } + } + assert( outIndex == ( widthOut * heightOut - 1) ); + } + + public static void scaleInternal3D( int components, int widthIn, int heightIn, + int depthIn, ShortBuffer dataIn, int widthOut, int heightOut, + int depthOut, ShortBuffer dataOut ) { + float x, lowx, highx, convx, halfconvx; + float y, lowy, highy, convy, halfconvy; + float z, lowz, highz, convz, halfconvz; + float xpercent, ypercent, zpercent; + float percent; + // max compnents in a format is 4 + float[] totals = new float[4]; + float volume; + int i, j, d, k, zint, yint, xint, xindex, yindex, zindex; + int temp; + + lowy = highy = lowx = highx = 0.0f; + + convz = (float)depthIn / depthOut; + convy = (float)heightIn / heightOut; + convx = (float)widthIn / widthOut; + halfconvz = convz / 2.0f; + halfconvy = convy / 2.0f; + halfconvx = convx / 2.0f; + for( d = 0; d < depthOut; d++ ) { + z = convz * ( d + 0.5f ); + if( depthIn > depthOut ) { + highz = z + halfconvz; + lowz = z - halfconvz; + } else { + highz = z + 0.5f; + lowz = z - 0.5f; + } + for( i = 0; i < heightOut; i++ ) { + y = convy * ( i + 0.5f ); + if( heightIn > heightOut ) { + highz = y + halfconvy; + lowz = y - halfconvy; + } else { + highz = y + 0.5f; + lowz = y - 0.5f; + } + for( j = 0; j < widthOut; j++ ) { + x = convx * ( j + 0.5f ); + if( depthIn > depthOut ) { + highz = x + halfconvx; + lowz = x - halfconvx; + } else { + highz = x + 0.5f; + lowz = x - 0.5f; + } + + // Ok, now apply box filter to box that goes from ( lowx, lowy, lowz ) + // to ( highx, highy, highz ) on input data into this pixel on output data + + totals[0] = totals[1] = totals[2] = totals[3] = 0.0f; + volume = 0.0f; + + z = lowz; + zint = (int)(Math.floor( z ) ); + while( z < highz ) { + zindex = ( zint + depthIn ) % depthIn; + if( highz < zint + 1 ) { + zpercent = highz - z; + } else { + zpercent = zint + 1 - z; + } + + y = lowy; + yint = (int)(Math.floor( y ) ); + while( y < highy ) { + yindex = ( yint + heightIn ) % heightIn; + if( highy < yint + 1 ) { + ypercent = highy - y; + } else { + ypercent = yint + 1 - y; + } + + x = lowx; + xint = (int)(Math.floor( x ) ); + + while( x < highx ) { + xindex = (xint + widthIn ) % widthIn; + if( highx < xint + 1 ) { + xpercent = highx - x; + } else { + xpercent = xint + 1 - x; + } + + percent = xpercent * ypercent * zpercent; + volume += percent; + + temp = (xindex + ( yindex *widthIn) + (zindex * widthIn *heightIn)) * components; + for( k = 0; k < components; k++ ) { + assert( 0 <= (temp+k) && (temp+k) < (widthIn * heightIn * depthIn * components) ); + totals[k] += dataIn.get( temp + k ) * percent; + } + xint++; + x = xint; + } // while x + yint++; + y = yint; + } // while y + zint++; + z = zint; + } // while z + + temp = ( j + ( i * widthOut ) + (d * widthOut * heightOut ) ) * components; + for( k = 0; k < components; k++ ) { + // totals should be rounded in the case of enlarging an rgb ramp when the type is 332 or 4444 + assert( 0 <= ( temp + k ) && ( temp + k ) < (widthOut * heightOut* depthOut * components) ); + dataOut.put( temp + k, (short)((totals[k] + 0.5f) / volume ) ); + } + } + } + } + } + + public static int gluScaleImage3D( GL gl, int format, int widthIn, int heightIn, + int depthIn, int typeIn, ByteBuffer dataIn, int widthOut, int heightOut, + int depthOut, int typeOut, ByteBuffer dataOut ) { + int components; + ShortBuffer beforeImage, afterImage; + PixelStorageModes psm = new PixelStorageModes(); + + if( widthIn == 0 || heightIn == 0 || depthIn == 0 || + widthOut == 0 || heightOut == 0 || depthOut == 0 ) { + return( 0 ); + } + + if( widthIn < 0 || heightIn < 0 || depthIn < 0 || + widthOut < 0 || heightOut < 0 || depthOut < 0 ) { + return( GLU.GLU_INVALID_VALUE ); + } + + if( !Mipmap.legalFormat(format) || !Mipmap.legalType(typeIn) || + !Mipmap.legalType(typeOut) || typeIn == GL2.GL_BITMAP || + typeOut == GL2.GL_BITMAP ) { + return( GLU.GLU_INVALID_ENUM ); + } + + if( !Mipmap.isLegalFormatForPackedPixelType( format, typeIn ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + + if( !Mipmap.isLegalFormatForPackedPixelType( format, typeOut ) ) { + return( GLU.GLU_INVALID_OPERATION ); + } + + try { + beforeImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.imageSize3D( widthIn, + heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + afterImage = InternalBufferUtil.nativeOrder(ByteBuffer.allocateDirect( Mipmap.imageSize3D( widthIn, + heightIn, depthIn, format, GL2.GL_UNSIGNED_SHORT ) )).asShortBuffer(); + } catch( OutOfMemoryError err ) { + return( GLU.GLU_OUT_OF_MEMORY ); + } + Mipmap.retrieveStoreModes3D( gl, psm ); + + Image.fillImage3D( psm, widthIn, heightIn, depthIn, format, typeIn, + Mipmap.is_index( format ), dataIn, beforeImage ); + components = Mipmap.elements_per_group( format, 0 ); + ScaleInternal.scaleInternal3D( components, widthIn, heightIn, depthIn, + beforeImage, widthOut, heightOut, depthOut, afterImage ); + Image.emptyImage3D( psm, widthOut, heightOut, depthOut, format, typeOut, + Mipmap.is_index( format ), afterImage, dataOut ); + + return( 0 ); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java new file mode 100644 index 000000000..b329840ef --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/mipmap/Type_Widget.java @@ -0,0 +1,224 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.mipmap; + +import java.nio.*; + +/** + * + * @author Administrator + */ +public class Type_Widget { + + ByteBuffer buffer; + + /** Creates a new instance of Type_Widget */ + public Type_Widget() { + buffer = ByteBuffer.allocateDirect( 4 ); + } + + public void setUB0( byte b ) { + buffer.position( 0 ); + buffer.put( b ); + } + + public byte getUB0() { + buffer.position( 0 ); + return( buffer.get() ); + } + + public void setUB1( byte b ) { + buffer.position( 1 ); + buffer.put( b ); + } + + public byte getUB1() { + buffer.position( 1 ); + return( buffer.get() ); + } + + public void setUB2( byte b ) { + buffer.position( 2 ); + buffer.put( b ); + } + + public byte getUB2() { + buffer.position( 2 ); + return( buffer.get() ); + } + + public void setUB3( byte b ) { + buffer.position( 3 ); + buffer.put( b ); + } + + public byte getUB3() { + buffer.position( 3 ); + return( buffer.get() ); + } + + public void setUS0( short s ) { + buffer.position( 0 ); + buffer.putShort( s ); + } + + public short getUS0() { + buffer.position( 0 ); + return( buffer.getShort() ); + } + + public void setUS1( short s ) { + buffer.position( 2 ); + buffer.putShort( s ); + } + + public short getUS1() { + buffer.position( 2 ); + return( buffer.getShort() ); + } + + public void setUI( int i ) { + buffer.position( 0 ); + buffer.putInt( i ); + } + + public int getUI() { + buffer.position( 0 ); + return( buffer.getInt() ); + } + + public void setB0( byte b ) { + buffer.position( 0 ); + buffer.put( b ); + } + + public byte getB0() { + buffer.position( 0 ); + return( buffer.get() ); + } + + public void setB1( byte b ) { + buffer.position( 1 ); + buffer.put( b ); + } + + public byte getB1() { + buffer.position( 1 ); + return( buffer.get() ); + } + + public void setB2( byte b ) { + buffer.position( 2 ); + buffer.put( b ); + } + + public byte getB2() { + buffer.position( 2 ); + return( buffer.get() ); + } + + public void setB3( byte b ) { + buffer.position( 3 ); + buffer.put( b ); + } + + public byte getB3() { + buffer.position( 3 ); + return( buffer.get() ); + } + + public void setS0( short s ) { + buffer.position( 0 ); + buffer.putShort( s ); + } + + public short getS0() { + buffer.position( 0 ); + return( buffer.getShort() ); + } + + public void setS1( short s ) { + buffer.position( 2 ); + buffer.putShort( s ); + } + + public short getS1() { + buffer.position( 2 ); + return( buffer.getShort() ); + } + + public void setI( int i ) { + buffer.position( 0 ); + buffer.putInt( i ); + } + + public int getI() { + buffer.position( 0 ); + return( buffer.getInt() ); + } + + public void setF( float f ) { + buffer.position( 0 ); + buffer.putFloat( f ); + } + + public float getF() { + buffer.position( 0 ); + return( buffer.getFloat() ); + } + + public ByteBuffer getBuffer() { + buffer.rewind(); + return( buffer ); + } + + public static void main( String args[] ) { + Type_Widget t = new Type_Widget(); + t.setI( 1000000 ); + + System.out.println("int: " + Integer.toHexString( t.getI() ) ); + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java new file mode 100755 index 000000000..9ee2494a1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Arc.java @@ -0,0 +1,258 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +*/ + +/** + * Trimming arc + * @author Tomas Hrasky + * + */ +public class Arc { + /** + * Corresponding picewise-linear arc + */ + public PwlArc pwlArc; + + /** + * Arc type + */ + private long type; + + /** + * Arc link in linked list + */ + public Arc link; + + /** + * Previous arc + */ + Arc prev; + + /** + * Next arc + */ + Arc next; + + /** + * Corresponding berizer type arc + */ + private BezierArc bezierArc; + + /** + * Makes new arc at specified side + * + * @param side + * which side doeas this arc form + */ + public Arc(int side) { + bezierArc = null; + pwlArc = null; + type = 0; + setside(side); + // nuid=_nuid + } + + /** + * Sets side the arc is at + * + * @param side + * arc side + */ + private void setside(int side) { + // DONE + clearside(); + type |= side << 8; + } + + /** + * Unsets side + */ + private void clearside() { + // DONE + type &= ~(0x7 << 8); + } + + // this one replaces enum arc_side + /** + * Side not specified + */ + public static final int ARC_NONE = 0; + + /** + * Arc on right + */ + public static final int ARC_RIGHT = 1; + + /** + * Arc on top + */ + public static final int ARC_TOP = 2; + + /** + * Arc on left + */ + public static final int ARC_LEFT = 3; + + /** + * Arc on bottom + */ + public static final int ARC_BOTTOM = 4; + + /** + * Bezier type flag + */ + private static final long BEZIER_TAG = 1 << 13; + + /** + * Arc type flag + */ + private static final long ARC_TAG = 1 << 3; + + /** + * Tail type tag + */ + private static final long TAIL_TAG = 1 << 6; + + /** + * Appends arc to the list + * + * @param jarc + * arc to be append + * @return this + */ + public Arc append(Arc jarc) { + // DONE + if (jarc != null) { + next = jarc.next; + prev = jarc; + next.prev = this; + prev.next = this; + } else { + next = this; + prev = this; + } + + return this; + } + + /** + * Unused + * + * @return true + */ + public boolean check() { + return true; + } + + /** + * Sets bezier type flag + */ + public void setbezier() { + // DONE + type |= BEZIER_TAG; + + } + + /** + * Returns tail of linked list coords + * + * @return tail coords + */ + public float[] tail() { + // DONE + return pwlArc.pts[0].param; + } + + /** + * Returns head of linked list coords + * + * @return head coords + */ + public float[] head() { + // DONE + return next.pwlArc.pts[0].param; + } + + /** + * Returns whether arc is marked with arc_tag + * + * @return is arc marked with arc_tag + */ + public boolean ismarked() { + // DONE + return ((type & ARC_TAG) > 0) ? true : false; + } + + /** + * Cleans arc_tag flag + */ + public void clearmark() { + // DONE + type &= (~ARC_TAG); + } + + /** + * Sets arc_tag flag + */ + public void setmark() { + // DONE + type |= ARC_TAG; + } + + /** + * sets tail tag + */ + public void setitail() { + // DONE + type |= TAIL_TAG; + } + + /** + * Returns whether arc is marked tail + * + * @return is tail + */ + public boolean getitail() { + return false; + } + + /** + * Unsets tail tag + */ + public void clearitail() { + // DONE + type &= (~TAIL_TAG); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java new file mode 100755 index 000000000..3955e3176 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcSdirSorter.java @@ -0,0 +1,63 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcSdirSorter { + + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcSdirSorter(Subdivider subdivider) { + //TODO + // System.out.println("TODO arcsdirsorter.constructor"); + } + + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO + // System.out.println("TODO arcsdirsorter.qsort"); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java new file mode 100755 index 000000000..098ba97b7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTdirSorter.java @@ -0,0 +1,60 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for sorting list of Arcs + * @author Tomas Hrasky + * + */ +public class ArcTdirSorter { + /** + * Makes new ArcSdirSorter with Subdivider + * @param subdivider subdivider + */ + public ArcTdirSorter(Subdivider subdivider) { + // TODO Auto-generated constructor stub + // System.out.println("TODO arcTsorter.konstruktor"); + } + /** + * Sorts list of arcs + * @param list arc list to be sorted + * @param count size of list + */ + public void qsort(CArrayOfArcs list, int count) { + // TODO Auto-generated method stub + // System.out.println("TODO arcTsorter.qsort"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java new file mode 100755 index 000000000..edfb8905f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/ArcTesselator.java @@ -0,0 +1,90 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for arc tesselation + * @author Tomas Hrasky + * + */ +public class ArcTesselator { + + /** + * Makes given arc an bezier arc + * @param arc arc to work with + * @param s1 minimum s param + * @param s2 maximum s param + * @param t1 minimum t param + * @param t2 maximum s param + */ + public void bezier(Arc arc, float s1, float s2, float t1, float t2) { + // DONE + TrimVertex[] p = new TrimVertex[2]; + p[0] = new TrimVertex(); + p[1] = new TrimVertex(); + arc.pwlArc = new PwlArc(2, p); + p[0].param[0] = s1; + p[0].param[1] = s2; + p[1].param[0] = t1; + p[1].param[1] = t2; + arc.setbezier(); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_right(Arc newright, float s, float t1, float t2, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_right"); + } + + /** + * Empty method + * @param newright arc to work with + * @param s first tail + * @param t2 second tail + * @param t1 third tail + * @param f stepsize + */ + public void pwl_left(Arc newright, float s, float t2, float t1, float f) { + // TODO Auto-generated method stub + // System.out.println("TODO arctesselator.pwl_left"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java new file mode 100755 index 000000000..39097720c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Backend.java @@ -0,0 +1,217 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class responsible for rendering + * @author Tomas Hrasky + * + */ +public abstract class Backend { + + /** + * Fill surface + */ + public static final int N_MESHFILL = 0; + + /** + * Draw surface as wire model + */ + public static final int N_MESHLINE = 1; + + /** + * Draw surface with points + */ + public static final int N_MESHPOINT = 2; + + /** + * Object rendering curves + */ + protected CurveEvaluator curveEvaluator; + + /** + * Object rendering surfaces + */ + protected SurfaceEvaluator surfaceEvaluator; + + /** + * Makes new backend + */ + public Backend() { + // curveEvaluator = new OpenGLCurveEvaluator(); + // surfaceEvaluator = new OpenGLSurfaceEvaluator(); + } + + /** + * Begin a curve + */ + public void bgncurv() { + // DONE + curveEvaluator.bgnmap1f(); + + } + + /** + * End a curve + */ + public void endcurv() { + // DONE + curveEvaluator.endmap1f(); + + } + + /** + * Make cuve with given parameters + * @param type curve type + * @param ps control points + * @param stride control points coordinates number + * @param order order of curve + * @param ulo smallest u + * @param uhi highest u + */ + public void curvpts(int type, CArrayOfFloats ps, int stride, int order, + float ulo, float uhi) { + // DONE + curveEvaluator.map1f(type, ulo, uhi, stride, order, ps); + curveEvaluator.enable(type); + } + + /** + * Draw curve + * @param u1 smallest u + * @param u2 highest u + * @param nu number of pieces + */ + public void curvgrid(float u1, float u2, int nu) { + // DONE + curveEvaluator.mapgrid1f(nu, u1, u2); + + } + + /** + * Evaluates curve mesh + * @param from low param + * @param n step + */ + public void curvmesh(int from, int n) { + // DONE + curveEvaluator.mapmesh1f(N_MESHFILL, from, from + n); + } + + /** + * Begin surface + * @param wiretris use triangles + * @param wirequads use quads + */ + public void bgnsurf(int wiretris, int wirequads) { + // DONE + surfaceEvaluator.bgnmap2f(); + + if (wiretris > 0) + surfaceEvaluator.polymode(NurbsConsts.N_MESHLINE); + else + surfaceEvaluator.polymode(NurbsConsts.N_MESHFILL); + } + + /** + * End surface + */ + public void endsurf() { + // DONE + surfaceEvaluator.endmap2f(); + } + + /** + * Empty method + * @param ulo low u param + * @param uhi hig u param + * @param vlo low v param + * @param vhi high v param + */ + public void patch(float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.domain2f(ulo, uhi, vlo, vhi); + } + + /** + * Draw surface + * @param u0 lowest u + * @param u1 highest u + * @param nu number of pieces in u direction + * @param v0 lowest v + * @param v1 highest v + * @param nv number of pieces in v direction + */ + public void surfgrid(float u0, float u1, int nu, float v0, float v1, int nv) { + // DONE + surfaceEvaluator.mapgrid2f(nu, u0, u1, nv, v0, v1); + + } + + /** + * Evaluates surface mesh + * @param u u param + * @param v v param + * @param n step in u direction + * @param m step in v direction + */ + public void surfmesh(int u, int v, int n, int m) { + // System.out.println("TODO backend.surfmesh wireframequads"); + // TODO wireframequads + surfaceEvaluator.mapmesh2f(NurbsConsts.N_MESHFILL, u, u + n, v, v + m); + } + + /** + * Make surface + * @param type surface type + * @param pts control points + * @param ustride control points coordinates in u direction + * @param vstride control points coordinates in v direction + * @param uorder surface order in u direction + * @param vorder surface order in v direction + * @param ulo lowest u + * @param uhi hightest u + * @param vlo lowest v + * @param vhi hightest v + */ + public void surfpts(int type, CArrayOfFloats pts, int ustride, int vstride, + int uorder, int vorder, float ulo, float uhi, float vlo, float vhi) { + // DONE + surfaceEvaluator.map2f(type, ulo, uhi, ustride, uorder, vlo, vhi, + vstride, vorder, pts); + surfaceEvaluator.enable(type); + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java new file mode 100755 index 000000000..d9b390b67 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/BezierArc.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class BezierArc { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java new file mode 100755 index 000000000..61316f348 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Bin.java @@ -0,0 +1,155 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding trimming arcs + * @author Tomas Hrasky + * + */ +public class Bin { + + /** + * Head of linked list of arcs + */ + private Arc head; + + /** + * Current arc + */ + private Arc current; + + /** + * Indicates whether there are any Arcs in linked list + * @return true if there are any Arcs in linked list + */ + public boolean isnonempty() { + // DONE + return this.head != null ? true : false; + } + + /** + * Adds and arc to linked list + * @param jarc added arc + */ + public void addarc(Arc jarc) { + // DONE + // if (head == null) + // head = jarc; + // else { + jarc.link = head; + head = jarc; + // } + + } + + /** + * Returns number of arcs in linked list + * @return number of arcs + */ + public int numarcs() { + // DONE + int count = 0; + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + count++; + return count; + } + + /** + * Removes first arc in list + * @return new linked list head + */ + public Arc removearc() { + // DONE + Arc jarc = head; + if (jarc != null) + head = jarc.link; + return jarc; + + } + + /** + * Consolidates linked list + */ + public void adopt() { + // DONE + markall(); + + Arc orphan; + while ((orphan = removearc()) != null) { + for (Arc parent = orphan.next; !parent.equals(orphan); parent = parent.next) { + if (!parent.ismarked()) { + orphan.link = parent.link; + parent.link = orphan; + orphan.clearmark(); + break; + } + } + } + + } + + /** + * Marks all arc in linked list + */ + private void markall() { + // DONE + for (Arc jarc = firstarc(); jarc != null; jarc = nextarc()) + jarc.setmark(); + } + + /** + * Returns first arc in linked list + * @return first arc in linked list + */ + private Arc firstarc() { + // DONE + current = head; + return nextarc(); + } + + /** + * Returns next arc in linked list + * @return next arc + * + */ + private Arc nextarc() { + // DONE + Arc jarc = current; + if (jarc != null) + current = jarc.link; + return jarc; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java new file mode 100755 index 000000000..b5b88ad96 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Breakpt.java @@ -0,0 +1,59 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding break point parameters + * + * @author Tomas Hrasky + * + */ +public class Breakpt { + + /** + * Breakpoint multiplicity + */ + public int multi; + + /** + * Breakpint value + */ + public float value; + + /** + * Breakpoint deficit (how many times it has to be added) + */ + public int def; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java new file mode 100755 index 000000000..0646e1d9f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfArcs.java @@ -0,0 +1,194 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfArcs { + /** + * Underlaying array + */ + private Arc[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfArcs(Arc[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfArcs(CArrayOfArcs carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfArcs(Arc[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Arc get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Arc f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Arc get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public Arc getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, Arc value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Arc[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Arc[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java new file mode 100755 index 000000000..e47fdf966 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfBreakpts.java @@ -0,0 +1,130 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfBreakpts { + /** + * Underlaying array + */ + private Breakpt[] pole; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfBreakpts(Breakpt[] array, int pointer) { + this.pole = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfBreakpts(CArrayOfBreakpts carray) { + this.pole = carray.pole; + this.pointer = carray.pointer; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Breakpt get() { + return pole[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Breakpt f) { + pole[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Breakpt get(int i) { + return pole[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java new file mode 100755 index 000000000..60cef9919 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfFloats.java @@ -0,0 +1,195 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfFloats { + + /** + * Underlaying array + */ + private float[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Don't check for array borders? + */ + private boolean noCheck = true; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfFloats(float[] array, int pointer) { + this.array = array; + // this.pointer=pointer; + setPointer(pointer); + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfFloats(CArrayOfFloats carray) { + this.array = carray.array; + // this.pointer=carray.pointer; + setPointer(carray.pointer); + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param ctlarray + * underlaying array + */ + public CArrayOfFloats(float[] ctlarray) { + this.array = ctlarray; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public float get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + // pointer++; + setPointer(pointer + 1); + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(float f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public float get(int i) { + return array[i]; + } + + /** + * Returns array element at specified index relatively to pointer + * + * @param i + * relative index + * @return element at relative index + */ + public float getRelative(int i) { + return array[pointer + i]; + } + + /** + * Sets value of element at specified index relatively to pointer + * + * @param i + * relative index + * @param value + * value to be set + */ + public void setRelative(int i, float value) { + array[pointer + i] = value; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + // pointer-=i; + setPointer(pointer - i); + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + if (!noCheck && pointer > array.length) + throw new IllegalArgumentException("Pointer " + pointer + + " out of bounds " + array.length); + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + // pointer+=i; + setPointer(pointer + i); + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + // pointer--; + setPointer(pointer - 1); + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public float[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(float[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java new file mode 100755 index 000000000..ef16a8204 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CArrayOfQuiltspecs.java @@ -0,0 +1,160 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/** + * Class replacing C language pointer + * + * @author Tomas Hrasky + * + */ +public class CArrayOfQuiltspecs { + /** + * Underlaying array + */ + private Quiltspec[] array; + + /** + * Pointer to array member + */ + private int pointer; + + /** + * Makes new CArray + * + * @param array + * underlaying array + * @param pointer + * pointer (index) to array + */ + public CArrayOfQuiltspecs(Quiltspec[] array, int pointer) { + this.array = array; + this.pointer = pointer; + } + + /** + * Makes new CArray from other CArray + * + * @param carray + * reference array + */ + public CArrayOfQuiltspecs(CArrayOfQuiltspecs carray) { + this.array = carray.array; + this.pointer = carray.pointer; + } + + /** + * Makes new CArray with pointer set to 0 + * + * @param array + * underlaying array + */ + public CArrayOfQuiltspecs(Quiltspec[] array) { + this.array = array; + this.pointer = 0; + } + + /** + * Returns element at pointer + * + * @return element at pointer + */ + public Quiltspec get() { + return array[pointer]; + } + + /** + * Increases pointer by one (++) + */ + public void pp() { + pointer++; + } + + /** + * Sets element at pointer + * + * @param f + * desired value + */ + public void set(Quiltspec f) { + array[pointer] = f; + + } + + /** + * Returns array element at specified index + * + * @param i + * array index + * @return element at index + */ + public Quiltspec get(int i) { + return array[i]; + } + + /** + * Lessens pointer by value + * + * @param i + * lessen by + */ + public void lessenPointerBy(int i) { + pointer -= i; + + } + + /** + * Returns pointer value + * + * @return pointer value + */ + public int getPointer() { + return pointer; + } + + /** + * Sets ponter value + * + * @param pointer + * pointer value to be set + */ + public void setPointer(int pointer) { + this.pointer = pointer; + } + + /** + * Raises pointer by value + * + * @param i + * raise by + */ + public void raisePointerBy(int i) { + pointer += i; + + } + + /** + * Lessens ponter by one (--) + */ + public void mm() { + pointer--; + + } + + /** + * Returns underlaying array + * + * @return underlaying array + */ + public Quiltspec[] getArray() { + return array; + } + + /** + * Sets underlaying array + * + * @param array + * underlaying array + */ + public void setArray(Quiltspec[] array) { + this.array = array; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java new file mode 100755 index 000000000..fb1a5acea --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curve.java @@ -0,0 +1,238 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding curve definition + * @author Tomáš Hráský + * + */ +public class Curve { + + /** + * Maximum coordinates per control point + */ + private static final int MAXCOORDS = 5; + + /** + * Max curve order + */ + private static final int MAXORDER = 24; + + /** + * Next curve in linked list + */ + public Curve next; + + /** + * OpenGL maps + */ + private Mapdesc mapdesc; + + /** + * Does the curve need sampling + */ + private boolean needsSampling; + + /** + * Culling + */ + private int cullval; + + /** + * Number of coords + */ + private int stride; + + /** + * Curve order + */ + private int order; + + /** + * Holds conversion range borders + */ + private float[] range; + + /** + * Subdivision stepsize + */ + public float stepsize; + + /** + * Minimal subdivision stepsize + */ + private float minstepsize; + + /** + * Sampling points + */ + float[] spts; + + /** + * Makes new Curve + * + * @param geo + * @param pta + * @param ptb + * @param c + * next curve in linked list + */ + public Curve(Quilt geo, float[] pta, float[] ptb, Curve c) { + + spts = new float[MAXORDER * MAXCOORDS]; + + mapdesc = geo.mapdesc; + + next = c; + needsSampling = mapdesc.isRangeSampling() ? true : false; + + cullval = mapdesc.isCulling() ? Subdivider.CULL_ACCEPT + : Subdivider.CULL_TRIVIAL_REJECT; + order = geo.qspec.get(0).order; + stride = MAXCOORDS; + + // CArrayOfFloats ps = geo.cpts; + CArrayOfFloats ps = new CArrayOfFloats(geo.cpts.getArray(), 0); + CArrayOfQuiltspecs qs = geo.qspec; + ps.raisePointerBy(qs.get().offset); + ps.raisePointerBy(qs.get().index * qs.get().order * qs.get().stride); + + if (needsSampling) { + mapdesc.xformSampling(ps, qs.get().order, qs.get().stride, spts, + stride); + } + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.Curve-cullval"); + // mapdesc.xformCulling(ps,qs.get().order,qs.get().stride,cpts,stride); + } + + range = new float[3]; + range[0] = qs.get().breakpoints[qs.get().index]; + range[1] = qs.get().breakpoints[qs.get().index + 1]; + range[2] = range[1] - range[0]; + // TODO it is necessary to solve problem with "this" pointer here + if (range[0] != pta[0]) { + // System.out.println("TODO curve.Curve-range0"); + // Curve lower=new Curve(this,pta,0); + // lower.next=next; + // this=lower; + } + if (range[1] != ptb[0]) { + // System.out.println("TODO curve.Curve-range1"); + // Curve lower=new Curve(this,ptb,0); + } + } + + /** + * Checks culling type + * @return Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + if (cullval == Subdivider.CULL_ACCEPT) { + // System.out.println("TODO curve.cullval"); + // cullval=mapdesc.cullCheck(cpts,order,stride); + } + // TODO compute cullval and return the computed value + // return cullval; + return Subdivider.CULL_ACCEPT; + } + + /** + * Computes subdivision step size + */ + public void getStepSize() { + minstepsize = 0; + if (mapdesc.isConstantSampling()) { + setstepsize(mapdesc.maxrate); + } else if (mapdesc.isDomainSampling()) { + setstepsize(mapdesc.maxrate * range[2]); + } else { + assert (order <= MAXORDER); + + float tmp[][] = new float[MAXORDER][MAXCOORDS]; + + int tstride = (MAXORDER); + + int val = 0; + // mapdesc.project(spts,stride,tmp,tstride,order); + + // System.out.println("TODO curve.getsptepsize mapdesc.project"); + + if (val == 0) { + setstepsize(mapdesc.maxrate); + } else { + float t = mapdesc.getProperty(NurbsConsts.N_PIXEL_TOLERANCE); + if (mapdesc.isParametricDistanceSampling()) { + // System.out.println("TODO curve.getstepsize - parametric"); + } else if (mapdesc.isPathLengthSampling()) { + // System.out.println("TODO curve.getstepsize - pathlength"); + } else { + setstepsize(mapdesc.maxrate); + } + } + + } + + } + + /** + * Sets maximum subdivision step size + * @param max maximum subdivision step size + */ + private void setstepsize(float max) { + // DONE + stepsize = (max >= 1) ? (range[2] / max) : range[2]; + minstepsize = stepsize; + } + + /** + * Clamps the curve + */ + public void clamp() { + // DONE + if (stepsize < minstepsize) + stepsize = mapdesc.clampfactor * minstepsize; + } + + /** + * Tells whether curve needs subdivision + * + * @return curve needs subdivison + */ + public boolean needsSamplingSubdivision() { + return (stepsize < minstepsize); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java new file mode 100755 index 000000000..c27ffd4c4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/CurveEvaluator.java @@ -0,0 +1,86 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering curves with OpenGL + * @author Tomáš Hráský + * + */ +public interface CurveEvaluator { + /** + * Pushes eval bit + */ + public void bgnmap1f(); + + /** + * Pops all OpenGL attributes + */ + public void endmap1f() ; + + /** + * Initializes opengl evaluator + * @param type curve type + * @param ulo lowest u + * @param uhi highest u + * @param stride control point coords + * @param order curve order + * @param ps control points + */ + public void map1f(int type, float ulo, float uhi, int stride, int order, + CArrayOfFloats ps) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; + + /** + * Calls glMapGrid1f + * @param nu steps + * @param u1 low u + * @param u2 high u + */ + public void mapgrid1f(int nu, float u1, float u2) ; + + /** + * Evaluates a curve using glEvalMesh1f + * @param style Backend.N_MESHFILL/N_MESHLINE/N_MESHPOINT + * @param from lowest param + * @param to highest param + */ + public void mapmesh1f(int style, int from, int to) ; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java new file mode 100755 index 000000000..fc3018833 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Curvelist.java @@ -0,0 +1,121 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for woking with linked list of curves + * @author Tomas Hrasky + * + */ +public class Curvelist { + + /** + * Head of linked list + */ + private Curve curve; + + /** + * Holds conversion range borders + */ + float[] range; + + /** + * Subdivision step size + */ + public float stepsize; + + /** + * Do curves need subdivision? + */ + private boolean needsSubdivision; + + /** + * Makes new instance on top of specified lis of Quilts + * @param qlist underlaying list of quilts + * @param pta range start + * @param ptb range end + */ + public Curvelist(Quilt qlist, float[] pta, float[] ptb) { + // DONE + curve = null; + range = new float[3]; + + for (Quilt q = qlist; q != null; q = q.next) { + curve = new Curve(q, pta, ptb, curve); + } + range[0] = pta[0]; + range[1] = ptb[0]; + range[2] = range[1] - range[0]; + } + + /** + * Compute step size + */ + public void getstepsize() { + // DONE + stepsize = range[2]; + Curve c; + for (c = curve; c != null; c = c.next) { + c.getStepSize(); + c.clamp(); + stepsize = (c.stepsize < stepsize) ? c.stepsize : stepsize; + if (c.needsSamplingSubdivision()) + break; + } + needsSubdivision = (c != null) ? true : false; + + } + + /** + * Indicates whether curves need subdivision + * @return curves need subdivision + */ + public boolean needsSamplingSubdivision() { + // DONE + return needsSubdivision; + } + + /** + * Checks for culling + * @return Subdivider.CULL_TRIVIAL_REJECT or Subdivider.CULL_ACCEPT + */ + public int cullCheck() { + // DONE + for (Curve c = curve; c != null; c = c.next) + if (c.cullCheck() == Subdivider.CULL_TRIVIAL_REJECT) + return Subdivider.CULL_TRIVIAL_REJECT; + return Subdivider.CULL_ACCEPT; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java new file mode 100755 index 000000000..39a3a28f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/DisplayList.java @@ -0,0 +1,56 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.lang.reflect.Method; + +/** + * Display list + * @author Tomas Hrasky + * + */ +public class DisplayList { + + /** + * Append action to the display list + * @param src source object to invoke method on + * @param m invoked method + * @param arg method argument + */ + public void append(Object src, Method m, Object arg) { + // TODO Auto-generated method stub + // System.out.println("TODO displaylist append"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java new file mode 100755 index 000000000..00757ed7e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Flist.java @@ -0,0 +1,130 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +import java.util.Arrays; + +/** + * List of breakpoints + * @author Tomas Hrasky + * + */ +public class Flist { + + /** + * Data elements end index + * + */ + public int end; + + /** + *Data elements start index + */ + public int start; + + /** + * Breakpoint values + */ + public float[] pts; + + /** + * Number of array fields + */ + private int npts; + + /** + * Grows list + * @param maxpts maximum desired size + */ + public void grow(int maxpts) { + // DONE + if (npts < maxpts) { + // npts=2*maxpts; + npts = maxpts; + pts = new float[npts]; + } + start = 0; + end = 0; + } + + /** + * Removes duplicate array elemnts + */ + public void filter() { + // INFO the aim of this method is to remove duplicates from array + + Arrays.sort(pts); + + start = 0; + + int j = 0; + + for (int i = 1; i < end; i++) { + if (pts[i] == pts[i - j - 1]) + j++; + pts[i - j] = pts[i]; + } + + end -= j; + + } + + /** + * Sets start and and to real start and end of array elements + * @param from start from + * @param to end at + */ + public void taper(float from, float to) { + // DONE + + while (pts[start] != from) { + start++; + } + + while (pts[end - 1] != to) { + end--; + } + + } + + /** + * Adds breakpoint value + * @param f value + */ + public void add(float f) { + //DONE + pts[end++] = f; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java new file mode 100755 index 000000000..9251aa231 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotspec.java @@ -0,0 +1,557 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector specification + * + * @author Tomas Hrasky + * + */ +public class Knotspec { + + /** + * Begin of input knots + */ + public CArrayOfFloats inkbegin; + + /** + * End of input knots + */ + public CArrayOfFloats inkend; + + /** + * Stride before knot operations + */ + public int prestride; + + /** + * Curve order + */ + public int order; + + /** + * Next knot specification in linked list (used in surfaces) + */ + public Knotspec next; + + /** + * Last knot + */ + public CArrayOfFloats klast; + + /** + * First knot + */ + CArrayOfFloats kfirst; + + /** + * Beginning of breakpoints + */ + CArrayOfBreakpts bbegin; + + /** + * End of breakpoints + */ + CArrayOfBreakpts bend; + + /** + * Considered left end knot + */ + CArrayOfFloats kleft; + + /** + * Considered right end knot + */ + CArrayOfFloats kright; + + /** + * Offset before knot operations + */ + int preoffset; + + /** + * Control points array Length after knot operations + */ + int postwidth; + + /** + * Beginning of coeficients array + */ + private CArrayOfFloats sbegin; + + /** + * Beginning of output knots + */ + private CArrayOfFloats outkbegin; + + /** + * End of output knots + */ + private CArrayOfFloats outkend; + + /** + * Control points aray length before knot operations + */ + int prewidth; + + /** + * Offset after knot operations + */ + int postoffset; + + /** + * Number of control points' coordinates after knot operations + */ + public int poststride; + + /** + * Number of control points' coordinates + */ + public int ncoords; + + /** + * Tell whether knotspec has already benn transformed + */ + public boolean istransformed; + + /** + * Knotspec to be transformed + */ + public Knotspec kspectotrans; + + /** + * Finds knot border of knot insertion and required multiplicities + */ + public void preselect() { + // DONE + float kval; + + klast = new CArrayOfFloats(inkend); + klast.lessenPointerBy(order); + for (kval = klast.get(); klast.getPointer() != inkend.getPointer(); klast + .pp()) { + if (!Knotvector.identical(klast.get(), kval)) + break; + } + + kfirst = new CArrayOfFloats(inkbegin); + kfirst.raisePointerBy(order - 1); + for (kval = kfirst.get(); kfirst.getPointer() != inkend.getPointer(); kfirst + .pp()) { + if (!Knotvector.identical(kfirst.get(), kval)) + break; + } + + CArrayOfFloats k = new CArrayOfFloats(kfirst); + k.mm(); + + for (; k.getPointer() >= inkbegin.getPointer(); k.mm()) + if (!Knotvector.identical(kval, k.get())) + break; + k.pp(); + + Breakpt[] bbeginArray = new Breakpt[(klast.getPointer() - kfirst + .getPointer()) + 1]; + for (int i = 0; i < bbeginArray.length; i++) + bbeginArray[i] = new Breakpt(); + bbegin = new CArrayOfBreakpts(bbeginArray, 0); + bbegin.get().multi = kfirst.getPointer() - k.getPointer(); + bbegin.get().value = kval; + + bend = new CArrayOfBreakpts(bbegin); + kleft = new CArrayOfFloats(kfirst); + kright = new CArrayOfFloats(kfirst); + + } + + /** + * Perpares knotspec for transformation + */ + public void select() { + // DONE + breakpoints(); + knots(); + factors(); + + preoffset = kleft.getPointer() - (inkbegin.getPointer() + order); + postwidth = ((bend.getPointer() - bbegin.getPointer()) * order); + prewidth = (outkend.getPointer() - outkbegin.getPointer()) - order; + postoffset = (bbegin.get().def > 1) ? (bbegin.get().def - 1) : 0; + + } + + /** + * Computes alpha factors for computing new control points + */ + private void factors() { + // DONE + CArrayOfFloats mid = new CArrayOfFloats(outkend.getArray(), (outkend + .getPointer() - 1) + - order + bend.get().multi); + + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + + for (CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); bpt + .getPointer() >= bbegin.getPointer(); bpt.mm()) { + mid.lessenPointerBy(bpt.get().multi); + int def = bpt.get().def - 1; + if (def < 0) + continue; + float kv = bpt.get().value; + + CArrayOfFloats kf = new CArrayOfFloats(mid.getArray(), (mid + .getPointer() - def) + + (order - 1)); + for (CArrayOfFloats kl = new CArrayOfFloats(kf.getArray(), kf + .getPointer() + + def); kl.getPointer() != kf.getPointer(); kl.mm()) { + CArrayOfFloats kh, kt; + for (kt = new CArrayOfFloats(kl), kh = new CArrayOfFloats(mid); kt + .getPointer() != kf.getPointer(); kh.mm(), kt.mm()) { + fptr.set((kv - kh.get()) / (kt.get() - kh.get())); + fptr.pp(); + } + kl.set(kv); + } + } + + } + + /** + * Makes new knot vector + */ + private void knots() { + // DONE + CArrayOfFloats inkpt = new CArrayOfFloats(kleft.getArray(), kleft + .getPointer() + - order); + CArrayOfFloats inkend = new CArrayOfFloats(kright.getArray(), kright + .getPointer() + + bend.get().def); + + outkbegin = new CArrayOfFloats(new float[inkend.getPointer() + - inkpt.getPointer()], 0); + CArrayOfFloats outkpt; + for (outkpt = new CArrayOfFloats(outkbegin); inkpt.getPointer() != inkend + .getPointer(); inkpt.pp(), outkpt.pp()) { + outkpt.set(inkpt.get()); + } + outkend = new CArrayOfFloats(outkpt); + } + + /** + * Analyzes breakpoints + */ + private void breakpoints() { + // DONE + CArrayOfBreakpts ubpt = new CArrayOfBreakpts(bbegin); + CArrayOfBreakpts ubend = new CArrayOfBreakpts(bend); + int nfactors = 0; + + ubpt.get().value = ubend.get().value; + ubpt.get().multi = ubend.get().multi; + + kleft = new CArrayOfFloats(kright); + + for (; kright.getPointer() != klast.getPointer(); kright.pp()) { + if (Knotvector.identical(kright.get(), ubpt.get().value)) { + ubpt.get().multi++; + } else { + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + ubpt.pp(); + ubpt.get().value = kright.get(); + ubpt.get().multi = 1; + } + } + ubpt.get().def = order - ubpt.get().multi; + nfactors += (ubpt.get().def * (ubpt.get().def - 1)) / 2; + + bend = new CArrayOfBreakpts(ubpt); + + if (nfactors > 0) { + sbegin = new CArrayOfFloats(new float[nfactors], 0); + } else { + sbegin = null; + } + + } + + /** + * Copies control points + * + * @param _inpt + * input control points + * @param _outpt + * output control points + */ + public void copy(CArrayOfFloats _inpt, CArrayOfFloats _outpt) { + CArrayOfFloats inpt = new CArrayOfFloats(_inpt); + CArrayOfFloats outpt = new CArrayOfFloats(_outpt); + + inpt.raisePointerBy(preoffset); + if (next != null) { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + next.copy(inpt, outpt); + inpt.raisePointerBy(prestride); + } + + } else { + for (CArrayOfFloats lpt = new CArrayOfFloats(outpt.getArray(), + outpt.getPointer() + prewidth); outpt.getPointer() != lpt + .getPointer(); outpt.raisePointerBy(poststride)) { + pt_io_copy(outpt, inpt); + inpt.raisePointerBy(prestride); + } + } + + } + + /** + * Copies one control point to other + * + * @param topt + * source control point + * @param frompt + * destination control point + */ + private void pt_io_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.set(frompt.get()); + break; + default: + // TODO break with copying in general case + // System.out.println("TODO knotspec.pt_io_copy"); + break; + } + + } + + /** + * Inserts a knot + * + * @param _p + * inserted knot + */ + public void transform(CArrayOfFloats _p) { + CArrayOfFloats p = new CArrayOfFloats(_p); + // DONE + if (next != null) {//surface code + if (this.equals(kspectotrans)) { + next.transform(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) + next.transform(p); + + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + next.transform(p); + } + } + + } else {//code for curve + if (this.equals(kspectotrans)) { + insert(p); + } else { + if (istransformed) { + p.raisePointerBy(postoffset); + for (CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), + p.getPointer() + postwidth); p.getPointer() != pend + .getPointer(); p.raisePointerBy(poststride)) { + kspectotrans.insert(p); + } + } else { + CArrayOfFloats pend = new CArrayOfFloats(p.getArray(), p + .getPointer() + + prewidth); + for (; p.getPointer() != pend.getPointer(); p + .raisePointerBy(poststride)) + kspectotrans.insert(p); + } + } + } + + } + + /** + * Inserts a knot and computes new control points + * + * @param p + * inserted knot + */ + private void insert(CArrayOfFloats p) { + // DONE + CArrayOfFloats fptr = null; + if (sbegin != null) + fptr = new CArrayOfFloats(sbegin); + CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + prewidth - poststride); + // CArrayOfFloats srcpt = new CArrayOfFloats(p.getArray(), prewidth - + // poststride); + CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), p.getPointer() + + postwidth + postoffset - poststride); + // CArrayOfFloats dstpt = new CArrayOfFloats(p.getArray(), postwidth + + // postoffset - poststride); + CArrayOfBreakpts bpt = new CArrayOfBreakpts(bend); + + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride * bpt.get().def); srcpt.getPointer() != pend + .getPointer(); pend.raisePointerBy(poststride)) { + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), srcpt + .getPointer() + - poststride); p2.getPointer() != pend.getPointer(); p1 + .setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + bpt.mm(); + for (; bpt.getPointer() >= bbegin.getPointer(); bpt.mm()) { + + for (int multi = bpt.get().multi; multi > 0; multi--) { + pt_oo_copy(dstpt, srcpt); + dstpt.lessenPointerBy(poststride); + srcpt.lessenPointerBy(poststride); + } + for (CArrayOfFloats pend = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride * bpt.get().def); srcpt + .getPointer() != pend.getPointer(); pend + .raisePointerBy(poststride), dstpt + .lessenPointerBy(poststride)) { + pt_oo_copy(dstpt, srcpt); + CArrayOfFloats p1 = new CArrayOfFloats(srcpt); + + for (CArrayOfFloats p2 = new CArrayOfFloats(srcpt.getArray(), + srcpt.getPointer() - poststride); p2.getPointer() != pend + .getPointer(); p1.setPointer(p2.getPointer()), p2 + .lessenPointerBy(poststride)) { + pt_oo_sum(p1, p1, p2, fptr.get(), 1.0 - fptr.get()); + fptr.pp(); + } + } + } + } + + /** + * Copies one control point to another + * + * @param topt + * source ctrl point + * @param frompt + * distance ctrl point + */ + private void pt_oo_copy(CArrayOfFloats topt, CArrayOfFloats frompt) { + // DONE + // this is a "trick" with case - "break" is omitted so it comes through all cases + switch (ncoords) { + case 4: + topt.setRelative(3, frompt.getRelative(3)); + case 3: + topt.setRelative(2, frompt.getRelative(2)); + case 2: + topt.setRelative(1, frompt.getRelative(1)); + case 1: + topt.setRelative(0, frompt.getRelative(0)); + break; + default: + // default uses memcpy but it is not needed (we probably won't have more than 4 coords) + // TODO not sure about it + break; + } + + } + + /** + * Computes new control point + * + * @param x + * first point + * @param y + * second point + * @param z + * third pont + * @param a + * alpha + * @param b + * 1 - alpha + */ + private void pt_oo_sum(CArrayOfFloats x, CArrayOfFloats y, + CArrayOfFloats z, float a, double b) { + // DONE + switch (ncoords) { + case 4: + x.setRelative(3, (float) (a * y.getRelative(3) + b + * z.getRelative(3))); + case 3: + x.setRelative(2, (float) (a * y.getRelative(2) + b + * z.getRelative(2))); + case 2: + x.setRelative(1, (float) (a * y.getRelative(1) + b + * z.getRelative(1))); + case 1: + x.setRelative(0, (float) (a * y.getRelative(0) + b + * z.getRelative(0))); + break; + default: + //no need of default - see previous method and its case statement + // System.out.println("TODO pt_oo_sum default"); + break; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java new file mode 100755 index 000000000..658a1cbda --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Knotvector.java @@ -0,0 +1,179 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Knot vector used in curve specification + * + * @author Tomas Hrasky + * + */ +public class Knotvector { + + /** + * Tolerance used when comparing knots - when difference is smaller, knots + * are considered equal + */ + public static final float TOLERANCE = 1.0e-5f; + + /** + * Maximum curve order + */ + private static final int MAXORDER = 24; + + /** + * Number of knots + */ + int knotcount; + + /** + * Number of control points' coordinates + */ + int stride; + + /** + * Curve order + */ + int order; + + /** + * Knots + */ + float[] knotlist; + + /** + * Makes new knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public Knotvector(int nknots, int stride, int order, float[] knot) { + // DONE + init(nknots, stride, order, knot); + } + + /** + * Initializes knotvector + * + * @param nknots + * number of knots + * @param stride + * number of ctrl points' corrdinates + * @param order + * curve order + * @param knot + * knots + */ + public void init(int nknots, int stride, int order, float[] knot) { + // DONE + this.knotcount = nknots; + this.stride = stride; + this.order = order; + this.knotlist = new float[nknots]; + for (int i = 0; i < nknots; i++) { + this.knotlist[i] = knot[i]; + } + + } + + /** + * Validates knot vector parameters + * + * @return knot vector validity + */ + public int validate() { + int kindex = knotcount - 1; + if (order < 1 || order > MAXORDER) { + return 1; + } + if (knotcount < 2 * order) { + return 2; + } + if (identical(knotlist[kindex - (order - 1)], knotlist[order - 1])) { + return 3; + } + for (int i = 0; i < kindex; i++) { + if (knotlist[i] > knotlist[i + 1]) + return 4; + } + int multi = 1; + for (; kindex >= 1; kindex--) { + if (knotlist[kindex] - knotlist[kindex - 1] < TOLERANCE) { + multi++; + continue; + } + if (multi > order) { + return 5; + } + multi = 1; + } + if (multi > order) { + return 5; + } + + return 0; + } + + /** + * Show specified message + * + * @param msg + * message to be shown + */ + public void show(String msg) { + // TODO Auto-generated method stub + // System.out.println("TODO knotvector.show"); + + } + + /** + * Compares two knots for equality + * + * @param a + * first knot + * @param b + * second knot + * @return knots are/are not equal + */ + public static boolean identical(float a, float b) { + return ((a - b) < TOLERANCE) ? true : false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java new file mode 100755 index 000000000..568eddc51 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Mapdesc.java @@ -0,0 +1,442 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding properties of OpenGL map + * @author Tomas Hrasky + * + */ +public class Mapdesc { + + /** + * Maximum control point coords + */ + private static final int MAXCOORDS = 5; + + /** + * Next description in list + */ + public Mapdesc next; + + /** + * Is map rational + */ + public int isrational; + + /** + * Number of control point coords + */ + public int ncoords; + + /** + * Map type + */ + private int type; + + /** + * Number of homogenous coords + */ + private int hcoords; + + /** + * Number of inhomogenous coords + */ + private int inhcoords; + + /** + * Not used + */ + private int mask; + + /** + * Value of N_PIXEL_TOLERANCE property + */ + private float pixel_tolerance; + + /** + * Value of N_ERROR_TOLERANCE property + */ + private float error_tolerance; + + /** + * Value of N_BBOX_SUBDIVIDING property + */ + private float bbox_subdividing; + + /** + * Value of N_CULLING property + */ + private float culling_method; + + /** + * Value of N_SAMPLINGMETHOD property + */ + private float sampling_method; + + /** + * Value of N_CLAMPFACTOR property + */ + float clampfactor; + + /** + * Value of N_MINSAVINGS property + */ + private float minsavings; + + /** + * Steps in u direction + */ + private float s_steps; + + /** + * Steps in v direction + */ + private float t_steps; + + /** + * Maximal step + */ + float maxrate; + + /** + * Maximal u direction step + */ + private float maxsrate; + + /** + * Maximal v direction step + */ + private float maxtrate; + + /** + * Not used + */ + private float[][] bmat; + + /** + * Sampling matrix + */ + private float[][] smat; + + /** + * Not used + */ + private float[][] cmat; + + /** + * Not used + */ + private float[] bboxsize; + + /** + * Makes new mapdesc + * @param type map type + * @param rational is rational + * @param ncoords number of control points coords + * @param backend backend object + */ + public Mapdesc(int type, int rational, int ncoords, Backend backend) { + // DONE + this.type = type; + this.isrational = rational; + this.ncoords = ncoords; + this.hcoords = ncoords + (isrational > 0 ? 0 : 1); + this.inhcoords = ncoords - (isrational > 0 ? 1 : 0); + this.mask = ((1 << (inhcoords * 2)) - 1); + next = null; + + assert (hcoords <= MAXCOORDS); + assert (inhcoords >= 1); + + pixel_tolerance = 1f; + error_tolerance = 1f; + bbox_subdividing = NurbsConsts.N_NOBBOXSUBDIVISION; + culling_method = NurbsConsts.N_NOCULLING; + sampling_method = NurbsConsts.N_NOSAMPLING; + clampfactor = NurbsConsts.N_NOCLAMPING; + minsavings = NurbsConsts.N_NOSAVINGSSUBDIVISION; + s_steps = 0f; + t_steps = 0f; + + maxrate = (s_steps < 0) ? 0 : s_steps; + maxsrate = (s_steps < 0) ? 0 : s_steps; + maxtrate = (t_steps < 0) ? 0 : t_steps; + bmat = new float[MAXCOORDS][MAXCOORDS]; + cmat = new float[MAXCOORDS][MAXCOORDS]; + smat = new float[MAXCOORDS][MAXCOORDS]; + + identify(bmat); + identify(cmat); + identify(smat); + bboxsize = new float[MAXCOORDS]; + for (int i = 0; i < inhcoords; i++) + bboxsize[i] = 1; + } + + /** + * Make matrix identity matrix + * @param arr matrix + */ + private void identify(float[][] arr) { + // DONE + for (int i = 0; i < MAXCOORDS; i++) + for (int j = 0; j < MAXCOORDS; j++) + arr[i][j] = 0; + for (int i = 0; i < MAXCOORDS; i++) + arr[i][i] = 1; + + } + + /** + * Tells whether tag is property tag + * @param tag property tag + * @return is/is not property + */ + public boolean isProperty(int tag) { + boolean ret; + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + case NurbsConsts.N_ERROR_TOLERANCE: + case NurbsConsts.N_CULLING: + case NurbsConsts.N_BBOX_SUBDIVIDING: + case NurbsConsts.N_S_STEPS: + case NurbsConsts.N_T_STEPS: + case NurbsConsts.N_SAMPLINGMETHOD: + case NurbsConsts.N_CLAMPFACTOR: + case NurbsConsts.N_MINSAVINGS: + ret = true; + break; + default: + ret = false; + break; + } + return ret; + } + + /** + * Returns number of control points' coords + * @return number of control points' coords + */ + public int getNCoords() { + return ncoords; + } + + /** + * Returns map type + * @return map type + */ + public int getType() { + return type; + } + + /** + * Tells whether map is range sampling + * @return is map range sampling + */ + public boolean isRangeSampling() { + // DONE + return (isParametricDistanceSampling() || isPathLengthSampling() + || isSurfaceAreaSampling() || isObjectSpaceParaSampling() || isObjectSpacePathSampling()); + } + + /** + * Tells whether map is object space sampling + * @return is map object space sampling + */ + private boolean isObjectSpacePathSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PATH; + } + + /** + * Tells whether map is object space parasampling + * @return is map object space parasampling + */ + private boolean isObjectSpaceParaSampling() { + // DONE + return sampling_method == NurbsConsts.N_OBJECTSPACE_PARA; + } + + /** + * Tells whether map is area sampling surface + * @return is map area sampling surface + */ + private boolean isSurfaceAreaSampling() { + // DONE + return sampling_method == NurbsConsts.N_SURFACEAREA; + } + + /** + * Tells whether map is path length sampling + * @return is map path length sampling + */ + boolean isPathLengthSampling() { + // DONE + return sampling_method == NurbsConsts.N_PATHLENGTH; + } + + /** + * Tells whether map is parametric distance sampling + * @return is map parametric distance sampling + */ + boolean isParametricDistanceSampling() { + // DONE + return sampling_method == NurbsConsts.N_PARAMETRICDISTANCE; + } + + /** + * Tells whether map is culling + * @return is map culling + */ + public boolean isCulling() { + // DONE + return culling_method != NurbsConsts.N_NOCULLING ? true : false; + } + + /** + * Tells whether map is constantly sampling + * @return is map constant sampling + */ + public boolean isConstantSampling() { + return (sampling_method == NurbsConsts.N_FIXEDRATE) ? true : false; + } + + /** + * Tells whether map is domain sampling + * @return is map domain sampling + */ + public boolean isDomainSampling() { + return (sampling_method == NurbsConsts.N_DOMAINDISTANCE) ? true : false; + } + + /** + * Returns property of specified tag value + * @param tag property tag + * @return property value + */ + public float getProperty(int tag) { + // TODO Auto-generated method stub + // System.out.println("TODO mapdesc.getproperty"); + return 0; + } + + /** + * Sets property with given tag + * @param tag property tag + * @param value desired value + */ + public void setProperty(int tag, float value) { + // TODO Auto-generated method stub + switch (tag) { + case NurbsConsts.N_PIXEL_TOLERANCE: + pixel_tolerance = value; + break; + case NurbsConsts.N_ERROR_TOLERANCE: + error_tolerance = value; + break; + case NurbsConsts.N_CULLING: + culling_method = value; + break; + case NurbsConsts.N_BBOX_SUBDIVIDING: + if (value <= 0) + value = NurbsConsts.N_NOBBOXSUBDIVISION; + bbox_subdividing = value; + break; + case NurbsConsts.N_S_STEPS: + if (value < 0) + value = 0; + s_steps = value; + maxrate = value; + maxsrate = value; + break; + case NurbsConsts.N_T_STEPS: + if (value < 0) + value = 0; + t_steps = value; + maxtrate = value; + break; + case NurbsConsts.N_SAMPLINGMETHOD: + sampling_method = value; + break; + case NurbsConsts.N_CLAMPFACTOR: + if (value < 0) + value = 0; + clampfactor = value; + break; + case NurbsConsts.N_MINSAVINGS: + if (value <= 0) + value = NurbsConsts.N_NOSAVINGSSUBDIVISION; + minsavings = value; + break; + } + } + + /** + * Samples curve + * @param pts control points + * @param order curve order + * @param stride number of control points' coordinates + * @param sp breakpoints + * @param outstride output number of control points' coordinates + */ + public void xformSampling(CArrayOfFloats pts, int order, int stride, + float[] sp, int outstride) { + // DONE + xFormMat(smat, pts, order, stride, sp, outstride); + } + + /** + * Empty method + * @param mat sampling matrix + * @param pts ontrol points + * @param order curve order + * @param stride number of control points' coordinates + * @param cp breakpoints + * @param outstride output number of control points' coordinates + */ + private void xFormMat(float[][] mat, CArrayOfFloats pts, int order, + int stride, float[] cp, int outstride) { + // TODO Auto-generated method stub + + // System.out.println("TODO mapdsc.xformmat ; change cp from float[] to carrayoffloats"); + + if (isrational > 0) { + + } else { + + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java new file mode 100755 index 000000000..b23a1f665 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Maplist.java @@ -0,0 +1,122 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding list of Mapdescs + * @author Tomáš Hráský + * + */ +public class Maplist { + /** + * Head of linked list + */ + private Mapdesc maps; + + /** + * Backend class + */ + private Backend backend; + + /** + * Makes new Maplist + * @param backend Backend class + */ + public Maplist(Backend backend) { + this.backend = backend; + } + + /** + * Sets linked list beginning to null + */ + public void initialize() { + // TODO mapdespool.clear ? + maps = null; + } + + /** + * Defines new Mapdesc if it is not defined and appends it to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + public void define(int type, int rational, int ncoords) { + // DONE + Mapdesc m = locate(type); + assert (m == null || (m.isrational == rational && m.ncoords == ncoords)); + add(type, rational, ncoords); + + } + + /** + * Adds new Mapdesc to linked list + * @param type map type + * @param rational is map rational + * @param ncoords number of coords + */ + private void add(int type, int rational, int ncoords) { + // DONE + Mapdesc map = new Mapdesc(type, rational, ncoords, backend); + if (maps == null) { + maps = map; + } else { + map.next = maps; + maps = map; + } + } + + /** + * Tries to find Mapdesc in linked list + * @param type map type + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc locate(int type) { + // DONE + Mapdesc m = null; + for (m = maps; m != null; m = m.next) + if (m.getType() == type) + break; + return m; + } + + /** + * Alias for locate + * @param type maptype + * @return Mapdesc of type or null if there is no such map + */ + public Mapdesc find(int type) { + return locate(type); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java new file mode 100755 index 000000000..ee7f3b31b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/NurbsConsts.java @@ -0,0 +1,184 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class hodling NURBS constants as seen in OpenGL GLU documentation + * @author JOGL project + * + */ +public class NurbsConsts { + /* + * NURBS Properties - one set per map, each takes a single INREAL arg + */ + public static final int N_SAMPLING_TOLERANCE = 1; + + public static final int N_S_RATE = 6; + + public static final int N_T_RATE = 7; + + public static final int N_CLAMPFACTOR = 13; + + public static final float N_NOCLAMPING = 0.0f; + + public static final int N_MINSAVINGS = 14; + + public static final float N_NOSAVINGSSUBDIVISION = 0.0f; + + /* + * NURBS Properties - one set per map, each takes an enumerated value + */ + public static final int N_CULLING = 2; + + public static final float N_NOCULLING = 0.0f; + + public static final float N_CULLINGON = 1.0f; + + public static final int N_SAMPLINGMETHOD = 10; + + public static final float N_NOSAMPLING = 0.0f; + + public static final float N_FIXEDRATE = 3.0f; + + public static final float N_DOMAINDISTANCE = 2.0f; + + public static final float N_PARAMETRICDISTANCE = 5.0f; + + public static final float N_PATHLENGTH = 6.0f; + + public static final float N_SURFACEAREA = 7.0f; + + public static final float N_OBJECTSPACE_PARA = 8.0f; + + public static final float N_OBJECTSPACE_PATH = 9.0f; + + public static final int N_BBOX_SUBDIVIDING = 17; + + public static final float N_NOBBOXSUBDIVISION = 0.0f; + + public static final float N_BBOXTIGHT = 1.0f; + + public static final float N_BBOXROUND = 2.0f; + + /* + * NURBS Rendering Properties - one set per renderer each takes an + * enumerated value + */ + public static final int N_DISPLAY = 3; + + public static final int N_FILL = 1; + + public static final int N_OUTLINE_POLY = 2; + + public static final int N_OUTLINE_TRI = 3; + + public static final int N_OUTLINE_QUAD = 4; + + public static final int N_OUTLINE_PATCH = 5; + + public static final int N_OUTLINE_PARAM = 6; + + public static final int N_OUTLINE_PARAM_S = 7; + + public static final int N_OUTLINE_PARAM_ST = 8; + + public static final int N_OUTLINE_SUBDIV = 9; + + public static final int N_OUTLINE_SUBDIV_S = 10; + + public static final int N_OUTLINE_SUBDIV_ST = 11; + + public static final int N_ISOLINE_S = 12; + + public static final int N_ERRORCHECKING = 4; + + public static final int N_NOMSG = 0; + + public static final int N_MSG = 1; + + /* GL 4.0 propeties not defined above */ + + public static final int N_PIXEL_TOLERANCE = N_SAMPLING_TOLERANCE; + + public static final int N_ERROR_TOLERANCE = 20; + + public static final int N_SUBDIVISIONS = 5; + + public static final int N_TILES = 8; + + public static final int N_TMP1 = 9; + + public static final int N_TMP2 = N_SAMPLINGMETHOD; + + public static final int N_TMP3 = 11; + + public static final int N_TMP4 = 12; + + public static final int N_TMP5 = N_CLAMPFACTOR; + + public static final int N_TMP6 = N_MINSAVINGS; + + public static final int N_S_STEPS = N_S_RATE; + + public static final int N_T_STEPS = N_T_RATE; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL matrix + * argument + */ + public static final int N_CULLINGMATRIX = 1; + + public static final int N_SAMPLINGMATRIX = 2; + + public static final int N_BBOXMATRIX = 3; + + /* + * NURBS Rendering Properties - one set per map, each takes an INREAL vector + * argument + */ + public static final int N_BBOXSIZE = 4; + + /* type argument for trimming curves */ + + public static final int N_P2D = 0x8; + + public static final int N_P2DR = 0xd; + + public static final int N_MESHLINE = 1; + + public static final int N_MESHFILL = 0; + + public static final int N_MESHPOINT = 2; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java new file mode 100755 index 000000000..900f8e56f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_curve.java @@ -0,0 +1,63 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Struct holding curve links + * @author Tomáš Hráský + * + */ +public class O_curve { + + /** + * Curve type + */ + public int curvetype; + + /** + * Next curve in linked list + */ + public O_curve next; + + /** + * Curve of picewiselinear type + */ + public O_pwlcurve o_pwlcurve; + + /** + * NURBS curve + */ + public O_nurbscurve o_nurbscurve; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java new file mode 100755 index 000000000..81110813f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbscurve.java @@ -0,0 +1,80 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS curve object + * @author Tomáš Hráský + * + */ +public class O_nurbscurve { + + /** + * List of bezier curves + */ + public Quilt bezier_curves; + + /** + * Curve type + */ + public int type; + + /** + * Was curve used ? + */ + public boolean used; + + /** + * Parent curve + */ + public O_curve owner; + + /** + * Next curve in list + */ + public O_nurbscurve next; + + /** + * Makes new O_nurbscurve + * @param realType type of curve + */ + public O_nurbscurve(int realType) { + // DONE + this.type = realType; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java new file mode 100755 index 000000000..b598f525d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_nurbssurface.java @@ -0,0 +1,79 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS surface object + * @author Tomáš Hráský + * + */ +public class O_nurbssurface { + + /** + * List of bezier patches forming NURBS surface + */ + public Quilt bezier_patches; + + /** + * Was surface used + */ + public boolean used; + + /** + * Parent O_surface + */ + public O_surface owner; + + /** + * Next surface in list + */ + public O_nurbssurface next; + + /** + * Surface type + */ + private int type; + + /** + * Makes new O_nurbssurface of type + * @param type surface type + */ + public O_nurbssurface(int type) { + this.type = type; + this.owner = null; + this.next = null; + this.used = false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java new file mode 100755 index 000000000..e50f41d81 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_pwlcurve.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_pwlcurve { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java new file mode 100755 index 000000000..76ac79f0a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_surface.java @@ -0,0 +1,52 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Surface object + * @author Tomáš Hráský + * + */ +public class O_surface { + /** + * NURBS surface + */ + public O_nurbssurface o_nurbssurface; + + /** + * Trims + */ + public O_trim o_trim; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java new file mode 100755 index 000000000..17e5002df --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/O_trim.java @@ -0,0 +1,44 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomáš Hráský + * + */ +public class O_trim { + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java new file mode 100755 index 000000000..d3066cc84 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patch.java @@ -0,0 +1,54 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Empty class + * @author Tomas Hrasky + * + */ +public class Patch { + + /** + * Empty constructor + * @param q + * @param pta + * @param ptb + * @param patch + */ + public Patch(Quilt q, float[] pta, float[] ptb, Patch patch) { + // System.out.println("TODO patch.constructor"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java new file mode 100755 index 000000000..8b439a02f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Patchlist.java @@ -0,0 +1,145 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * List of patches + * @author Tomáš Hráský + * + */ +public class Patchlist { + + /** + * Array of ranges + */ + public Pspec[] pspec; + + /** + * head of list of patches + */ + private Patch patch; + + /** + * Makes new list of patches + * @param quilts list of quilts + * @param pta low border + * @param ptb high border + */ + public Patchlist(Quilt quilts, float[] pta, float[] ptb) { + // DONE + patch = null; + + for (Quilt q = quilts; q != null; q = q.next) + patch = new Patch(q, pta, ptb, patch); + pspec[0] = new Pspec(); + pspec[0].range[0] = pta[0]; + pspec[0].range[1] = ptb[0]; + pspec[0].range[2] = ptb[0] - pta[0]; + pspec[1] = new Pspec(); + pspec[1].range[0] = pta[1]; + pspec[1].range[1] = ptb[1]; + pspec[1].range[2] = ptb[1] - pta[1]; + + } + + /** + * Empty constructor + * @param patchlist + * @param param + * @param mid + */ + public Patchlist(Patchlist patchlist, int param, float mid) { + // TODO Auto-generated constructor stub + // System.out.println("TODO patchlist.konstruktor 2"); + } + + /** + * Empty method + * @return 0 + */ + public int cullCheck() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.cullcheck"); + return 0; + } + + /** + * Empty method + */ + public void getstepsize() { + // System.out.println("TODO patchlist.getsptepsize"); + // TODO Auto-generated method stub + + } + + /** + * Empty method + * @return false + */ + public boolean needsSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("patchlist.needsSamplingSubdivision"); + return false; + } + + /** + * Empty method + * @param i + * @return false + */ + public boolean needsSubdivision(int i) { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsSubdivision"); + return false; + } + + /** + * Empty method + * @return false + */ + public boolean needsNonSamplingSubdivision() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.needsNonSamplingSubdivision"); + return false; + } + + /** + * Empty method + */ + public void bbox() { + // TODO Auto-generated method stub + // System.out.println("TODO patchlist.bbox"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java new file mode 100755 index 000000000..b486a0ead --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Property.java @@ -0,0 +1,75 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class representing property + * + * @author Tomas Hrasky + * + */ +public class Property { + + /** + * Property type + */ + public int type; + + /** + * Property id + */ + public int tag; + + /** + * Property value + */ + public float value; + + /** + * Makes new property with given parameters + * + * @param type + * property type + * @param tag + * property id + * @param value + * property value + */ + public Property(int type, int tag, float value) { + this.type = type; + this.tag = tag; + this.value = value; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java new file mode 100755 index 000000000..1e60ed335 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Pspec.java @@ -0,0 +1,47 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding range + * @author Tomáš Hráský + * + */ +public class Pspec { + /** + * Range + */ + public float[] range; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java new file mode 100755 index 000000000..0c9eca91e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/PwlArc.java @@ -0,0 +1,71 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Picewiselinar trimming arc + * @author Tomáš Hráský + * + */ +public class PwlArc { + + /** + * Number of points + */ + private int npts; + + /** + * Vertexes + */ + public TrimVertex[] pts; + + /** + * Arc type + */ + private int type; + + /** + * Makes new trimming arc + * @param i num ber of vertexes + * @param p trimming vertexes array + */ + public PwlArc(int i, TrimVertex[] p) { + // DONE + this.npts = i; + this.pts = p; + type = NurbsConsts.N_P2D; + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java new file mode 100755 index 000000000..03e809d23 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quilt.java @@ -0,0 +1,282 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class for converting NURBS curves and surfaces to list of bezier arcs or patches repectively + * @author Tomáš Hráský + * + */ +public class Quilt { + /** + * Maximum quilt dimension + */ + private static final int MAXDIM = 2; + + /** + * List of map descriptions + */ + Mapdesc mapdesc; + + /** + * Array of quiltspecs pointer + */ + public CArrayOfQuiltspecs qspec; + + /** + * End array of quilt specs pointer + */ + public CArrayOfQuiltspecs eqspec; + + /** + * Control points + */ + public CArrayOfFloats cpts; + + /** + * Next quilt in list + */ + public Quilt next; + + /** + * Makes new quilt with mapdesc + * @param mapdesc map description + */ + public Quilt(Mapdesc mapdesc) { + // DONE + this.mapdesc = mapdesc; + Quiltspec[] tmpquilts = new Quiltspec[MAXDIM]; + for (int i = 0; i < tmpquilts.length; i++) + tmpquilts[i] = new Quiltspec(); + this.qspec = new CArrayOfQuiltspecs(tmpquilts); + + } + + /** + * Converts NURBS surface to bezier patches + * @param sknotvector knots in u direction + * @param tknotvector knots in v direction + * @param ctrlarr control points + * @param coords control points coords + */ + public void toBezier(Knotvector sknotvector, Knotvector tknotvector, + CArrayOfFloats ctrlarr, int coords) { + Splinespec spline = new Splinespec(2); + spline.kspecinit(sknotvector, tknotvector); + spline.select(); + spline.layout(coords); + spline.setupquilt(this); + spline.copy(ctrlarr); + spline.transform(); + } + + /** + * Converts NURBS curve to list of bezier curves + * @param knots knot vector + * @param ctlarray control points + * @param ncoords number of coordinates + */ + public void toBezier(Knotvector knots, CArrayOfFloats ctlarray, int ncoords) { + // DONE + Splinespec spline = new Splinespec(1); + spline.kspecinit(knots); + spline.select(); + spline.layout(ncoords); + spline.setupquilt(this); + spline.copy(ctlarray); + spline.transform(); + } + + /** + * Walks thru all arcs/patches + * @param pta low border + * @param ptb high border + * @param backend Backend + */ + public void downloadAll(float[] pta, float[] ptb, Backend backend) { + // DONE + for (Quilt m = this; m != null; m = m.next) { + m.select(pta, ptb); + m.download(backend); + } + + } + + /** + * Renders arcs/patches + * @param backend Backend for rendering + */ + private void download(Backend backend) { + // DONE + if (getDimension() == 2) { + + CArrayOfFloats ps = new CArrayOfFloats(cpts); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(1).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + ps.raisePointerBy(qspec.get(1).index * qspec.get(1).order + * qspec.get(1).stride); + + backend.surfpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(1).stride, qspec.get(0).order, qspec.get(1).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1], qspec + .get(1).breakpoints[qspec.get(1).index], qspec + .get(1).breakpoints[qspec.get(1).index + 1]); + + } else {// code for curves + // CArrayOfFloats ps=new CArrayOfFloats(cpts); + CArrayOfFloats ps = new CArrayOfFloats(cpts.getArray(), 0); + ps.raisePointerBy(qspec.get(0).offset); + ps.raisePointerBy(qspec.get(0).index * qspec.get(0).order + * qspec.get(0).stride); + backend.curvpts(mapdesc.getType(), ps, qspec.get(0).stride, qspec + .get(0).order, + qspec.get(0).breakpoints[qspec.get(0).index], + qspec.get(0).breakpoints[qspec.get(0).index + 1]); + } + + } + + /** + * Returns quilt dimension + * @return quilt dimesion + */ + private int getDimension() { + // DONE + return eqspec.getPointer() - qspec.getPointer(); + } + + /** + * Finds Quiltspec.index + * @param pta range + * @param ptb range + */ + private void select(float[] pta, float[] ptb) { + // DONE + int dim = eqspec.getPointer() - qspec.getPointer(); + int i, j; + for (i = 0; i < dim; i++) { + for (j = qspec.get(i).width - 1; j >= 0; j--) + if (qspec.get(i).breakpoints[j] <= pta[i] + && ptb[i] <= qspec.get(i).breakpoints[j + 1]) + break; + assert (j != -1); + qspec.get(i).index = j; + } + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param bpts breakpoints + */ + public void getRange(float[] from, float[] to, Flist bpts) { + // DONE + getRange(from, to, 0, bpts); + + } + + /** + * Find range according to breakpoints + * @param from low param + * @param to high param + * @param i from/to array index + * @param list breakpoints + */ + private void getRange(float[] from, float[] to, int i, Flist list) { + // DONE + Quilt maps = this; + from[i] = maps.qspec.get(i).breakpoints[0]; + to[i] = maps.qspec.get(i).breakpoints[maps.qspec.get(i).width]; + int maxpts = 0; + Quilt m; + for (m = maps; m != null; m = m.next) { + if (m.qspec.get(i).breakpoints[0] > from[i]) + from[i] = m.qspec.get(i).breakpoints[0]; + if (m.qspec.get(i).breakpoints[m.qspec.get(i).width] < to[i]) + to[i] = m.qspec.get(i).breakpoints[m.qspec.get(i).width]; + maxpts += m.qspec.get(i).width + 1; + } + list.grow(maxpts); + for (m = maps; m != null; m = m.next) { + for (int j = 0; j <= m.qspec.get(i).width; j++) { + list.add(m.qspec.get(i).breakpoints[j]); + } + } + list.filter(); + list.taper(from[i], to[i]); + } + + /** + * Is this quilt culled + * @return 0 or Subdivider.CULL_ACCEPT + */ + public int isCulled() { + if (mapdesc.isCulling()) { + // System.out.println("TODO quilt.isculled mapdesc.isculling"); + return 0; + } else { + return Subdivider.CULL_ACCEPT; + } + } + + /** + * Finds range for surface + * @param from low param + * @param to high param + * @param slist u direction breakpoints + * @param tlist v direction breakpoints + */ + public void getRange(float[] from, float[] to, Flist slist, Flist tlist) { + // DONE + getRange(from, to, 0, slist); + getRange(from, to, 1, tlist); + + } + + /** + * Empty method + * @param sbrkpts + * @param tbrkpts + * @param rate + */ + public void findRates(Flist sbrkpts, Flist tbrkpts, float[] rate) { + // TODO Auto-generated method stub + // System.out.println("TODO quilt.findrates"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java new file mode 100755 index 000000000..6c8e55e06 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Quiltspec.java @@ -0,0 +1,85 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Quilt definition + * @author Tomas Hrasky + * + */ +public class Quiltspec { + + /** + * Stride between control points + */ + public int stride; + + /** + * Quilt width in breakpoints + */ + public int width; + + /** + * Quilt order + */ + public int order; + + /** + * Start offset + */ + public int offset; + + /** + * Breakpoint index + */ + public int index; + + /** + * Boundary + */ + public int[] bdry; + + /** + * Breakpoints + */ + public float[] breakpoints; + + /** + * Makes new quiltspec + */ + public Quiltspec() { + this.bdry = new int[2]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt new file mode 100755 index 000000000..89630c71e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/README.txt @@ -0,0 +1,59 @@ +Unimplemented functionality + - tesselation and callbacks + - trimming + - setting NURBS properties (-> sampling etc.) +Differences from C++ source + - no pooling + - pointers to arrays are replaced by CArrayOf... classes and their methods +Unimplemented or incomplete "calltree top" methods (according to glu.def in Mesa 6.5) + gluBeginTrim + gluDeleteNurbsRenderer - won't be needed + gluEndTrim + gluGetNurbsProperty + gluLoadSamplingMatrices + gluNurbsCallback + gluNurbsCallbackData + gluNurbsCallbackDataEXT + gluNurbsCurve - TODO type switch + gluNurbsProperty + gluPwlCurve + gluQuadricCallback - not a NURBS method +As of files + - Arc[ST]dirSorter.java - unimplemented (part of tesselation) + - Backend.java:194 - wireframe quads - part of tesselation/callback + - Curve.java:141-204 - culling + - DisplayList.java:57 - append to DL - not sure whether it will be needed + - GLUnurbs.java :443,484 - error values + :445 - trimming + :512 - error handling (callback) + :530 - loadGLmatrices + :786 - nuid - nurbs object id - won't be needed I think + :803 - end trim + - GLUwNURBS.java:68,176 - NUBRS properties + - Knotspec.java :371 - copying in general case (more than 4 coords) + :517 - copying with more than 4 coords + :556 - pt_oo_sum default + - Knotvector.java:165 - show method (probably debugging) + - Mapdesc.java :354 - get property + :435 - xFormMat - change param cp to CArrayOfFloats; probably sampling functionality + - Maplist.java:68 - clear ? + - OpenGLCurveEvaluator.java :132 - tess./callback code + :168 - mapgrid1f + :190 - tess./callback code (output triangles) + - OpenGLSurfaceEvaluator.java :77 . tess./callback code + :81 - glGetIntegerValue + :114 - tess./callback code + :117 - Level of detail + :144,161,201 - tess./callback code - output triangles + - Patch.java:55 - constructor stuff ? + - Patchlist.java:55 - constructor stuff ? + :97 - cull check + :105 - step size + :115 - need of sampling subdivision + :126 - need of subdivision + :137 - need of non sampling subd. + :146 - bbox (??) + -Quilt.java :254 - culling + :282 - rates + -Subdivider.java - all TODOs - it's stuff about trimming probably + :545 - jumpbuffer - not sure purpose it exactly served in original source diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java new file mode 100755 index 000000000..d1a23fbab --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Renderhints.java @@ -0,0 +1,128 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class holding rendering params + * @author Tomas Hrasky + * + */ +public class Renderhints { + + /** + * Check for errors + */ + public int errorchecking; + + /** + * Maximum subdivisions + */ + public int maxsubdivisions; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * Display method + */ + int display_method; + + /** + * Output triangles + */ + int wiretris; + + /** + * Output quads + */ + int wirequads; + + /** + * Makes new Renderinghints + */ + public Renderhints() { + display_method = NurbsConsts.N_FILL; + errorchecking = NurbsConsts.N_MSG; + subdivisions = 6; + // tmp1=0; + } + + /** + * Set property value + * @param prop property + */ + public void setProperty(Property prop) { + switch (prop.type) { + case NurbsConsts.N_DISPLAY: + display_method = (int) prop.value; + break; + case NurbsConsts.N_ERRORCHECKING: + errorchecking = (int) prop.value; + break; + case NurbsConsts.N_SUBDIVISIONS: + subdivisions = (int) prop.value; + break; + default: + // abort - end program + break; + } + } + + /** + * Initialization + */ + public void init() { + // DONE + maxsubdivisions = subdivisions; + if (maxsubdivisions < 0) + maxsubdivisions = 0; + + if (display_method == NurbsConsts.N_FILL) { + wiretris = 0; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_TRI) { + wiretris = 1; + wirequads = 0; + } else if (display_method == NurbsConsts.N_OUTLINE_QUAD) { + wiretris = 0; + wirequads = 1; + } else { + wiretris = 1; + wirequads = 1; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java new file mode 100755 index 000000000..487b47f2d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Splinespec.java @@ -0,0 +1,204 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * NURBS definition + * @author Tomas Hrasky + * + */ +public class Splinespec { + + /** + * Dimension + */ + private int dim; + + /** + * Knot vector specs + */ + private Knotspec kspec; + + /** + * Control points after conversion + */ + private CArrayOfFloats outcpts; + + /** + * Makes new Splinespec with given dimension + * @param i dimension + */ + public Splinespec(int i) { + // DONE + this.dim = i; + } + + /** + * Initializes knotspec according to knotvector + * @param knotvector basic knotvector + */ + public void kspecinit(Knotvector knotvector) { + // DONE + this.kspec = new Knotspec(); + kspec.inkbegin = new CArrayOfFloats(knotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(knotvector.knotlist, + knotvector.knotcount); + kspec.prestride = knotvector.stride; + kspec.order = knotvector.order; + kspec.next = null; + } + + /** + * Initializes knotspec according to knotvector - SURFACE + * @param sknotvector knotvector in u dir + * @param tknotvector knotvector in v dir + */ + public void kspecinit(Knotvector sknotvector, Knotvector tknotvector) { + // DONE + this.kspec = new Knotspec(); + Knotspec tkspec = new Knotspec(); + + kspec.inkbegin = new CArrayOfFloats(sknotvector.knotlist, 0); + kspec.inkend = new CArrayOfFloats(sknotvector.knotlist, + sknotvector.knotcount); + kspec.prestride = sknotvector.stride; + kspec.order = sknotvector.order; + kspec.next = tkspec; + + tkspec.inkbegin = new CArrayOfFloats(tknotvector.knotlist, 0); + tkspec.inkend = new CArrayOfFloats(tknotvector.knotlist, + tknotvector.knotcount); + tkspec.prestride = tknotvector.stride; + tkspec.order = tknotvector.order; + tkspec.next = null; + } + + /** + * Preselect and select knotspecs + */ + public void select() { + // DONE + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.preselect(); + knotspec.select(); + } + + } + + /** + * Prepares for conversion + * @param ncoords number of coords + */ + public void layout(int ncoords) { + // DONE + int stride = ncoords; + for (Knotspec knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + knotspec.poststride = stride; + stride *= (knotspec.bend.getPointer() - knotspec.bbegin + .getPointer()) + * knotspec.order + knotspec.postoffset; + knotspec.preoffset *= knotspec.prestride; + knotspec.prewidth *= knotspec.poststride; + knotspec.postwidth *= knotspec.poststride; + knotspec.postoffset *= knotspec.poststride; + knotspec.ncoords = ncoords; + } + outcpts = new CArrayOfFloats(new float[stride]); + + } + + /** + * Prepares quilt for conversion + * @param quilt quilt to work with + */ + public void setupquilt(Quilt quilt) { + // DONE + CArrayOfQuiltspecs qspec = new CArrayOfQuiltspecs(quilt.qspec); + quilt.eqspec = new CArrayOfQuiltspecs(qspec.getArray(), dim); + for (Knotspec knotspec = kspec; knotspec != null;) { + qspec.get().stride = knotspec.poststride; + qspec.get().width = knotspec.bend.getPointer() + - knotspec.bbegin.getPointer(); + qspec.get().order = knotspec.order; + qspec.get().offset = knotspec.postoffset; + qspec.get().index = 0; + qspec.get().bdry[0] = (knotspec.kleft.getPointer() == knotspec.kfirst + .getPointer()) ? 1 : 0; + qspec.get().bdry[1] = (knotspec.kright.getPointer() == knotspec.klast + .getPointer()) ? 1 : 0; + qspec.get().breakpoints = new float[qspec.get().width + 1]; + CArrayOfFloats k = new CArrayOfFloats(qspec.get().breakpoints, 0); + for (CArrayOfBreakpts bk = new CArrayOfBreakpts(knotspec.bbegin); bk + .getPointer() <= knotspec.bend.getPointer(); bk.pp()) { + k.set(bk.get().value); + k.pp(); + } + knotspec = knotspec.next; + if (knotspec != null) + qspec.pp(); + } + quilt.cpts = new CArrayOfFloats(outcpts); + quilt.next = null; + } + + /** + * Copies array of control points to output array + * @param ctlarray control points array + */ + public void copy(CArrayOfFloats ctlarray) { + // DONE + kspec.copy(ctlarray, outcpts); + + } + + /** + * Transforms knotspecs - conversion + */ + public void transform() { + // DONE + Knotspec knotspec; + outcpts.setPointer(0); + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) + knotspec.istransformed = false; + + for (knotspec = kspec; knotspec != null; knotspec = knotspec.next) { + for (Knotspec kspec2 = kspec; kspec2 != null; kspec2 = kspec2.next) + kspec2.kspectotrans = knotspec; + kspec.transform(outcpts); + knotspec.istransformed = true; + } + + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java new file mode 100755 index 000000000..99c1b740b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/Subdivider.java @@ -0,0 +1,1167 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class working with curves and surfaces + * @author Tomas Hrasky + * + */ +public class Subdivider { + /** + * Cull type + */ + public static final int CULL_TRIVIAL_REJECT = 0; + + /** + * Cull type + */ + public static final int CULL_ACCEPT = 1; + + /** + * Maximum trimming arcs + */ + private static final int MAXARCS = 10; + + /** + * Linked list of Quilts + */ + Quilt qlist; + + /** + * Object holding rendering honts information + */ + private Renderhints renderhints; + + /** + * Backend object + */ + private Backend backend; + + /** + * Number of subdivisions + */ + private int subdivisions; + + /** + * U step when using domain distance sampling + */ + private float domain_distance_u_rate; + + /** + * Use domain distance sampling + */ + private int is_domain_distance_sampling; + + /** + * Initial class holding trimming arcs + */ + private Bin initialbin; + + /** + * Not used + */ + private boolean showDegenerate; + + /** + * Is triming arc type bezier arc + */ + private boolean isArcTypeBezier; + + /** + * Breakpoints in v direction + */ + private Flist tpbrkpts; + + /** + * Breakpoints in u direction + */ + private Flist spbrkpts; + + /** + * Unused + */ + private int s_index; + + /** + * Head of linked list of trimming arcs + */ + private Arc pjarc; + + /** + * Class tesselating trimming arcs + */ + private ArcTesselator arctesselator; + + /** + * Unused + */ + private int t_index; + + /** + * Breakpoints + */ + private Flist smbrkpts; + + /** + * Not used + */ + private float[] stepsizes; + + /** + * Domain distance in V direction + */ + private float domain_distance_v_rate; + + /** + * Initializes quilt list + */ + public void beginQuilts(Backend backend) { + // DONE + qlist = null; + renderhints = new Renderhints(); + this.backend = backend; + + initialbin = new Bin(); + arctesselator = new ArcTesselator(); + } + + /** + * Adds quilt to linked list + * @param quilt added quilt + */ + public void addQuilt(Quilt quilt) { + // DONE + if (qlist == null) + qlist = quilt; + else { + quilt.next = qlist; + qlist = quilt; + } + + } + + /** + * Empty method + */ + public void endQuilts() { + // DONE + } + + /** + * Draws a surface + */ + public void drawSurfaces() { + renderhints.init(); + + if (qlist == null) { + // System.out.println("qlist is null"); + return; + } + + for (Quilt q = qlist; q != null; q = q.next) { + if (q.isCulled() == CULL_TRIVIAL_REJECT) { + freejarcs(initialbin); + return; + } + } + + float[] from = new float[2]; + float[] to = new float[2]; + + spbrkpts = new Flist(); + tpbrkpts = new Flist(); + qlist.getRange(from, to, spbrkpts, tpbrkpts); + + boolean optimize = (is_domain_distance_sampling > 0 && (renderhints.display_method != NurbsConsts.N_OUTLINE_PATCH)); + + // TODO decide whether to optimize (when there is gluNurbsProperty implemented) + optimize = true; + + if (!initialbin.isnonempty()) { + if (!optimize) { + makeBorderTrim(from, to); + } + } else { + float[] rate = new float[2]; + qlist.findRates(spbrkpts, tpbrkpts, rate); + // System.out.println("subdivider.drawsurfaces decompose"); + } + + backend.bgnsurf(renderhints.wiretris, renderhints.wirequads); + + // TODO partition test + + if (!initialbin.isnonempty() && optimize) { + + int i, j; + int num_u_steps; + int num_v_steps; + for (i = spbrkpts.start; i < spbrkpts.end - 1; i++) { + for (j = tpbrkpts.start; j < tpbrkpts.end - 1; j++) { + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[i]; + ptb[0] = spbrkpts.pts[i + 1]; + pta[1] = tpbrkpts.pts[j]; + ptb[1] = tpbrkpts.pts[j + 1]; + qlist.downloadAll(pta, ptb, backend); + + num_u_steps = (int) (domain_distance_u_rate * (ptb[0] - pta[0])); + num_v_steps = (int) (domain_distance_v_rate * (ptb[1] - pta[1])); + + if (num_u_steps <= 0) + num_u_steps = 1; + if (num_v_steps <= 0) + num_v_steps = 1; + + backend.surfgrid(pta[0], ptb[0], num_u_steps, ptb[1], + pta[1], num_v_steps); + backend.surfmesh(0, 0, num_u_steps, num_v_steps); + + } + } + + } else + + subdivideInS(initialbin); + + backend.endsurf(); + } + + /** + * Empty method + * @param initialbin2 + */ + private void freejarcs(Bin initialbin2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.freejarcs"); + } + + /** + * Subdivide in U direction + * @param source Trimming arcs source + */ + private void subdivideInS(Bin source) { + // DONE + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + splitInS(source, spbrkpts.start, spbrkpts.end); + } + + } + + /** + * Split in U direction + * @param source Trimming arcs source + * @param start breakpoints start + * @param end breakpoints end + */ + private void splitInS(Bin source, int start, int end) { + // DONE + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + + split(source, left, right, 0, spbrkpts.pts[i]); + splitInS(left, start, i); + splitInS(right, i + 1, end); + } else { + if (start == spbrkpts.start || start == spbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_S) { + outline(source); + freejarcs(source); + } else { + setArcTypeBezier(); + setNonDegenerate(); + s_index = start; + splitInT(source, tpbrkpts.start, tpbrkpts.end); + } + } + } else{ + // System.out.println("Source is empty - subdivider.splitins"); + } + } + + /** + * Split in V direction + * @param source + * @param start + * @param end + */ + private void splitInT(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.splitint"); + + if (source.isnonempty()) { + if (start != end) { + int i = start + (end - start) / 2; + Bin left = new Bin(); + Bin right = new Bin(); + split(source, left, right, 1, tpbrkpts.pts[i + 1]); + splitInT(left, start, i); + splitInT(right, i + 1, end); + } else { + if (start == tpbrkpts.start || start == tpbrkpts.end) { + freejarcs(source); + } else if (renderhints.display_method == NurbsConsts.N_OUTLINE_PARAM_ST) { + outline(source); + freejarcs(source); + } else { + t_index = start; + setArcTypeBezier(); + setDegenerate(); + + float[] pta = new float[2]; + float[] ptb = new float[2]; + + pta[0] = spbrkpts.pts[s_index - 1]; + pta[1] = tpbrkpts.pts[t_index - 1]; + + ptb[0] = spbrkpts.pts[s_index]; + ptb[1] = tpbrkpts.pts[t_index]; + qlist.downloadAll(pta, ptb, backend); + + Patchlist patchlist = new Patchlist(qlist, pta, ptb); + + samplingSplit(source, patchlist, + renderhints.maxsubdivisions, 0); + setNonDegenerate(); + setArcTypeBezier(); + } + } + } + + } + + /** + * Sample + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void samplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (!source.isnonempty()) + return; + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) { + freejarcs(source); + return; + } + + patchlist.getstepsize(); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_PATCH) { + tesselation(source, patchlist); + outline(source); + freejarcs(source); + return; + } + + tesselation(source, patchlist); + if (patchlist.needsSamplingSubdivision() && subdivisions > 0) { + if (!patchlist.needsSubdivision(0)) { + param = 1; + } else if (patchlist.needsSubdivision(1)) + param = 0; + else + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + samplingSplit(left, subpatchlist, subdivisions - 1, param); + samplingSplit(right, subpatchlist, subdivisions - 1, param); + } else { + setArcTypePwl(); + setDegenerate(); + nonSamplingSplit(source, patchlist, subdivisions, param); + setDegenerate(); + setArcTypeBezier(); + } + } + + /** + * Not used + * @param source + * @param patchlist + * @param subdivisions + * @param param + */ + private void nonSamplingSplit(Bin source, Patchlist patchlist, + int subdivisions, int param) { + // DONE + if (patchlist.needsNonSamplingSubdivision() && subdivisions > 0) { + param = 1 - param; + + Bin left = new Bin(); + Bin right = new Bin(); + + float mid = (float) ((patchlist.pspec[param].range[0] + patchlist.pspec[param].range[1]) * .5); + split(source, left, right, param, mid); + Patchlist subpatchlist = new Patchlist(patchlist, param, mid); + if (left.isnonempty()) { + if (subpatchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(left); + else + nonSamplingSplit(left, subpatchlist, subdivisions - 1, + param); + } + if (right.isnonempty()) { + if (patchlist.cullCheck() == CULL_TRIVIAL_REJECT) + freejarcs(right); + else + nonSamplingSplit(right, subpatchlist, subdivisions - 1, + param); + } + } else { + patchlist.bbox(); + backend.patch(patchlist.pspec[0].range[0], + patchlist.pspec[0].range[1], patchlist.pspec[1].range[0], + patchlist.pspec[1].range[1]); + if (renderhints.display_method == NurbsConsts.N_OUTLINE_SUBDIV) { + outline(source); + freejarcs(source); + } else { + setArcTypePwl(); + setDegenerate(); + findIrregularS(source); + monosplitInS(source, smbrkpts.start, smbrkpts.end); + } + } + + } + + /** + * Not used + * @param source + * @param start + * @param end + */ + private void monosplitInS(Bin source, int start, int end) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.monosplitins"); + } + + /** + * Not used + * @param source + */ + private void findIrregularS(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.findIrregularS"); + } + + /** + * Not used + */ + private void setArcTypePwl() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setarctypepwl"); + } + + /** + * Not used + * @param source + * @param patchlist + */ + private void tesselation(Bin source, Patchlist patchlist) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.tesselation"); + } + + /** + * Not used + */ + private void setDegenerate() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.setdegenerate"); + } + + /** + * Not used + * @param bin + * @param left + * @param right + * @param param + * @param value + */ + private void split(Bin bin, Bin left, Bin right, int param, float value) { + // DONE + Bin intersections = new Bin(); + Bin unknown = new Bin(); + + partition(bin, left, intersections, right, unknown, param, value); + + int count = intersections.numarcs(); + // TODO jumpbuffer ?? + + if (count % 2 == 0) { + + Arc[] arclist = new Arc[MAXARCS]; + CArrayOfArcs list; + if (count >= MAXARCS) { + list = new CArrayOfArcs(new Arc[count]); + } else { + list = new CArrayOfArcs(arclist); + } + + CArrayOfArcs last, lptr; + Arc jarc; + + for (last = new CArrayOfArcs(list); (jarc = intersections + .removearc()) != null; last.pp()) + last.set(jarc); + + if (param == 0) {// sort into incrasing t order + ArcSdirSorter sorter = new ArcSdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_s(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_s(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.pp()) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } else {// sort into decreasing s order + ArcTdirSorter sorter = new ArcTdirSorter(this); + sorter.qsort(list, count); + + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + check_t(lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() < last + .getPointer(); lptr.raisePointerBy(2)) + join_t(left, right, lptr.get(), lptr.getRelative(1)); + for (lptr = new CArrayOfArcs(list); lptr.getPointer() != last + .getPointer(); lptr.raisePointerBy(2)) { + if (lptr.get().head()[0] <= value + && lptr.get().tail()[0] <= value) + left.addarc(lptr.get()); + else + right.addarc(lptr.get()); + } + + } + + unknown.adopt(); + } + } + + /** + * Not used + * @param left + * @param right + * @param arc + * @param relative + */ + private void join_t(Bin left, Bin right, Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.join_t"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_t(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_t"); + } + + /** + * Not used + * @param left + * @param right + * @param jarc1 + * @param jarc2 + */ + private void join_s(Bin left, Bin right, Arc jarc1, Arc jarc2) { + // DONE + if (!jarc1.getitail()) + jarc1 = jarc1.next; + if (!jarc2.getitail()) + jarc2 = jarc2.next; + + float s = jarc1.tail()[0]; + float t1 = jarc1.tail()[1]; + float t2 = jarc2.tail()[1]; + + if (t1 == t2) { + simplelink(jarc1, jarc2); + } else { + Arc newright = new Arc(Arc.ARC_RIGHT); + Arc newleft = new Arc(Arc.ARC_LEFT); + if (isBezierArcType()) { + arctesselator.bezier(newright, s, s, t1, t2); + arctesselator.bezier(newleft, s, s, t2, t1); + } else { + arctesselator.pwl_right(newright, s, t1, t2, stepsizes[0]); + arctesselator.pwl_left(newright, s, t2, t1, stepsizes[2]); + } + link(jarc1, jarc2, newright, newleft); + left.addarc(newright); + right.addarc(newleft); + } + + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + * @param newright + * @param newleft + */ + private void link(Arc jarc1, Arc jarc2, Arc newright, Arc newleft) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.link"); + } + + /** + * Not used + * @return true + */ + private boolean isBezierArcType() { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.isbezierarc"); + return true; + } + + /** + * Not used + * @param jarc1 + * @param jarc2 + */ + private void simplelink(Arc jarc1, Arc jarc2) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.simplelink"); + } + + /** + * Not used + * @param arc + * @param relative + */ + private void check_s(Arc arc, Arc relative) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.check_s"); + + } + + /** + * Not used + * @param bin + * @param left + * @param intersections + * @param right + * @param unknown + * @param param + * @param value + */ + private void partition(Bin bin, Bin left, Bin intersections, Bin right, + Bin unknown, int param, float value) { + + Bin headonleft = new Bin(); + Bin headonright = new Bin(); + Bin tailonleft = new Bin(); + Bin tailonright = new Bin(); + + for (Arc jarc = bin.removearc(); jarc != null; jarc = bin.removearc()) { + float tdiff = jarc.tail()[param] - value; + float hdiff = jarc.head()[param] - value; + + if (tdiff > 0) { + if (hdiff > 0) { + right.addarc(jarc); + } else if (hdiff == 0) { + tailonright.addarc(jarc); + } else { + Arc jtemp; + switch (arc_split(jarc, param, value, 0)) { + case 2: + tailonright.addarc(jarc); + headonleft.addarc(jarc.next); + break; + // TODO rest cases + default: + System.out + .println("TODO subdivider.partition rest cases"); + break; + } + } + } else if (tdiff == 0) { + if (hdiff > 0) { + headonright.addarc(jarc); + } else if (hdiff == 0) { + unknown.addarc(jarc); + } else { + headonright.addarc(jarc); + } + } else { + if (hdiff > 0) { + // TODO rest + // System.out.println("TODO subdivider.partition rest of else"); + } else if (hdiff == 0) { + tailonleft.addarc(jarc); + } else { + left.addarc(jarc); + } + } + + } + if (param == 0) { + classify_headonleft_s(headonleft, intersections, left, value); + classify_tailonleft_s(tailonleft, intersections, left, value); + classify_headonright_s(headonright, intersections, right, value); + classify_tailonright_s(tailonright, intersections, right, value); + } else { + classify_headonleft_t(headonleft, intersections, left, value); + classify_tailonleft_t(tailonleft, intersections, left, value); + classify_headonright_t(headonright, intersections, right, value); + classify_tailonright_t(tailonright, intersections, right, value); + } + } + + /** + * Not used + * @param tailonright + * @param intersections + * @param right + * @param value + */ + private void classify_tailonright_t(Bin tailonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonright_t"); + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonleft_s(Bin bin, Bin in, Bin out, float val) { + + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + in.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + out.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sr(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO ccwTurn_sr"); + return false; + } + + /** + * Not used + * @param headonright + * @param intersections + * @param right + * @param value + */ + private void classify_headonright_t(Bin headonright, Bin intersections, + Bin right, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_headonright_t"); + } + + /** + * Not used + * @param tailonleft + * @param intersections + * @param left + * @param value + */ + private void classify_tailonleft_t(Bin tailonleft, Bin intersections, + Bin left, float value) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.classify_tailonleft_t"); + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_t(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[1] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_tl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[0] > j.prev.head()[0]) + out.addarc(j); + else + in.addarc(j); + } + } + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_tl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_tl"); + return false; + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_tailonright_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.clearitail(); + + float diff = j.next.head()[0] - val; + if (diff > 0) { + if (ccwTurn_sr(j, j.next)) + out.addarc(j); + else + in.addarc(j); + } else if (diff < 0) { + in.addarc(j); + } else { + if (j.next.tail()[1] > j.next.head()[1]) + out.addarc(j); + else + in.addarc(j); + } + } + + } + + /** + * Not used + * @param bin + * @param in + * @param out + * @param val + */ + private void classify_headonleft_s(Bin bin, Bin in, Bin out, float val) { + // DONE + Arc j; + while ((j = bin.removearc()) != null) { + j.setitail(); + + float diff = j.prev.tail()[0] - val; + if (diff > 0) { + out.addarc(j); + } else if (diff < 0) { + if (ccwTurn_sl(j.prev, j)) + out.addarc(j); + else + in.addarc(j); + } else { + if (j.prev.tail()[1] > j.prev.head()[1]) + in.addarc(j); + else + out.addarc(j); + } + } + + } + + /** + * Not used + * @param prev + * @param j + * @return false + */ + private boolean ccwTurn_sl(Arc prev, Arc j) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.ccwTurn_sl"); + return false; + } + + /** + * Not used + * @param jarc + * @param param + * @param value + * @param i + * @return 0 + */ + private int arc_split(Arc jarc, int param, float value, int i) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.arc_split"); + return 0; + } + + /** + * Not used + */ + private void setNonDegenerate() { + // DONE + this.showDegenerate = false; + + } + + /** + * sets trimming arc default type to bezier + */ + private void setArcTypeBezier() { + // DONE + isArcTypeBezier = true; + } + + /** + * Not used + * @param source + */ + private void outline(Bin source) { + // TODO Auto-generated method stub + // System.out.println("TODO subdivider.outline"); + } + + /** + * Makes default trim along surface borders + * @param from range beginnings + * @param to range ends + */ + private void makeBorderTrim(float[] from, float[] to) { + // DONE + float smin = from[0]; + float smax = to[0]; + + float tmin = from[1]; + float tmax = to[1]; + + pjarc = null; + Arc jarc = null; + + jarc = new Arc(Arc.ARC_BOTTOM); + arctesselator.bezier(jarc, smin, smax, tmin, tmin); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_RIGHT); + arctesselator.bezier(jarc, smax, smax, tmin, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_TOP); + arctesselator.bezier(jarc, smax, smin, tmax, tmax); + initialbin.addarc(jarc); + pjarc = jarc.append(pjarc); + + jarc = new Arc(Arc.ARC_LEFT); + arctesselator.bezier(jarc, smin, smin, tmax, tmin); + initialbin.addarc(jarc); + jarc = jarc.append(pjarc); + + // assert (jarc.check() == true); + } + + /** + * Draws NURBS curve + */ + public void drawCurves() { + // DONE + float[] from = new float[1]; + float[] to = new float[1]; + + Flist bpts = new Flist(); + qlist.getRange(from, to, bpts); + + renderhints.init(); + + backend.bgncurv(); + + for (int i = bpts.start; i < bpts.end - 1; i++) { + float[] pta = new float[1]; + float[] ptb = new float[1]; + pta[0] = bpts.pts[i]; + ptb[0] = bpts.pts[i + 1]; + + qlist.downloadAll(pta, ptb, backend); + Curvelist curvelist = new Curvelist(qlist, pta, ptb); + samplingSplit(curvelist, renderhints.maxsubdivisions); + } + backend.endcurv(); + } + + /** + * Samples a curve in case of need, or sends curve to backend + * @param curvelist list of curves + * @param maxsubdivisions maximum number of subdivisions + */ + private void samplingSplit(Curvelist curvelist, int maxsubdivisions) { + if (curvelist.cullCheck() == CULL_TRIVIAL_REJECT) + return; + + curvelist.getstepsize(); + + if (curvelist.needsSamplingSubdivision() && (subdivisions > 0)) { + // TODO kód + // System.out.println("TODO subdivider-needsSamplingSubdivision"); + } else { + int nu = (int) (1 + curvelist.range[2] / curvelist.stepsize); + backend.curvgrid(curvelist.range[0], curvelist.range[1], nu); + backend.curvmesh(0, nu); + } + + } + + /** + * Sets new domain_distance_u_rate value + * @param d new domain_distance_u_rate value + + */ + public void set_domain_distance_u_rate(double d) { + // DONE + domain_distance_u_rate = (float) d; + } + + /** + * Sets new domain_distance_v_rate value + * @param d new domain_distance_v_rate value + */ + public void set_domain_distance_v_rate(double d) { + // DONE + domain_distance_v_rate = (float) d; + } + + /** + * Sets new is_domain_distance_sampling value + * @param i new is_domain_distance_sampling value + */ + public void set_is_domain_distance_sampling(int i) { + // DONE + this.is_domain_distance_sampling = i; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java new file mode 100755 index 000000000..fe23f9c08 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/SurfaceEvaluator.java @@ -0,0 +1,111 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Class rendering surfaces with OpenGL + * @author Tomas Hrasky + * + */ +public interface SurfaceEvaluator { + + /** + * Pushes eval bit + */ + public void bgnmap2f() ; + + /** + * Sets glPolygonMode + * @param style polygon mode (N_MESHFILL/N_MESHLINE/N_MESHPOINT) + */ + public void polymode(int style) ; + + /** + * Pops all attributes + */ + public void endmap2f() ; + + /** + * Empty method + * @param ulo + * @param uhi + * @param vlo + * @param vhi + */ + public void domain2f(float ulo, float uhi, float vlo, float vhi) ; + + /** + * Defines 2D mesh + * @param nu number of steps in u direction + * @param u0 lowest u + * @param u1 highest u + * @param nv number of steps in v direction + * @param v0 lowest v + * @param v1 highest v + */ + public void mapgrid2f(int nu, float u0, float u1, int nv, float v0, float v1) ; + + /** + * Evaluates surface + * @param style surface style + * @param umin minimum U + * @param umax maximum U + * @param vmin minimum V + * @param vmax maximum V + */ + public void mapmesh2f(int style, int umin, int umax, int vmin, int vmax) ; + + /** + * Initializes evaluator + * @param type surface type + * @param ulo lowest u + * @param uhi highest u + * @param ustride number of objects between control points in u direction + * @param uorder surface order in u direction + * @param vlo lowest v + * @param vhi highest v + * @param vstride number of control points' coords + * @param vorder surface order in v direction + * @param pts control points + */ + public void map2f(int type, float ulo, float uhi, int ustride, int uorder, + float vlo, float vhi, int vstride, int vorder, CArrayOfFloats pts) ; + + /** + * Calls opengl enable + * @param type what to enable + */ + public void enable(int type) ; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java new file mode 100755 index 000000000..6608f8f40 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/nurbs/TrimVertex.java @@ -0,0 +1,56 @@ +package com.jogamp.opengl.impl.glu.nurbs; + +/* + ** License Applicability. Except to the extent portions of this file are + ** made subject to an alternative license as permitted in the SGI Free + ** Software License B, Version 2.0 (the "License"), the contents of this + ** file are subject only to the provisions of the License. You may not use + ** this file except in compliance with the License. You may obtain a copy + ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + ** + ** http://oss.sgi.com/projects/FreeB + ** + ** Note that, as provided in the License, the Software is distributed on an + ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + ** + ** Original Code. The Original Code is: OpenGL Sample Implementation, + ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + ** Copyright in any portions created by third parties is as indicated + ** elsewhere herein. All Rights Reserved. + ** + ** Additional Notice Provisions: The application programming interfaces + ** established by SGI in conjunction with the Original Code are The + ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + ** Window System(R) (Version 1.3), released October 19, 1998. This software + ** was created using the OpenGL(R) version 1.2.1 Sample Implementation + ** published by SGI, but has not been independently verified as being + ** compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +/** + * Holds vertex used in trim + * + * @author Tomas Hrasky + * + */ +public class TrimVertex { + + /** + * Trim vertex coords + */ + public float[] param; + + /** + * Makes new empty trim vertex + */ + public TrimVertex() { + param = new float[2]; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java new file mode 100644 index 000000000..21b15f4d4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/registry/Registry.java @@ -0,0 +1,79 @@ +/* + * License Applicability. Except to the extent portions of this file are + * made subject to an alternative license as permitted in the SGI Free + * Software License B, Version 2.0 (the "License"), the contents of this + * file are subject only to the provisions of the License. You may not use + * this file except in compliance with the License. You may obtain a copy + * of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 + * Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: + * + * http://oss.sgi.com/projects/FreeB + * + * Note that, as provided in the License, the Software is distributed on an + * "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS + * DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND + * CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A + * PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * + * NOTE: The Original Code (as defined below) has been licensed to Sun + * Microsystems, Inc. ("Sun") under the SGI Free Software License B + * (Version 1.1), shown above ("SGI License"). Pursuant to Section + * 3.2(3) of the SGI License, Sun is distributing the Covered Code to + * you under an alternative license ("Alternative License"). This + * Alternative License includes all of the provisions of the SGI License + * except that Section 2.2 and 11 are omitted. Any differences between + * the Alternative License and the SGI License are offered solely by Sun + * and not by SGI. + * + * Original Code. The Original Code is: OpenGL Sample Implementation, + * Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, + * Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. + * Copyright in any portions created by third parties is as indicated + * elsewhere herein. All Rights Reserved. + * + * Additional Notice Provisions: The application programming interfaces + * established by SGI in conjunction with the Original Code are The + * OpenGL(R) Graphics System: A Specification (Version 1.2.1), released + * April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version + * 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X + * Window System(R) (Version 1.3), released October 19, 1998. This software + * was created using the OpenGL(R) version 1.2.1 Sample Implementation + * published by SGI, but has not been independently verified as being + * compliant with the OpenGL(R) version 1.2.1 Specification. + */ + +package com.jogamp.opengl.impl.glu.registry; + +import javax.media.opengl.glu.GLU; + +/** + * + * @author Administrator + */ +public class Registry { + + /** Creates a new instance of Registry */ + public Registry() { + } + + public static String gluGetString(int name) { + if( name == GLU.GLU_VERSION ) { + return( "1.3" ); + } else if( name == GLU.GLU_EXTENSIONS ) { + return( "GLU_EXT_nurbs_tessellator GLU_EXT_object_space_tess " ); + } + return( null ); + } + + public static boolean gluCheckExtension( String extName, String extString ) { + if( extName == null || extString == null ) { + return( false ); + } + if ((extString.indexOf(extName + " ") >= 0) || + extString.endsWith(extName) || + extString.equals(extName)) { + return true; + } + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java new file mode 100644 index 000000000..85397dd6a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/ActiveRegion.java @@ -0,0 +1,69 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + + +class ActiveRegion { + GLUhalfEdge eUp; /* upper edge, directed right to left */ + DictNode nodeUp; /* dictionary node corresponding to eUp */ + int windingNumber; /* used to determine which regions are + * inside the polygon */ + boolean inside; /* is this region inside the polygon? */ + boolean sentinel; /* marks fake edges at t = +/-infinity */ + boolean dirty; /* marks regions where the upper or lower + * edge has changed, but we haven't checked + * whether they intersect yet */ + boolean fixUpperEdge; /* marks temporary edges introduced when + * we process a "right vertex" (one without + * any edges leaving to the right) */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java new file mode 100644 index 000000000..8948acfec --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/CachedVertex.java @@ -0,0 +1,58 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class CachedVertex { + public double[] coords = new double[3]; + public Object data; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java new file mode 100644 index 000000000..d26948e7f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Dict.java @@ -0,0 +1,140 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Dict { + DictNode head; + Object frame; + DictLeq leq; + + private Dict() { + } + + static Dict dictNewDict(Object frame, DictLeq leq) { + Dict dict = new Dict(); + dict.head = new DictNode(); + + dict.head.key = null; + dict.head.next = dict.head; + dict.head.prev = dict.head; + + dict.frame = frame; + dict.leq = leq; + + return dict; + } + + static void dictDeleteDict(Dict dict) { + dict.head = null; + dict.frame = null; + dict.leq = null; + } + + static DictNode dictInsert(Dict dict, Object key) { + return dictInsertBefore(dict, dict.head, key); + } + + static DictNode dictInsertBefore(Dict dict, DictNode node, Object key) { + do { + node = node.prev; + } while (node.key != null && !dict.leq.leq(dict.frame, node.key, key)); + + DictNode newNode = new DictNode(); + newNode.key = key; + newNode.next = node.next; + node.next.prev = newNode; + newNode.prev = node; + node.next = newNode; + + return newNode; + } + + static Object dictKey(DictNode aNode) { + return aNode.key; + } + + static DictNode dictSucc(DictNode aNode) { + return aNode.next; + } + + static DictNode dictPred(DictNode aNode) { + return aNode.prev; + } + + static DictNode dictMin(Dict aDict) { + return aDict.head.next; + } + + static DictNode dictMax(Dict aDict) { + return aDict.head.prev; + } + + static void dictDelete(Dict dict, DictNode node) { + node.next.prev = node.prev; + node.prev.next = node.next; + } + + static DictNode dictSearch(Dict dict, Object key) { + DictNode node = dict.head; + + do { + node = node.next; + } while (node.key != null && !(dict.leq.leq(dict.frame, key, node.key))); + + return node; + } + + public interface DictLeq { + boolean leq(Object frame, Object key1, Object key2); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java new file mode 100644 index 000000000..8864de127 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/DictNode.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class DictNode { + Object key; + DictNode next; + DictNode prev; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java new file mode 100644 index 000000000..2ff4aae59 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUface.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUface { + public GLUface next; /* next face (never NULL) */ + public GLUface prev; /* previous face (never NULL) */ + public GLUhalfEdge anEdge; /* a half edge with this left face */ + public Object data; /* room for client's data */ + + /* Internal data (keep hidden) */ + public GLUface trail; /* "stack" for conversion to strips */ + public boolean marked; /* flag for conversion to strips */ + public boolean inside; /* this face is in the polygon interior */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java new file mode 100644 index 000000000..c2128b616 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUhalfEdge.java @@ -0,0 +1,71 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUhalfEdge { + public GLUhalfEdge next; /* doubly-linked list (prev==Sym->next) */ + public GLUhalfEdge Sym; /* same edge, opposite direction */ + public GLUhalfEdge Onext; /* next edge CCW around origin */ + public GLUhalfEdge Lnext; /* next edge CCW around left face */ + public GLUvertex Org; /* origin vertex (Overtex too long) */ + public com.jogamp.opengl.impl.glu.tessellator.GLUface Lface; /* left face */ + + /* Internal data (keep hidden) */ + public com.jogamp.opengl.impl.glu.tessellator.ActiveRegion activeRegion; /* a region with this upper edge (sweep.c) */ + public int winding; /* change in winding number when crossing */ + public boolean first; + + public GLUhalfEdge(boolean first) { + this.first = first; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java new file mode 100644 index 000000000..493eb20f4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUmesh.java @@ -0,0 +1,60 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUmesh { + GLUvertex vHead = new GLUvertex(); /* dummy header for vertex list */ + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = new GLUface(); /* dummy header for face list */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHead = new GLUhalfEdge(true); /* dummy header for edge list */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHeadSym = new GLUhalfEdge(false); /* and its symmetric counterpart */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java new file mode 100644 index 000000000..b21998355 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUtessellatorImpl.java @@ -0,0 +1,646 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import com.jogamp.opengl.impl.glu.tessellator.*; +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +public class GLUtessellatorImpl implements GLUtessellator { + public static final int TESS_MAX_CACHE = 100; + + private int state; /* what begin/end calls have we seen? */ + + private GLUhalfEdge lastEdge; /* lastEdge->Org is the most recent vertex */ + GLUmesh mesh; /* stores the input contours, and eventually + the tessellation itself */ + + /*** state needed for projecting onto the sweep plane ***/ + + double[] normal = new double[3]; /* user-specified normal (if provided) */ + double[] sUnit = new double[3]; /* unit vector in s-direction (debugging) */ + double[] tUnit = new double[3]; /* unit vector in t-direction (debugging) */ + + /*** state needed for the line sweep ***/ + + private double relTolerance; /* tolerance for merging features */ + int windingRule; /* rule for determining polygon interior */ + boolean fatalError; /* fatal error: needed combine callback */ + + Dict dict; /* edge dictionary for sweep line */ + PriorityQ pq; /* priority queue of vertex events */ + GLUvertex event; /* current sweep event being processed */ + + /*** state needed for rendering callbacks (see render.c) ***/ + + boolean flagBoundary; /* mark boundary edges (use EdgeFlag) */ + boolean boundaryOnly; /* Extract contours, not triangles */ + boolean avoidDegenerateTris; /* JOGL-specific hint to try to improve triangulation + by avoiding producing degenerate (zero-area) triangles; + has not been tested exhaustively and is therefore an option */ + + GLUface lonelyTriList; + /* list of triangles which could not be rendered as strips or fans */ + + + + /*** state needed to cache single-contour polygons for renderCache() */ + + private boolean flushCacheOnNextVertex; /* empty cache on next vertex() call */ + int cacheCount; /* number of cached vertices */ + CachedVertex[] cache = new CachedVertex[TESS_MAX_CACHE]; /* the vertex data */ + + /*** rendering callbacks that also pass polygon data ***/ + private Object polygonData; /* client data for current polygon */ + + private GLUtessellatorCallback callBegin; + private GLUtessellatorCallback callEdgeFlag; + private GLUtessellatorCallback callVertex; + private GLUtessellatorCallback callEnd; +// private GLUtessellatorCallback callMesh; + private GLUtessellatorCallback callError; + private GLUtessellatorCallback callCombine; + + private GLUtessellatorCallback callBeginData; + private GLUtessellatorCallback callEdgeFlagData; + private GLUtessellatorCallback callVertexData; + private GLUtessellatorCallback callEndData; +// private GLUtessellatorCallback callMeshData; + private GLUtessellatorCallback callErrorData; + private GLUtessellatorCallback callCombineData; + + private static final double GLU_TESS_DEFAULT_TOLERANCE = 0.0; +// private static final int GLU_TESS_MESH = 100112; /* void (*)(GLUmesh *mesh) */ + private static GLUtessellatorCallback NULL_CB = new GLUtessellatorCallbackAdapter(); + +// #define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \ +// MAX(sizeof(GLUvertex),sizeof(GLUface)))) + + private GLUtessellatorImpl() { + state = TessState.T_DORMANT; + + normal[0] = 0; + normal[1] = 0; + normal[2] = 0; + + relTolerance = GLU_TESS_DEFAULT_TOLERANCE; + windingRule = GLU.GLU_TESS_WINDING_ODD; + flagBoundary = false; + boundaryOnly = false; + + callBegin = NULL_CB; + callEdgeFlag = NULL_CB; + callVertex = NULL_CB; + callEnd = NULL_CB; + callError = NULL_CB; + callCombine = NULL_CB; +// callMesh = NULL_CB; + + callBeginData = NULL_CB; + callEdgeFlagData = NULL_CB; + callVertexData = NULL_CB; + callEndData = NULL_CB; + callErrorData = NULL_CB; + callCombineData = NULL_CB; + + polygonData = null; + + for (int i = 0; i < cache.length; i++) { + cache[i] = new CachedVertex(); + } + } + + static public GLUtessellator gluNewTess() + { + return new GLUtessellatorImpl(); + } + + + private void makeDormant() { + /* Return the tessellator to its original dormant state. */ + + if (mesh != null) { + Mesh.__gl_meshDeleteMesh(mesh); + } + state = TessState.T_DORMANT; + lastEdge = null; + mesh = null; + } + + private void requireState(int newState) { + if (state != newState) gotoState(newState); + } + + private void gotoState(int newState) { + while (state != newState) { + /* We change the current state one level at a time, to get to + * the desired state. + */ + if (state < newState) { + if (state == TessState.T_DORMANT) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_POLYGON); + gluTessBeginPolygon(null); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_BEGIN_CONTOUR); + gluTessBeginContour(); + } + } else { + if (state == TessState.T_IN_CONTOUR) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_CONTOUR); + gluTessEndContour(); + } else if (state == TessState.T_IN_POLYGON) { + callErrorOrErrorData(GLU.GLU_TESS_MISSING_END_POLYGON); + /* gluTessEndPolygon( tess ) is too much work! */ + makeDormant(); + } + } + } + } + + public void gluDeleteTess() { + requireState(TessState.T_DORMANT); + } + + public void gluTessProperty(int which, double value) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: + if (value < 0.0 || value > 1.0) break; + relTolerance = value; + return; + + case GLU.GLU_TESS_WINDING_RULE: + int windingRule = (int) value; + if (windingRule != value) break; /* not an integer */ + + switch (windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + case GLU.GLU_TESS_WINDING_POSITIVE: + case GLU.GLU_TESS_WINDING_NEGATIVE: + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + this.windingRule = windingRule; + return; + default: + break; + } + + case GLU.GLU_TESS_BOUNDARY_ONLY: + boundaryOnly = (value != 0); + return; + + case GLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: + avoidDegenerateTris = (value != 0); + return; + + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + callErrorOrErrorData(GLU.GLU_INVALID_VALUE); + } + +/* Returns tessellator property */ + public void gluGetTessProperty(int which, double[] value, int value_offset) { + switch (which) { + case GLU.GLU_TESS_TOLERANCE: +/* tolerance should be in range [0..1] */ + assert (0.0 <= relTolerance && relTolerance <= 1.0); + value[value_offset] = relTolerance; + break; + case GLU.GLU_TESS_WINDING_RULE: + assert (windingRule == GLU.GLU_TESS_WINDING_ODD || + windingRule == GLU.GLU_TESS_WINDING_NONZERO || + windingRule == GLU.GLU_TESS_WINDING_POSITIVE || + windingRule == GLU.GLU_TESS_WINDING_NEGATIVE || + windingRule == GLU.GLU_TESS_WINDING_ABS_GEQ_TWO); + value[value_offset] = windingRule; + break; + case GLU.GLU_TESS_BOUNDARY_ONLY: + assert (boundaryOnly == true || boundaryOnly == false); + value[value_offset] = boundaryOnly ? 1 : 0; + break; + case GLU.GLU_TESS_AVOID_DEGENERATE_TRIANGLES: + value[value_offset] = avoidDegenerateTris ? 1 : 0; + break; + default: + value[value_offset] = 0.0; + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + break; + } + } /* gluGetTessProperty() */ + + public void gluTessNormal(double x, double y, double z) { + normal[0] = x; + normal[1] = y; + normal[2] = z; + } + + public void gluTessCallback(int which, GLUtessellatorCallback aCallback) { + switch (which) { + case GLU.GLU_TESS_BEGIN: + callBegin = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_BEGIN_DATA: + callBeginData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_EDGE_FLAG: + callEdgeFlag = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = aCallback != null; + return; + case GLU.GLU_TESS_EDGE_FLAG_DATA: + callEdgeFlagData = callBegin = aCallback == null ? NULL_CB : aCallback; +/* If the client wants boundary edges to be flagged, + * we render everything as separate triangles (no strips or fans). + */ + flagBoundary = (aCallback != null); + return; + case GLU.GLU_TESS_VERTEX: + callVertex = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_VERTEX_DATA: + callVertexData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END: + callEnd = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_END_DATA: + callEndData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR: + callError = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_ERROR_DATA: + callErrorData = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE: + callCombine = aCallback == null ? NULL_CB : aCallback; + return; + case GLU.GLU_TESS_COMBINE_DATA: + callCombineData = aCallback == null ? NULL_CB : aCallback; + return; +// case GLU_TESS_MESH: +// callMesh = aCallback == null ? NULL_CB : aCallback; +// return; + default: + callErrorOrErrorData(GLU.GLU_INVALID_ENUM); + return; + } + } + + private boolean addVertex(double[] coords, Object vertexData) { + GLUhalfEdge e; + + e = lastEdge; + if (e == null) { +/* Make a self-loop (one vertex, one edge). */ + + e = Mesh.__gl_meshMakeEdge(mesh); + if (e == null) return false; + if (!Mesh.__gl_meshSplice(e, e.Sym)) return false; + } else { +/* Create a new vertex and edge which immediately follow e + * in the ordering around the left face. + */ + if (Mesh.__gl_meshSplitEdge(e) == null) return false; + e = e.Lnext; + } + +/* The new vertex is now e.Org. */ + e.Org.data = vertexData; + e.Org.coords[0] = coords[0]; + e.Org.coords[1] = coords[1]; + e.Org.coords[2] = coords[2]; + +/* The winding of an edge says how the winding number changes as we + * cross from the edge''s right face to its left face. We add the + * vertices in such an order that a CCW contour will add +1 to + * the winding number of the region inside the contour. + */ + e.winding = 1; + e.Sym.winding = -1; + + lastEdge = e; + + return true; + } + + private void cacheVertex(double[] coords, Object vertexData) { + if (cache[cacheCount] == null) { + cache[cacheCount] = new CachedVertex(); + } + + CachedVertex v = cache[cacheCount]; + + v.data = vertexData; + v.coords[0] = coords[0]; + v.coords[1] = coords[1]; + v.coords[2] = coords[2]; + ++cacheCount; + } + + + private boolean flushCache() { + CachedVertex[] v = cache; + + mesh = Mesh.__gl_meshNewMesh(); + if (mesh == null) return false; + + for (int i = 0; i < cacheCount; i++) { + CachedVertex vertex = v[i]; + if (!addVertex(vertex.coords, vertex.data)) return false; + } + cacheCount = 0; + flushCacheOnNextVertex = false; + + return true; + } + + public void gluTessVertex(double[] coords, int coords_offset, Object vertexData) { + int i; + boolean tooLarge = false; + double x; + double[] clamped = new double[3]; + + requireState(TessState.T_IN_CONTOUR); + + if (flushCacheOnNextVertex) { + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + lastEdge = null; + } + for (i = 0; i < 3; ++i) { + x = coords[i+coords_offset]; + if (x < -GLU.GLU_TESS_MAX_COORD) { + x = -GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + if (x > GLU.GLU_TESS_MAX_COORD) { + x = GLU.GLU_TESS_MAX_COORD; + tooLarge = true; + } + clamped[i] = x; + } + if (tooLarge) { + callErrorOrErrorData(GLU.GLU_TESS_COORD_TOO_LARGE); + } + + if (mesh == null) { + if (cacheCount < TESS_MAX_CACHE) { + cacheVertex(clamped, vertexData); + return; + } + if (!flushCache()) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + return; + } + } + + if (!addVertex(clamped, vertexData)) { + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + + public void gluTessBeginPolygon(Object data) { + requireState(TessState.T_DORMANT); + + state = TessState.T_IN_POLYGON; + cacheCount = 0; + flushCacheOnNextVertex = false; + mesh = null; + + polygonData = data; + } + + + public void gluTessBeginContour() { + requireState(TessState.T_IN_POLYGON); + + state = TessState.T_IN_CONTOUR; + lastEdge = null; + if (cacheCount > 0) { +/* Just set a flag so we don't get confused by empty contours + * -- these can be generated accidentally with the obsolete + * NextContour() interface. + */ + flushCacheOnNextVertex = true; + } + } + + + public void gluTessEndContour() { + requireState(TessState.T_IN_CONTOUR); + state = TessState.T_IN_POLYGON; + } + + public void gluTessEndPolygon() { + GLUmesh mesh; + + try { + requireState(TessState.T_IN_POLYGON); + state = TessState.T_DORMANT; + + if (this.mesh == null) { + if (!flagBoundary /*&& callMesh == NULL_CB*/) { + +/* Try some special code to make the easy cases go quickly + * (eg. convex polygons). This code does NOT handle multiple contours, + * intersections, edge flags, and of course it does not generate + * an explicit mesh either. + */ + if (Render.__gl_renderCache(this)) { + polygonData = null; + return; + } + } + if (!flushCache()) throw new RuntimeException(); /* could've used a label*/ + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + Normal.__gl_projectPolygon(this); + +/* __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by windingRule. + * Each interior region is guaranteed be monotone. + */ + if (!Sweep.__gl_computeInterior(this)) { + throw new RuntimeException(); /* could've used a label */ + } + + mesh = this.mesh; + if (!fatalError) { + boolean rc = true; + +/* If the user wants only the boundary contours, we throw away all edges + * except those which separate the interior from the exterior. + * Otherwise we tessellate all the regions marked "inside". + */ + if (boundaryOnly) { + rc = TessMono.__gl_meshSetWindingNumber(mesh, 1, true); + } else { + rc = TessMono.__gl_meshTessellateInterior(mesh, avoidDegenerateTris); + } + if (!rc) throw new RuntimeException(); /* could've used a label */ + + Mesh.__gl_meshCheckMesh(mesh); + + if (callBegin != NULL_CB || callEnd != NULL_CB + || callVertex != NULL_CB || callEdgeFlag != NULL_CB + || callBeginData != NULL_CB + || callEndData != NULL_CB + || callVertexData != NULL_CB + || callEdgeFlagData != NULL_CB) { + if (boundaryOnly) { + Render.__gl_renderBoundary(this, mesh); /* output boundary contours */ + } else { + Render.__gl_renderMesh(this, mesh); /* output strips and fans */ + } + } +// if (callMesh != NULL_CB) { +// +///* Throw away the exterior faces, so that all faces are interior. +// * This way the user doesn't have to check the "inside" flag, +// * and we don't need to even reveal its existence. It also leaves +// * the freedom for an implementation to not generate the exterior +// * faces in the first place. +// */ +// TessMono.__gl_meshDiscardExterior(mesh); +// callMesh.mesh(mesh); /* user wants the mesh itself */ +// mesh = null; +// polygonData = null; +// return; +// } + } + Mesh.__gl_meshDeleteMesh(mesh); + polygonData = null; + mesh = null; + } catch (Exception e) { + e.printStackTrace(); + callErrorOrErrorData(GLU.GLU_OUT_OF_MEMORY); + } + } + + /*******************************************************/ + +/* Obsolete calls -- for backward compatibility */ + + public void gluBeginPolygon() { + gluTessBeginPolygon(null); + gluTessBeginContour(); + } + + +/*ARGSUSED*/ + public void gluNextContour(int type) { + gluTessEndContour(); + gluTessBeginContour(); + } + + + public void gluEndPolygon() { + gluTessEndContour(); + gluTessEndPolygon(); + } + + void callBeginOrBeginData(int a) { + if (callBeginData != NULL_CB) + callBeginData.beginData(a, polygonData); + else + callBegin.begin(a); + } + + void callVertexOrVertexData(Object a) { + if (callVertexData != NULL_CB) + callVertexData.vertexData(a, polygonData); + else + callVertex.vertex(a); + } + + void callEdgeFlagOrEdgeFlagData(boolean a) { + if (callEdgeFlagData != NULL_CB) + callEdgeFlagData.edgeFlagData(a, polygonData); + else + callEdgeFlag.edgeFlag(a); + } + + void callEndOrEndData() { + if (callEndData != NULL_CB) + callEndData.endData(polygonData); + else + callEnd.end(); + } + + void callCombineOrCombineData(double[] coords, Object[] vertexData, float[] weights, Object[] outData) { + if (callCombineData != NULL_CB) + callCombineData.combineData(coords, vertexData, weights, outData, polygonData); + else + callCombine.combine(coords, vertexData, weights, outData); + } + + void callErrorOrErrorData(int a) { + if (callErrorData != NULL_CB) + callErrorData.errorData(a, polygonData); + else + callError.error(a); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java new file mode 100644 index 000000000..af294caad --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/GLUvertex.java @@ -0,0 +1,65 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class GLUvertex { + public GLUvertex next; /* next vertex (never NULL) */ + public GLUvertex prev; /* previous vertex (never NULL) */ + public com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge anEdge; /* a half-edge with this origin */ + public Object data; /* client's data */ + + /* Internal data (keep hidden) */ + public double[] coords = new double[3]; /* vertex location in 3D */ + public double s, t; /* projection onto the sweep plane */ + public int pqHandle; /* to allow deletion from priority queue */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java new file mode 100644 index 000000000..2710346d1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Geom.java @@ -0,0 +1,338 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Geom { + private Geom() { + } + + /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->t = 0 and + * let r be the negated result (this evaluates (uw)(v->s)), then + * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t). + */ + static double EdgeEval(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.t - u.t) + (u.t - w.t) * (gapL / (gapL + gapR)); + } else { + return (v.t - w.t) + (w.t - u.t) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double EdgeSign(GLUvertex u, GLUvertex v, GLUvertex w) { + double gapL, gapR; + + assert (VertLeq(u, v) && VertLeq(v, w)); + + gapL = v.s - u.s; + gapR = w.s - v.s; + + if (gapL + gapR > 0) { + return (v.t - w.t) * gapL + (v.t - u.t) * gapR; + } + /* vertical line */ + return 0; + } + + + /*********************************************************************** + * Define versions of EdgeSign, EdgeEval with s and t transposed. + */ + + static double TransEval(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w), + * evaluates the t-coord of the edge uw at the s-coord of the vertex v. + * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v. + * If uw is vertical (and thus passes thru v), the result is zero. + * + * The calculation is extremely accurate and stable, even when v + * is very close to u or w. In particular if we set v->s = 0 and + * let r be the negated result (this evaluates (uw)(v->t)), then + * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s). + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + if (gapL < gapR) { + return (v.s - u.s) + (u.s - w.s) * (gapL / (gapL + gapR)); + } else { + return (v.s - w.s) + (w.s - u.s) * (gapR / (gapL + gapR)); + } + } + /* vertical line */ + return 0; + } + + static double TransSign(GLUvertex u, GLUvertex v, GLUvertex w) { + /* Returns a number whose sign matches TransEval(u,v,w) but which + * is cheaper to evaluate. Returns > 0, == 0 , or < 0 + * as v is above, on, or below the edge uw. + */ + double gapL, gapR; + + assert (TransLeq(u, v) && TransLeq(v, w)); + + gapL = v.t - u.t; + gapR = w.t - v.t; + + if (gapL + gapR > 0) { + return (v.s - w.s) * gapL + (v.s - u.s) * gapR; + } + /* vertical line */ + return 0; + } + + + static boolean VertCCW(GLUvertex u, GLUvertex v, GLUvertex w) { + /* For almost-degenerate situations, the results are not reliable. + * Unless the floating-point arithmetic can be performed without + * rounding errors, *any* implementation will give incorrect results + * on some degenerate inputs, so the client must have some way to + * handle this situation. + */ + return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; + } + +/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), + * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces + * this in the rare case that one argument is slightly negative. + * The implementation is extremely stable numerically. + * In particular it guarantees that the result r satisfies + * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate + * even when a and b differ greatly in magnitude. + */ + static double Interpolate(double a, double x, double b, double y) { + a = (a < 0) ? 0 : a; + b = (b < 0) ? 0 : b; + if (a <= b) { + if (b == 0) { + return (x + y) / 2.0; + } else { + return (x + (y - x) * (a / (a + b))); + } + } else { + return (y + (x - y) * (b / (a + b))); + } + } + + static void EdgeIntersect(GLUvertex o1, GLUvertex d1, + GLUvertex o2, GLUvertex d2, + GLUvertex v) +/* Given edges (o1,d1) and (o2,d2), compute their point of intersection. + * The computed point is guaranteed to lie in the intersection of the + * bounding rectangles defined by each edge. + */ { + double z1, z2; + + /* This is certainly not the most efficient way to find the intersection + * of two line segments, but it is very numerically stable. + * + * Strategy: find the two middle vertices in the VertLeq ordering, + * and interpolate the intersection s-value from these. Then repeat + * using the TransLeq ordering to find the intersection t-value. + */ + + if (!VertLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!VertLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!VertLeq(o1, o2)) { + GLUvertex temp = o1; + o1 = o2; + o2 = temp; + temp = d1; + d1 = d2; + d2 = temp; + } + + if (!VertLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.s = (o2.s + d1.s) / 2.0; + } else if (VertLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = EdgeEval(o1, o2, d1); + z2 = EdgeEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d1.s); + } else { + /* Interpolate between o2 and d2 */ + z1 = EdgeSign(o1, o2, d1); + z2 = -EdgeSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.s = Interpolate(z1, o2.s, z2, d2.s); + } + + /* Now repeat the process for t */ + + if (!TransLeq(o1, d1)) { + GLUvertex temp = o1; + o1 = d1; + d1 = temp; + } + if (!TransLeq(o2, d2)) { + GLUvertex temp = o2; + o2 = d2; + d2 = temp; + } + if (!TransLeq(o1, o2)) { + GLUvertex temp = o2; + o2 = o1; + o1 = temp; + temp = d2; + d2 = d1; + d1 = temp; + } + + if (!TransLeq(o2, d1)) { + /* Technically, no intersection -- do our best */ + v.t = (o2.t + d1.t) / 2.0; + } else if (TransLeq(d1, d2)) { + /* Interpolate between o2 and d1 */ + z1 = TransEval(o1, o2, d1); + z2 = TransEval(o2, d1, d2); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d1.t); + } else { + /* Interpolate between o2 and d2 */ + z1 = TransSign(o1, o2, d1); + z2 = -TransSign(o1, d2, d1); + if (z1 + z2 < 0) { + z1 = -z1; + z2 = -z2; + } + v.t = Interpolate(z1, o2.t, z2, d2.t); + } + } + + static boolean VertEq(GLUvertex u, GLUvertex v) { + return u.s == v.s && u.t == v.t; + } + + static boolean VertLeq(GLUvertex u, GLUvertex v) { + return u.s < v.s || (u.s == v.s && u.t <= v.t); + } + +/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */ + + static boolean TransLeq(GLUvertex u, GLUvertex v) { + return u.t < v.t || (u.t == v.t && u.s <= v.s); + } + + static boolean EdgeGoesLeft(GLUhalfEdge e) { + return VertLeq(e.Sym.Org, e.Org); + } + + static boolean EdgeGoesRight(GLUhalfEdge e) { + return VertLeq(e.Org, e.Sym.Org); + } + + static double VertL1dist(GLUvertex u, GLUvertex v) { + return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); + } + + /***********************************************************************/ + + // Compute the cosine of the angle between the edges between o and + // v1 and between o and v2 + static double EdgeCos(GLUvertex o, GLUvertex v1, GLUvertex v2) { + double ov1s = v1.s - o.s; + double ov1t = v1.t - o.t; + double ov2s = v2.s - o.s; + double ov2t = v2.t - o.t; + double dotp = ov1s * ov2s + ov1t * ov2t; + double len = Math.sqrt(ov1s * ov1s + ov1t * ov1t) * Math.sqrt(ov2s * ov2s + ov2t * ov2t); + if (len > 0.0) { + dotp /= len; + } + return dotp; + } + + static final double EPSILON = 1.0e-5; + static final double ONE_MINUS_EPSILON = 1.0 - EPSILON; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java new file mode 100644 index 000000000..b8be9f80f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Mesh.java @@ -0,0 +1,734 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class Mesh { + private Mesh() { + } + + /************************ Utility Routines ************************/ +/* MakeEdge creates a new pair of half-edges which form their own loop. + * No vertex or face structures are allocated, but these must be assigned + * before the current edge operation is completed. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge MakeEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge ePrev; + +// EdgePair * pair = (EdgePair *) +// memAlloc(sizeof(EdgePair)); +// if (pair == NULL) return NULL; +// +// e = &pair - > e; + e = new com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge(true); +// eSym = &pair - > eSym; + eSym = new com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge(false); + + + /* Make sure eNext points to the first edge of the edge pair */ + if (!eNext.first) { + eNext = eNext.Sym; + } + + /* Insert in circular doubly-linked list before eNext. + * Note that the prev pointer is stored in Sym->next. + */ + ePrev = eNext.Sym.next; + eSym.next = ePrev; + ePrev.Sym.next = e; + e.next = eNext; + eNext.Sym.next = eSym; + + e.Sym = eSym; + e.Onext = e; + e.Lnext = eSym; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.Sym = e; + eSym.Onext = eSym; + eSym.Lnext = e; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return e; + } + +/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the + * CS348a notes (see mesh.h). Basically it modifies the mesh so that + * a->Onext and b->Onext are exchanged. This can have various effects + * depending on whether a and b belong to different face or vertex rings. + * For more explanation see __gl_meshSplice() below. + */ + static void Splice(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge a, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge b) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge aOnext = a.Onext; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge bOnext = b.Onext; + + aOnext.Sym.Lnext = b; + bOnext.Sym.Lnext = a; + a.Onext = bOnext; + b.Onext = aOnext; + } + +/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the + * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives + * a place to insert the new vertex in the global vertex list. We insert + * the new vertex *before* vNext so that algorithms which walk the vertex + * list will not see the newly created vertices. + */ + static void MakeVertex(com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex, + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.jogamp.opengl.impl.glu.tessellator.GLUvertex vNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vNew = newVertex; + + assert (vNew != null); + + /* insert in circular doubly-linked list before vNext */ + vPrev = vNext.prev; + vNew.prev = vPrev; + vPrev.next = vNew; + vNew.next = vNext; + vNext.prev = vNew; + + vNew.anEdge = eOrig; + vNew.data = null; + /* leave coords, s, t undefined */ + + /* fix other edges on this vertex loop */ + e = eOrig; + do { + e.Org = vNew; + e = e.Onext; + } while (e != eOrig); + } + +/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left + * face of all edges in the face loop to which eOrig belongs. "fNext" gives + * a place to insert the new face in the global face list. We insert + * the new face *before* fNext so that algorithms which walk the face + * list will not see the newly created faces. + */ + static void MakeFace(com.jogamp.opengl.impl.glu.tessellator.GLUface newFace, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig, com.jogamp.opengl.impl.glu.tessellator.GLUface fNext) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUface fNew = newFace; + + assert (fNew != null); + + /* insert in circular doubly-linked list before fNext */ + fPrev = fNext.prev; + fNew.prev = fPrev; + fPrev.next = fNew; + fNew.next = fNext; + fNext.prev = fNew; + + fNew.anEdge = eOrig; + fNew.data = null; + fNew.trail = null; + fNew.marked = false; + + /* The new face is marked "inside" if the old one was. This is a + * convenience for the common case where a face has been split in two. + */ + fNew.inside = fNext.inside; + + /* fix other edges on this face loop */ + e = eOrig; + do { + e.Lface = fNew; + e = e.Lnext; + } while (e != eOrig); + } + +/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym), + * and removes from the global edge list. + */ + static void KillEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge ePrev, eNext; + + /* Half-edges are allocated in pairs, see EdgePair above */ + if (!eDel.first) { + eDel = eDel.Sym; + } + + /* delete from circular doubly-linked list */ + eNext = eDel.next; + ePrev = eDel.Sym.next; + eNext.Sym.next = ePrev; + ePrev.Sym.next = eNext; + } + + +/* KillVertex( vDel ) destroys a vertex and removes it from the global + * vertex list. It updates the vertex loop to point to a given new vertex. + */ + static void KillVertex(com.jogamp.opengl.impl.glu.tessellator.GLUvertex vDel, com.jogamp.opengl.impl.glu.tessellator.GLUvertex newOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = vDel.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vPrev, vNext; + + /* change the origin of all affected edges */ + e = eStart; + do { + e.Org = newOrg; + e = e.Onext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + vPrev = vDel.prev; + vNext = vDel.next; + vNext.prev = vPrev; + vPrev.next = vNext; + } + +/* KillFace( fDel ) destroys a face and removes it from the global face + * list. It updates the face loop to point to a given new face. + */ + static void KillFace(com.jogamp.opengl.impl.glu.tessellator.GLUface fDel, com.jogamp.opengl.impl.glu.tessellator.GLUface newLface) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eStart = fDel.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* change the left face of all affected edges */ + e = eStart; + do { + e.Lface = newLface; + e = e.Lnext; + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fDel.prev; + fNext = fDel.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + + /****************** Basic Edge Operations **********************/ + +/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face). + * The loop consists of the two new half-edges. + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshMakeEdge(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex1 = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex2 = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + e = MakeEdge(mesh.eHead); + if (e == null) return null; + + MakeVertex(newVertex1, e, mesh.vHead); + MakeVertex(newVertex2, e.Sym, mesh.vHead); + MakeFace(newFace, e, mesh.fHead); + return e; + } + + +/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the + * mesh connectivity and topology. It changes the mesh so that + * eOrg->Onext <- OLD( eDst->Onext ) + * eDst->Onext <- OLD( eOrg->Onext ) + * where OLD(...) means the value before the meshSplice operation. + * + * This can have two effects on the vertex structure: + * - if eOrg->Org != eDst->Org, the two vertices are merged together + * - if eOrg->Org == eDst->Org, the origin is split into two vertices + * In both cases, eDst->Org is changed and eOrg->Org is untouched. + * + * Similarly (and independently) for the face structure, + * - if eOrg->Lface == eDst->Lface, one loop is split into two + * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one + * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected. + * + * Some special cases: + * If eDst == eOrg, the operation has no effect. + * If eDst == eOrg->Lnext, the new face will have a single edge. + * If eDst == eOrg->Lprev, the old face will have a single edge. + * If eDst == eOrg->Onext, the new vertex will have a single edge. + * If eDst == eOrg->Oprev, the old vertex will have a single edge. + */ + public static boolean __gl_meshSplice(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + boolean joiningLoops = false; + boolean joiningVertices = false; + + if (eOrg == eDst) return true; + + if (eDst.Org != eOrg.Org) { + /* We are merging two disjoint vertices -- destroy eDst->Org */ + joiningVertices = true; + KillVertex(eDst.Org, eOrg.Org); + } + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Change the edge structure */ + Splice(eDst, eOrg); + + if (!joiningVertices) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + + /* We split one vertex into two -- the new vertex is eDst.Org. + * Make sure the old vertex points to a valid half-edge. + */ + MakeVertex(newVertex, eDst, eOrg.Org); + eOrg.Org.anEdge = eOrg; + } + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eDst.Lface. + * Make sure the old face points to a valid half-edge. + */ + MakeFace(newFace, eDst, eOrg.Lface); + eOrg.Lface.anEdge = eOrg; + } + + return true; + } + + +/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases: + * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop + * eDel.Lface is deleted. Otherwise, we are splitting one loop into two; + * the newly created loop will contain eDel.Dst. If the deletion of eDel + * would create isolated vertices, those are deleted as well. + * + * This function could be implemented as two calls to __gl_meshSplice + * plus a few calls to memFree, but this would allocate and delete + * unnecessary vertices and faces. + */ + static boolean __gl_meshDelete(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDel) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDelSym = eDel.Sym; + boolean joiningLoops = false; + + /* First step: disconnect the origin vertex eDel.Org. We make all + * changes to get a consistent mesh in this "intermediate" state. + */ + if (eDel.Lface != eDel.Sym.Lface) { + /* We are joining two loops into one -- remove the left face */ + joiningLoops = true; + KillFace(eDel.Lface, eDel.Sym.Lface); + } + + if (eDel.Onext == eDel) { + KillVertex(eDel.Org, null); + } else { + /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */ + eDel.Sym.Lface.anEdge = eDel.Sym.Lnext; + eDel.Org.anEdge = eDel.Onext; + + Splice(eDel, eDel.Sym.Lnext); + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We are splitting one loop into two -- create a new loop for eDel. */ + MakeFace(newFace, eDel, eDel.Lface); + } + } + + /* Claim: the mesh is now in a consistent state, except that eDel.Org + * may have been deleted. Now we disconnect eDel.Dst. + */ + if (eDelSym.Onext == eDelSym) { + KillVertex(eDelSym.Org, null); + KillFace(eDelSym.Lface, null); + } else { + /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */ + eDel.Lface.anEdge = eDelSym.Sym.Lnext; + eDelSym.Org.anEdge = eDelSym.Onext; + Splice(eDelSym, eDelSym.Sym.Lnext); + } + + /* Any isolated vertices or faces have already been freed. */ + KillEdge(eDel); + + return true; + } + + + /******************** Other Edge Operations **********************/ + +/* All these routines can be implemented with the basic edge + * operations above. They are provided for convenience and efficiency. + */ + + +/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that + * eNew == eOrg.Lnext, and eNew.Dst is a newly created vertex. + * eOrg and eNew will have the same left face. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshAddEdgeVertex(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex newVertex = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex(); + + MakeVertex(newVertex, eNewSym, eNew.Org); + } + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + return eNew; + } + + +/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew, + * such that eNew == eOrg.Lnext. The new vertex is eOrg.Sym.Org == eNew.Org. + * eOrg and eNew will have the same left face. + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshSplitEdge(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge tempHalfEdge = __gl_meshAddEdgeVertex(eOrg); + + eNew = tempHalfEdge.Sym; + + /* Disconnect eOrg from eOrg.Sym.Org and connect it to eNew.Org */ + Splice(eOrg.Sym, eOrg.Sym.Sym.Lnext); + Splice(eOrg.Sym, eNew); + + /* Set the vertex and face information */ + eOrg.Sym.Org = eNew.Org; + eNew.Sym.Org.anEdge = eNew.Sym; /* may have pointed to eOrg.Sym */ + eNew.Sym.Lface = eOrg.Sym.Lface; + eNew.winding = eOrg.winding; /* copy old winding information */ + eNew.Sym.winding = eOrg.Sym.winding; + + return eNew; + } + + +/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org + * to eDst.Org, and returns the corresponding half-edge eNew. + * If eOrg.Lface == eDst.Lface, this splits one loop into two, + * and the newly created loop is eNew.Lface. Otherwise, two disjoint + * loops are merged into one, and the loop eDst.Lface is destroyed. + * + * If (eOrg == eDst), the new face will have only two edges. + * If (eOrg.Lnext == eDst), the old face is reduced to a single edge. + * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges. + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge __gl_meshConnect(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrg, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eDst) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNewSym; + boolean joiningLoops = false; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eNew = MakeEdge(eOrg); + + eNewSym = eNew.Sym; + + if (eDst.Lface != eOrg.Lface) { + /* We are connecting two disjoint loops -- destroy eDst.Lface */ + joiningLoops = true; + KillFace(eDst.Lface, eOrg.Lface); + } + + /* Connect the new edge appropriately */ + Splice(eNew, eOrg.Lnext); + Splice(eNewSym, eDst); + + /* Set the vertex and face information */ + eNew.Org = eOrg.Sym.Org; + eNewSym.Org = eDst.Org; + eNew.Lface = eNewSym.Lface = eOrg.Lface; + + /* Make sure the old face points to a valid half-edge */ + eOrg.Lface.anEdge = eNewSym; + + if (!joiningLoops) { + com.jogamp.opengl.impl.glu.tessellator.GLUface newFace = new com.jogamp.opengl.impl.glu.tessellator.GLUface(); + + /* We split one loop into two -- the new loop is eNew.Lface */ + MakeFace(newFace, eNew, eOrg.Lface); + } + return eNew; + } + + + /******************** Other Operations **********************/ + +/* __gl_meshZapFace( fZap ) destroys a face and removes it from the + * global face list. All edges of fZap will have a null pointer as their + * left face. Any edges which also have a null pointer as their right face + * are deleted entirely (along with any isolated vertices this produces). + * An entire mesh can be deleted by zapping its faces, one at a time, + * in any order. Zapped faces cannot be used in further mesh operations! + */ + static void __gl_meshZapFace(com.jogamp.opengl.impl.glu.tessellator.GLUface fZap) { + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart = fZap.anEdge; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext, eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUface fPrev, fNext; + + /* walk around face, deleting edges whose right face is also null */ + eNext = eStart.Lnext; + do { + e = eNext; + eNext = e.Lnext; + + e.Lface = null; + if (e.Sym.Lface == null) { + /* delete the edge -- see __gl_MeshDelete above */ + + if (e.Onext == e) { + KillVertex(e.Org, null); + } else { + /* Make sure that e.Org points to a valid half-edge */ + e.Org.anEdge = e.Onext; + Splice(e, e.Sym.Lnext); + } + eSym = e.Sym; + if (eSym.Onext == eSym) { + KillVertex(eSym.Org, null); + } else { + /* Make sure that eSym.Org points to a valid half-edge */ + eSym.Org.anEdge = eSym.Onext; + Splice(eSym, eSym.Sym.Lnext); + } + KillEdge(e); + } + } while (e != eStart); + + /* delete from circular doubly-linked list */ + fPrev = fZap.prev; + fNext = fZap.next; + fNext.prev = fPrev; + fPrev.next = fNext; + } + + +/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, + * and no loops (what we usually call a "face"). + */ + public static com.jogamp.opengl.impl.glu.tessellator.GLUmesh __gl_meshNewMesh() { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v; + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eSym; + com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh = new com.jogamp.opengl.impl.glu.tessellator.GLUmesh(); + + v = mesh.vHead; + f = mesh.fHead; + e = mesh.eHead; + eSym = mesh.eHeadSym; + + v.next = v.prev = v; + v.anEdge = null; + v.data = null; + + f.next = f.prev = f; + f.anEdge = null; + f.data = null; + f.trail = null; + f.marked = false; + f.inside = false; + + e.next = e; + e.Sym = eSym; + e.Onext = null; + e.Lnext = null; + e.Org = null; + e.Lface = null; + e.winding = 0; + e.activeRegion = null; + + eSym.next = eSym; + eSym.Sym = e; + eSym.Onext = null; + eSym.Lnext = null; + eSym.Org = null; + eSym.Lface = null; + eSym.winding = 0; + eSym.activeRegion = null; + + return mesh; + } + + +/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in + * both meshes, and returns the new mesh (the old meshes are destroyed). + */ + static com.jogamp.opengl.impl.glu.tessellator.GLUmesh __gl_meshUnion(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh1, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh2) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f1 = mesh1.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v1 = mesh1.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e1 = mesh1.eHead; + com.jogamp.opengl.impl.glu.tessellator.GLUface f2 = mesh2.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v2 = mesh2.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e2 = mesh2.eHead; + + /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */ + if (f2.next != f2) { + f1.prev.next = f2.next; + f2.next.prev = f1.prev; + f2.prev.next = f1; + f1.prev = f2.prev; + } + + if (v2.next != v2) { + v1.prev.next = v2.next; + v2.next.prev = v1.prev; + v2.prev.next = v1; + v1.prev = v2.prev; + } + + if (e2.next != e2) { + e1.Sym.next.Sym.next = e2.next; + e2.next.Sym.next = e1.Sym.next; + e2.Sym.next.Sym.next = e1; + e1.Sym.next = e2.Sym.next; + } + + return mesh1; + } + + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + static void __gl_meshDeleteMeshZap(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + + while (fHead.next != fHead) { + __gl_meshZapFace(fHead.next); + } + assert (mesh.vHead.next == mesh.vHead); + } + +/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. + */ + public static void __gl_meshDeleteMesh(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fNext; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vNext; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eNext; + + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + } + + for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) { + vNext = v.next; + } + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + /* One call frees both e and e.Sym (see EdgePair above) */ + eNext = e.next; + } + } + +/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency. + */ + public static void __gl_meshCheckMesh(com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface fHead = mesh.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vHead = mesh.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eHead = mesh.eHead; + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vPrev; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, ePrev; + + fPrev = fHead; + for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f) { + assert (f.prev == fPrev); + e = f.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Lface == f); + e = e.Lnext; + } while (e != f.anEdge); + } + assert (f.prev == fPrev && f.anEdge == null && f.data == null); + + vPrev = vHead; + for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v) { + assert (v.prev == vPrev); + e = v.anEdge; + do { + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + assert (e.Org == v); + e = e.Onext; + } while (e != v.anEdge); + } + assert (v.prev == vPrev && v.anEdge == null && v.data == null); + + ePrev = eHead; + for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e) { + assert (e.Sym.next == ePrev.Sym); + assert (e.Sym != e); + assert (e.Sym.Sym == e); + assert (e.Org != null); + assert (e.Sym.Org != null); + assert (e.Lnext.Onext.Sym == e); + assert (e.Onext.Sym.Lnext == e); + } + assert (e.Sym.next == ePrev.Sym + && e.Sym == mesh.eHeadSym + && e.Sym.Sym == e + && e.Org == null && e.Sym.Org == null + && e.Lface == null && e.Sym.Lface == null); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java new file mode 100644 index 000000000..fe1a20c49 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Normal.java @@ -0,0 +1,288 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Normal { + private Normal() { + } + + static boolean SLANTED_SWEEP = false; + static double S_UNIT_X; /* Pre-normalized */ + static double S_UNIT_Y; + private static final boolean TRUE_PROJECT = false; + + static { + if (SLANTED_SWEEP) { +/* The "feature merging" is not intended to be complete. There are + * special cases where edges are nearly parallel to the sweep line + * which are not implemented. The algorithm should still behave + * robustly (ie. produce a reasonable tesselation) in the presence + * of such edges, however it may miss features which could have been + * merged. We could minimize this effect by choosing the sweep line + * direction to be something unusual (ie. not parallel to one of the + * coordinate axes). + */ + S_UNIT_X = 0.50941539564955385; /* Pre-normalized */ + S_UNIT_Y = 0.86052074622010633; + } else { + S_UNIT_X = 1.0; + S_UNIT_Y = 0.0; + } + } + + private static double Dot(double[] u, double[] v) { + return (u[0] * v[0] + u[1] * v[1] + u[2] * v[2]); + } + + static void Normalize(double[] v) { + double len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; + + assert (len > 0); + len = Math.sqrt(len); + v[0] /= len; + v[1] /= len; + v[2] /= len; + } + + static int LongAxis(double[] v) { + int i = 0; + + if (Math.abs(v[1]) > Math.abs(v[0])) { + i = 1; + } + if (Math.abs(v[2]) > Math.abs(v[i])) { + i = 2; + } + return i; + } + + static void ComputeNormal(GLUtessellatorImpl tess, double[] norm) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, v1, v2; + double c, tLen2, maxLen2; + double[] maxVal, minVal, d1, d2, tNorm; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex[] maxVert, minVert; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex vHead = tess.mesh.vHead; + int i; + + maxVal = new double[3]; + minVal = new double[3]; + minVert = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex[3]; + maxVert = new com.jogamp.opengl.impl.glu.tessellator.GLUvertex[3]; + d1 = new double[3]; + d2 = new double[3]; + tNorm = new double[3]; + + maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU.GLU_TESS_MAX_COORD; + minVal[0] = minVal[1] = minVal[2] = 2 * GLU.GLU_TESS_MAX_COORD; + + for (v = vHead.next; v != vHead; v = v.next) { + for (i = 0; i < 3; ++i) { + c = v.coords[i]; + if (c < minVal[i]) { + minVal[i] = c; + minVert[i] = v; + } + if (c > maxVal[i]) { + maxVal[i] = c; + maxVert[i] = v; + } + } + } + +/* Find two vertices separated by at least 1/sqrt(3) of the maximum + * distance between any two vertices + */ + i = 0; + if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0]) { + i = 1; + } + if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i]) { + i = 2; + } + if (minVal[i] >= maxVal[i]) { +/* All vertices are the same -- normal doesn't matter */ + norm[0] = 0; + norm[1] = 0; + norm[2] = 1; + return; + } + +/* Look for a third vertex which forms the triangle with maximum area + * (Length of normal == twice the triangle area) + */ + maxLen2 = 0; + v1 = minVert[i]; + v2 = maxVert[i]; + d1[0] = v1.coords[0] - v2.coords[0]; + d1[1] = v1.coords[1] - v2.coords[1]; + d1[2] = v1.coords[2] - v2.coords[2]; + for (v = vHead.next; v != vHead; v = v.next) { + d2[0] = v.coords[0] - v2.coords[0]; + d2[1] = v.coords[1] - v2.coords[1]; + d2[2] = v.coords[2] - v2.coords[2]; + tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1]; + tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2]; + tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0]; + tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2]; + if (tLen2 > maxLen2) { + maxLen2 = tLen2; + norm[0] = tNorm[0]; + norm[1] = tNorm[1]; + norm[2] = tNorm[2]; + } + } + + if (maxLen2 <= 0) { +/* All points lie on a single line -- any decent normal will do */ + norm[0] = norm[1] = norm[2] = 0; + norm[LongAxis(d1)] = 1; + } + } + + static void CheckOrientation(GLUtessellatorImpl tess) { + double area; + com.jogamp.opengl.impl.glu.tessellator.GLUface f, fHead = tess.mesh.fHead; + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + +/* When we compute the normal automatically, we choose the orientation + * so that the the sum of the signed areas of all contours is non-negative. + */ + area = 0; + for (f = fHead.next; f != fHead; f = f.next) { + e = f.anEdge; + if (e.winding <= 0) continue; + do { + area += (e.Org.s - e.Sym.Org.s) * (e.Org.t + e.Sym.Org.t); + e = e.Lnext; + } while (e != f.anEdge); + } + if (area < 0) { +/* Reverse the orientation by flipping all the t-coordinates */ + for (v = vHead.next; v != vHead; v = v.next) { + v.t = -v.t; + } + tess.tUnit[0] = -tess.tUnit[0]; + tess.tUnit[1] = -tess.tUnit[1]; + tess.tUnit[2] = -tess.tUnit[2]; + } + } + +/* Determine the polygon normal and project vertices onto the plane + * of the polygon. + */ + public static void __gl_projectPolygon(GLUtessellatorImpl tess) { + com.jogamp.opengl.impl.glu.tessellator.GLUvertex v, vHead = tess.mesh.vHead; + double w; + double[] norm = new double[3]; + double[] sUnit, tUnit; + int i; + boolean computedNormal = false; + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal(tess, norm); + computedNormal = true; + } + sUnit = tess.sUnit; + tUnit = tess.tUnit; + i = LongAxis(norm); + + if (TRUE_PROJECT) { +/* Choose the initial sUnit vector to be approximately perpendicular + * to the normal. + */ + Normalize(norm); + + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + +/* Now make it exactly perpendicular */ + w = Dot(sUnit, norm); + sUnit[0] -= w * norm[0]; + sUnit[1] -= w * norm[1]; + sUnit[2] -= w * norm[2]; + Normalize(sUnit); + +/* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */ + tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1]; + tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2]; + tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0]; + Normalize(tUnit); + } else { +/* Project perpendicular to a coordinate axis -- better numerically */ + sUnit[i] = 0; + sUnit[(i + 1) % 3] = S_UNIT_X; + sUnit[(i + 2) % 3] = S_UNIT_Y; + + tUnit[i] = 0; + tUnit[(i + 1) % 3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y; + tUnit[(i + 2) % 3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X; + } + +/* Project the vertices onto the sweep plane */ + for (v = vHead.next; v != vHead; v = v.next) { + v.s = Dot(v.coords, sUnit); + v.t = Dot(v.coords, tUnit); + } + if (computedNormal) { + CheckOrientation(tess); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java new file mode 100644 index 000000000..b77305ae2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQ.java @@ -0,0 +1,100 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +abstract class PriorityQ { + public static final int INIT_SIZE = 32; + + public static class PQnode { + int handle; + } + + public static class PQhandleElem { + Object key; + int node; + } + + public static interface Leq { + boolean leq(Object key1, Object key2); + } + + // #ifdef FOR_TRITE_TEST_PROGRAM +// private static boolean LEQ(PriorityQCommon.Leq leq, Object x,Object y) { +// return pq.leq.leq(x,y); +// } +// #else +/* Violates modularity, but a little faster */ +// #include "geom.h" + public static boolean LEQ(Leq leq, Object x, Object y) { + return com.jogamp.opengl.impl.glu.tessellator.Geom.VertLeq((com.jogamp.opengl.impl.glu.tessellator.GLUvertex) x, (com.jogamp.opengl.impl.glu.tessellator.GLUvertex) y); + } + + static PriorityQ pqNewPriorityQ(Leq leq) { + return new PriorityQSort(leq); + } + + abstract void pqDeletePriorityQ(); + + abstract boolean pqInit(); + + abstract int pqInsert(Object keyNew); + + abstract Object pqExtractMin(); + + abstract void pqDelete(int hCurr); + + abstract Object pqMinimum(); + + abstract boolean pqIsEmpty(); +// #endif +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java new file mode 100644 index 000000000..61aa9574f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQHeap.java @@ -0,0 +1,262 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class PriorityQHeap extends com.jogamp.opengl.impl.glu.tessellator.PriorityQ { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] handles; + int size, max; + int freeList; + boolean initialized; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + +/* really __gl_pqHeapNewPriorityQ */ + public PriorityQHeap(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + size = 0; + max = com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + nodes = new com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < nodes.length; i++) { + nodes[i] = new PQnode(); + } + handles = new com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE + 1]; + for (int i = 0; i < handles.length; i++) { + handles[i] = new PQhandleElem(); + } + initialized = false; + freeList = 0; + this.leq = leq; + + nodes[1].handle = 1; /* so that Minimum() returns NULL */ + handles[1].key = null; + } + +/* really __gl_pqHeapDeletePriorityQ */ + void pqDeletePriorityQ() { + handles = null; + nodes = null; + } + + void FloatDown(int curr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hChild; + int child; + + hCurr = n[curr].handle; + for (; ;) { + child = curr << 1; + if (child < size && LEQ(leq, h[n[child + 1].handle].key, + h[n[child].handle].key)) { + ++child; + } + + assert (child <= max); + + hChild = n[child].handle; + if (child > size || LEQ(leq, h[hCurr].key, h[hChild].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hChild; + h[hChild].node = curr; + curr = child; + } + } + + + void FloatUp(int curr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hCurr, hParent; + int parent; + + hCurr = n[curr].handle; + for (; ;) { + parent = curr >> 1; + hParent = n[parent].handle; + if (parent == 0 || LEQ(leq, h[hParent].key, h[hCurr].key)) { + n[curr].handle = hCurr; + h[hCurr].node = curr; + break; + } + n[curr].handle = hParent; + h[hParent].node = curr; + curr = parent; + } + } + +/* really __gl_pqHeapInit */ + boolean pqInit() { + int i; + + /* This method of building a heap is O(n), rather than O(n lg n). */ + + for (i = size; i >= 1; --i) { + FloatDown(i); + } + initialized = true; + + return true; + } + +/* really __gl_pqHeapInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + int free; + + curr = ++size; + if ((curr * 2) > max) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] saveNodes = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] saveHandles = handles; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->nodes = (PQnode *)memRealloc( pq->nodes, (size_t) ((pq->max + 1) * sizeof( pq->nodes[0] ))); + PriorityQ.PQnode[] pqNodes = new PriorityQ.PQnode[max + 1]; + System.arraycopy( nodes, 0, pqNodes, 0, nodes.length ); + for (int i = nodes.length; i < pqNodes.length; i++) { + pqNodes[i] = new PQnode(); + } + nodes = pqNodes; + if (nodes == null) { + nodes = saveNodes; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + +// pq->handles = (PQhandleElem *)memRealloc( pq->handles,(size_t)((pq->max + 1) * sizeof( pq->handles[0] ))); + PriorityQ.PQhandleElem[] pqHandles = new PriorityQ.PQhandleElem[max + 1]; + System.arraycopy( handles, 0, pqHandles, 0, handles.length ); + for (int i = handles.length; i < pqHandles.length; i++) { + pqHandles[i] = new PQhandleElem(); + } + handles = pqHandles; + if (handles == null) { + handles = saveHandles; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + + if (freeList == 0) { + free = curr; + } else { + free = freeList; + freeList = handles[free].node; + } + + nodes[curr].handle = free; + handles[free].node = curr; + handles[free].key = keyNew; + + if (initialized) { + FloatUp(curr); + } + assert (free != Integer.MAX_VALUE); + return free; + } + +/* really __gl_pqHeapExtractMin */ + Object pqExtractMin() { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int hMin = n[1].handle; + Object min = h[hMin].key; + + if (size > 0) { + n[1].handle = n[size].handle; + h[n[1].handle].node = 1; + + h[hMin].key = null; + h[hMin].node = freeList; + freeList = hMin; + + if (--size > 0) { + FloatDown(1); + } + } + return min; + } + +/* really __gl_pqHeapDelete */ + void pqDelete(int hCurr) { + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQnode[] n = nodes; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.PQhandleElem[] h = handles; + int curr; + + assert (hCurr >= 1 && hCurr <= max && h[hCurr].key != null); + + curr = h[hCurr].node; + n[curr].handle = n[size].handle; + h[n[curr].handle].node = curr; + + if (curr <= --size) { + if (curr <= 1 || LEQ(leq, h[n[curr >> 1].handle].key, h[n[curr].handle].key)) { + FloatDown(curr); + } else { + FloatUp(curr); + } + } + h[hCurr].key = null; + h[hCurr].node = freeList; + freeList = hCurr; + } + + Object pqMinimum() { + return handles[nodes[1].handle].key; + } + + boolean pqIsEmpty() { + return size == 0; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java new file mode 100644 index 000000000..f115b8f49 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/PriorityQSort.java @@ -0,0 +1,278 @@ +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class PriorityQSort extends com.jogamp.opengl.impl.glu.tessellator.PriorityQ { + com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap heap; + Object[] keys; + + // JAVA: 'order' contains indices into the keys array. + // This simulates the indirect pointers used in the original C code + // (from Frank Suykens, Luciad.com). + int[] order; + int size, max; + boolean initialized; + com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq; + + public PriorityQSort(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq) { + heap = new com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap(leq); + + keys = new Object[com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE]; + + size = 0; + max = com.jogamp.opengl.impl.glu.tessellator.PriorityQ.INIT_SIZE; + initialized = false; + this.leq = leq; + } + +/* really __gl_pqSortDeletePriorityQ */ + void pqDeletePriorityQ() { + if (heap != null) heap.pqDeletePriorityQ(); + order = null; + keys = null; + } + + private static boolean LT(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, y, x)); + } + + private static boolean GT(com.jogamp.opengl.impl.glu.tessellator.PriorityQ.Leq leq, Object x, Object y) { + return (!com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, x, y)); + } + + private static void Swap(int[] array, int a, int b) { + if (true) { + int tmp = array[a]; + array[a] = array[b]; + array[b] = tmp; + } else { + + } + } + + private static class Stack { + int p, r; + } + +/* really __gl_pqSortInit */ + boolean pqInit() { + int p, r, i, j; + int piv; + Stack[] stack = new Stack[50]; + for (int k = 0; k < stack.length; k++) { + stack[k] = new Stack(); + } + int top = 0; + + int seed = 2016473283; + + /* Create an array of indirect pointers to the keys, so that we + * the handles we have returned are still valid. + */ + order = new int[size + 1]; +/* the previous line is a patch to compensate for the fact that IBM */ +/* machines return a null on a malloc of zero bytes (unlike SGI), */ +/* so we have to put in this defense to guard against a memory */ +/* fault four lines down. from [email protected]. */ + p = 0; + r = size - 1; + for (piv = 0, i = p; i <= r; ++piv, ++i) { + // indirect pointers: keep an index into the keys array, not a direct pointer to its contents + order[i] = piv; + } + + /* Sort the indirect pointers in descending order, + * using randomized Quicksort + */ + stack[top].p = p; + stack[top].r = r; + ++top; + while (--top >= 0) { + p = stack[top].p; + r = stack[top].r; + while (r > p + 10) { + seed = Math.abs( seed * 1539415821 + 1 ); + i = p + seed % (r - p + 1); + piv = order[i]; + order[i] = order[p]; + order[p] = piv; + i = p - 1; + j = r + 1; + do { + do { + ++i; + } while (GT(leq, keys[order[i]], keys[piv])); + do { + --j; + } while (LT(leq, keys[order[j]], keys[piv])); + Swap(order, i, j); + } while (i < j); + Swap(order, i, j); /* Undo last swap */ + if (i - p < r - j) { + stack[top].p = j + 1; + stack[top].r = r; + ++top; + r = i - 1; + } else { + stack[top].p = p; + stack[top].r = i - 1; + ++top; + p = j + 1; + } + } + /* Insertion sort small lists */ + for (i = p + 1; i <= r; ++i) { + piv = order[i]; + for (j = i; j > p && LT(leq, keys[order[j - 1]], keys[piv]); --j) { + order[j] = order[j - 1]; + } + order[j] = piv; + } + } + max = size; + initialized = true; + heap.pqInit(); /* always succeeds */ + +/* #ifndef NDEBUG + p = order; + r = p + size - 1; + for (i = p; i < r; ++i) { + Assertion.doAssert(LEQ( * * (i + 1), **i )); + } + #endif*/ + + return true; + } + +/* really __gl_pqSortInsert */ +/* returns LONG_MAX iff out of memory */ + int pqInsert(Object keyNew) { + int curr; + + if (initialized) { + return heap.pqInsert(keyNew); + } + curr = size; + if (++size >= max) { + Object[] saveKey = keys; + + /* If the heap overflows, double its size. */ + max <<= 1; +// pq->keys = (PQHeapKey *)memRealloc( pq->keys,(size_t)(pq->max * sizeof( pq->keys[0] ))); + Object[] pqKeys = new Object[max]; + System.arraycopy( keys, 0, pqKeys, 0, keys.length ); + keys = pqKeys; + if (keys == null) { + keys = saveKey; /* restore ptr to free upon return */ + return Integer.MAX_VALUE; + } + } + assert curr != Integer.MAX_VALUE; + keys[curr] = keyNew; + + /* Negative handles index the sorted array. */ + return -(curr + 1); + } + +/* really __gl_pqSortExtractMin */ + Object pqExtractMin() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqExtractMin(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (LEQ(leq, heapMin, sortMin)) { + return heap.pqExtractMin(); + } + } + do { + --size; + } while (size > 0 && keys[order[size - 1]] == null); + return sortMin; + } + +/* really __gl_pqSortMinimum */ + Object pqMinimum() { + Object sortMin, heapMin; + + if (size == 0) { + return heap.pqMinimum(); + } + sortMin = keys[order[size - 1]]; + if (!heap.pqIsEmpty()) { + heapMin = heap.pqMinimum(); + if (com.jogamp.opengl.impl.glu.tessellator.PriorityQHeap.LEQ(leq, heapMin, sortMin)) { + return heapMin; + } + } + return sortMin; + } + +/* really __gl_pqSortIsEmpty */ + boolean pqIsEmpty() { + return (size == 0) && heap.pqIsEmpty(); + } + +/* really __gl_pqSortDelete */ + void pqDelete(int curr) { + if (curr >= 0) { + heap.pqDelete(curr); + return; + } + curr = -(curr + 1); + assert curr < max && keys[curr] != null; + + keys[curr] = null; + while (size > 0 && keys[order[size - 1]] == null) { + --size; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java new file mode 100644 index 000000000..9761200e0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Render.java @@ -0,0 +1,557 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Render { + private static final boolean USE_OPTIMIZED_CODE_PATH = false; + + private Render() { + } + + private static final RenderFan renderFan = new RenderFan(); + private static final RenderStrip renderStrip = new RenderStrip(); + private static final RenderTriangle renderTriangle = new RenderTriangle(); + +/* This structure remembers the information we need about a primitive + * to be able to render it later, once we have determined which + * primitive is able to use the most triangles. + */ + private static class FaceCount { + public FaceCount() { + } + + public FaceCount(long size, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart, renderCallBack render) { + this.size = size; + this.eStart = eStart; + this.render = render; + } + + long size; /* number of triangles used */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eStart; /* edge where this primitive starts */ + renderCallBack render; + }; + + private static interface renderCallBack { + void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size); + } + + /************************ Strips and Fans decomposition ******************/ + +/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle + * fans, strips, and separate triangles. A substantial effort is made + * to use as few rendering primitives as possible (ie. to make the fans + * and strips as large as possible). + * + * The rendering output is provided as callbacks (see the api). + */ + public static void __gl_renderMesh(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + + /* Make a list of separate triangles so we can render them all at once */ + tess.lonelyTriList = null; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + f.marked = false; + } + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + + /* We examine all faces in an arbitrary order. Whenever we find + * an unprocessed face F, we output a group of faces including F + * whose size is maximum. + */ + if (f.inside && !f.marked) { + RenderMaximumFaceGroup(tess, f); + assert (f.marked); + } + } + if (tess.lonelyTriList != null) { + RenderLonelyTriangles(tess, tess.lonelyTriList); + tess.lonelyTriList = null; + } + } + + + static void RenderMaximumFaceGroup(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUface fOrig) { + /* We want to find the largest triangle fan or strip of unmarked faces + * which includes the given face fOrig. There are 3 possible fans + * passing through fOrig (one centered at each vertex), and 3 possible + * strips (one for each CCW permutation of the vertices). Our strategy + * is to try all of these, and take the primitive which uses the most + * triangles (a greedy approach). + */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e = fOrig.anEdge; + FaceCount max = new FaceCount(); + FaceCount newFace = new FaceCount(); + + max.size = 1; + max.eStart = e; + max.render = renderTriangle; + + if (!tess.flagBoundary) { + newFace = MaximumFan(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumFan(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + + newFace = MaximumStrip(e); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Lnext); + if (newFace.size > max.size) { + max = newFace; + } + newFace = MaximumStrip(e.Onext.Sym); + if (newFace.size > max.size) { + max = newFace; + } + } + max.render.render(tess, max.eStart, max.size); + } + + +/* Macros which keep track of faces we have marked temporarily, and allow + * us to backtrack when necessary. With triangle fans, this is not + * really necessary, since the only awkward case is a loop of triangles + * around a single origin vertex. However with strips the situation is + * more complicated, and we need a general tracking method like the + * one here. + */ + private static boolean Marked(com.jogamp.opengl.impl.glu.tessellator.GLUface f) { + return !f.inside || f.marked; + } + + private static GLUface AddToTrail(com.jogamp.opengl.impl.glu.tessellator.GLUface f, com.jogamp.opengl.impl.glu.tessellator.GLUface t) { + f.trail = t; + f.marked = true; + return f; + } + + private static void FreeTrail(com.jogamp.opengl.impl.glu.tessellator.GLUface t) { + if (true) { + while (t != null) { + t.marked = false; + t = t.trail; + } + } else { + /* absorb trailing semicolon */ + } + } + + static FaceCount MaximumFan(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* eOrig.Lface is the face we want to render. We want to find the size + * of a maximal fan around eOrig.Org. To do this we just walk around + * the origin vertex as far as possible in both directions. + */ + FaceCount newFace = new FaceCount(0, null, renderFan); + com.jogamp.opengl.impl.glu.tessellator.GLUface trail = null; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (e = eOrig; !Marked(e.Lface); e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++newFace.size; + } + for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext) { + trail = AddToTrail(e.Sym.Lface, trail); + ++newFace.size; + } + newFace.eStart = e; + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + + private static boolean IsEven(long n) { + return (n & 0x1L) == 0; + } + + static FaceCount MaximumStrip(com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge eOrig) { + /* Here we are looking for a maximal strip that contains the vertices + * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the + * reverse, such that all triangles are oriented CCW). + * + * Again we walk forward and backward as far as possible. However for + * strips there is a twist: to get CCW orientations, there must be + * an *even* number of triangles in the strip on one side of eOrig. + * We walk the strip starting on a side with an even number of triangles; + * if both side have an odd number, we are forced to shorten one side. + */ + FaceCount newFace = new FaceCount(0, null, renderStrip); + long headSize = 0, tailSize = 0; + com.jogamp.opengl.impl.glu.tessellator.GLUface trail = null; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, eTail, eHead; + + for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext) { + trail = AddToTrail(e.Lface, trail); + ++tailSize; + e = e.Lnext.Sym; + if (Marked(e.Lface)) break; + trail = AddToTrail(e.Lface, trail); + } + eTail = e; + + for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym) { + trail = AddToTrail(e.Sym.Lface, trail); + ++headSize; + e = e.Sym.Lnext; + if (Marked(e.Sym.Lface)) break; + trail = AddToTrail(e.Sym.Lface, trail); + } + eHead = e; + + newFace.size = tailSize + headSize; + if (IsEven(tailSize)) { + newFace.eStart = eTail.Sym; + } else if (IsEven(headSize)) { + newFace.eStart = eHead; + } else { + /* Both sides have odd length, we must shorten one of them. In fact, + * we must start from eHead to guarantee inclusion of eOrig.Lface. + */ + --newFace.size; + newFace.eStart = eHead.Onext; + } + /*LINTED*/ + FreeTrail(trail); + return newFace; + } + + private static class RenderTriangle implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Just add the triangle to a triangle list, so we can render all + * the separate triangles at once. + */ + assert (size == 1); + tess.lonelyTriList = AddToTrail(e.Lface, tess.lonelyTriList); + } + } + + + static void RenderLonelyTriangles(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUface f) { + /* Now we render all the separate triangles which could not be + * grouped into a triangle fan or strip. + */ + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + int newState; + int edgeState = -1; /* force edge state output for first vertex */ + + tess.callBeginOrBeginData(GL.GL_TRIANGLES); + + for (; f != null; f = f.trail) { + /* Loop once for each edge (there will always be 3 edges) */ + + e = f.anEdge; + do { + if (tess.flagBoundary) { + /* Set the "edge state" to true just before we output the + * first vertex of each edge on the polygon boundary. + */ + newState = (!e.Sym.Lface.inside) ? 1 : 0; + if (edgeState != newState) { + edgeState = newState; + tess.callEdgeFlagOrEdgeFlagData( edgeState != 0); + } + } + tess.callVertexOrVertexData( e.Org.data); + + e = e.Lnext; + } while (e != f.anEdge); + } + tess.callEndOrEndData(); + } + + private static class RenderFan implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a fan starting from + * edge "e". The fan *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL.GL_TRIANGLE_FAN); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + private static class RenderStrip implements renderCallBack { + public void render(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e, long size) { + /* Render as many CCW triangles as possible in a strip starting from + * edge "e". The strip *should* contain exactly "size" triangles + * (otherwise we've goofed up somewhere). + */ + tess.callBeginOrBeginData( GL.GL_TRIANGLE_STRIP); + tess.callVertexOrVertexData( e.Org.data); + tess.callVertexOrVertexData( e.Sym.Org.data); + + while (!Marked(e.Lface)) { + e.Lface.marked = true; + --size; + e = e.Lnext.Sym; + tess.callVertexOrVertexData( e.Org.data); + if (Marked(e.Lface)) break; + + e.Lface.marked = true; + --size; + e = e.Onext; + tess.callVertexOrVertexData( e.Sym.Org.data); + } + + assert (size == 0); + tess.callEndOrEndData(); + } + } + + /************************ Boundary contour decomposition ******************/ + +/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one + * contour for each face marked "inside". The rendering output is + * provided as callbacks (see the api). + */ + public static void __gl_renderBoundary(GLUtessellatorImpl tess, com.jogamp.opengl.impl.glu.tessellator.GLUmesh mesh) { + com.jogamp.opengl.impl.glu.tessellator.GLUface f; + com.jogamp.opengl.impl.glu.tessellator.GLUhalfEdge e; + + for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { + if (f.inside) { + tess.callBeginOrBeginData( GL.GL_LINE_LOOP); + e = f.anEdge; + do { + tess.callVertexOrVertexData( e.Org.data); + e = e.Lnext; + } while (e != f.anEdge); + tess.callEndOrEndData(); + } + } + } + + + /************************ Quick-and-dirty decomposition ******************/ + + private static final int SIGN_INCONSISTENT = 2; + + static int ComputeNormal(GLUtessellatorImpl tess, double[] norm, boolean check) +/* + * If check==false, we compute the polygon normal and place it in norm[]. + * If check==true, we check that each triangle in the fan from v0 has a + * consistent orientation with respect to norm[]. If triangles are + * consistently oriented CCW, return 1; if CW, return -1; if all triangles + * are degenerate return 0; otherwise (no consistent orientation) return + * SIGN_INCONSISTENT. + */ { + com.jogamp.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double dot, xc, yc, zc, xp, yp, zp; + double[] n = new double[3]; + int sign = 0; + + /* Find the polygon normal. It is important to get a reasonable + * normal even when the polygon is self-intersecting (eg. a bowtie). + * Otherwise, the computed normal could be very tiny, but perpendicular + * to the true plane of the polygon due to numerical noise. Then all + * the triangles would appear to be degenerate and we would incorrectly + * decompose the polygon as a fan (or simply not render it at all). + * + * We use a sum-of-triangles normal algorithm rather than the more + * efficient sum-of-trapezoids method (used in CheckOrientation() + * in normal.c). This lets us explicitly reverse the signed area + * of some triangles to get a reasonable normal in the self-intersecting + * case. + */ + if (!check) { + norm[0] = norm[1] = norm[2] = 0.0; + } + + vc = 1; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + while (++vc < vn) { + xp = xc; + yp = yc; + zp = zc; + xc = v[vc].coords[0] - v[0].coords[0]; + yc = v[vc].coords[1] - v[0].coords[1]; + zc = v[vc].coords[2] - v[0].coords[2]; + + /* Compute (vp - v0) cross (vc - v0) */ + n[0] = yp * zc - zp * yc; + n[1] = zp * xc - xp * zc; + n[2] = xp * yc - yp * xc; + + dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; + if (!check) { + /* Reverse the contribution of back-facing triangles to get + * a reasonable normal for self-intersecting polygons (see above) + */ + if (dot >= 0) { + norm[0] += n[0]; + norm[1] += n[1]; + norm[2] += n[2]; + } else { + norm[0] -= n[0]; + norm[1] -= n[1]; + norm[2] -= n[2]; + } + } else if (dot != 0) { + /* Check the new orientation for consistency with previous triangles */ + if (dot > 0) { + if (sign < 0) return SIGN_INCONSISTENT; + sign = 1; + } else { + if (sign > 0) return SIGN_INCONSISTENT; + sign = -1; + } + } + } + return sign; + } + +/* __gl_renderCache( tess ) takes a single contour and tries to render it + * as a triangle fan. This handles convex polygons, as well as some + * non-convex polygons if we get lucky. + * + * Returns true if the polygon was successfully rendered. The rendering + * output is provided as callbacks (see the api). + */ + public static boolean __gl_renderCache(GLUtessellatorImpl tess) { + com.jogamp.opengl.impl.glu.tessellator.CachedVertex[] v = tess.cache; +// CachedVertex vn = v0 + tess.cacheCount; + int vn = tess.cacheCount; +// CachedVertex vc; + int vc; + double[] norm = new double[3]; + int sign; + + if (tess.cacheCount < 3) { + /* Degenerate contour -- no output */ + return true; + } + + norm[0] = tess.normal[0]; + norm[1] = tess.normal[1]; + norm[2] = tess.normal[2]; + if (norm[0] == 0 && norm[1] == 0 && norm[2] == 0) { + ComputeNormal( tess, norm, false); + } + + sign = ComputeNormal( tess, norm, true); + if (sign == SIGN_INCONSISTENT) { + /* Fan triangles did not have a consistent orientation */ + return false; + } + if (sign == 0) { + /* All triangles were degenerate */ + return true; + } + + if ( !USE_OPTIMIZED_CODE_PATH ) { + return false; + } else { + /* Make sure we do the right thing for each winding rule */ + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + case GLU.GLU_TESS_WINDING_NONZERO: + break; + case GLU.GLU_TESS_WINDING_POSITIVE: + if (sign < 0) return true; + break; + case GLU.GLU_TESS_WINDING_NEGATIVE: + if (sign > 0) return true; + break; + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return true; + } + + tess.callBeginOrBeginData( tess.boundaryOnly ? GL.GL_LINE_LOOP + : (tess.cacheCount > 3) ? GL.GL_TRIANGLE_FAN + : GL.GL_TRIANGLES); + + tess.callVertexOrVertexData( v[0].data); + if (sign > 0) { + for (vc = 1; vc < vn; ++vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } else { + for (vc = vn - 1; vc > 0; --vc) { + tess.callVertexOrVertexData( v[vc].data); + } + } + tess.callEndOrEndData(); + return true; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java new file mode 100644 index 000000000..8ffeadb67 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/Sweep.java @@ -0,0 +1,1353 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; + +class Sweep { + private Sweep() { + } + +// #ifdef FOR_TRITE_TEST_PROGRAM +// extern void DebugEvent( GLUtessellator *tess ); +// #else + private static void DebugEvent(GLUtessellatorImpl tess) { + + } +// #endif + +/* + * Invariants for the Edge Dictionary. + * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2) + * at any valid location of the sweep event + * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2 + * share a common endpoint + * - for each e, e.Dst has been processed, but not e.Org + * - each edge e satisfies VertLeq(e.Dst,event) && VertLeq(event,e.Org) + * where "event" is the current sweep line event. + * - no edge e has zero length + * + * Invariants for the Mesh (the processed portion). + * - the portion of the mesh left of the sweep line is a planar graph, + * ie. there is *some* way to embed it in the plane + * - no processed edge has zero length + * - no two processed vertices have identical coordinates + * - each "inside" region is monotone, ie. can be broken into two chains + * of monotonically increasing vertices according to VertLeq(v1,v2) + * - a non-invariant: these chains may intersect (very slightly) + * + * Invariants for the Sweep. + * - if none of the edges incident to the event vertex have an activeRegion + * (ie. none of these edges are in the edge dictionary), then the vertex + * has only right-going edges. + * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced + * by ConnectRightVertex), then it is the only right-going edge from + * its associated vertex. (This says that these edges exist only + * when it is necessary.) + */ + +/* When we merge two edges into one, we need to compute the combined + * winding of the new edge. + */ + private static void AddWinding(GLUhalfEdge eDst, GLUhalfEdge eSrc) { + eDst.winding += eSrc.winding; + eDst.Sym.winding += eSrc.Sym.winding; + } + + + private static ActiveRegion RegionBelow(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictPred(r.nodeUp))); + } + + private static ActiveRegion RegionAbove(ActiveRegion r) { + return ((ActiveRegion) Dict.dictKey(Dict.dictSucc(r.nodeUp))); + } + + static boolean EdgeLeq(GLUtessellatorImpl tess, ActiveRegion reg1, ActiveRegion reg2) +/* + * Both edges must be directed from right to left (this is the canonical + * direction for the upper edge of each region). + * + * The strategy is to evaluate a "t" value for each edge at the + * current sweep line position, given by tess.event. The calculations + * are designed to be very stable, but of course they are not perfect. + * + * Special case: if both edge destinations are at the sweep event, + * we sort the edges by slope (they would otherwise compare equally). + */ { + GLUvertex event = tess.event; + GLUhalfEdge e1, e2; + double t1, t2; + + e1 = reg1.eUp; + e2 = reg2.eUp; + + if (e1.Sym.Org == event) { + if (e2.Sym.Org == event) { + /* Two edges right of the sweep line which meet at the sweep event. + * Sort them by slope. + */ + if (Geom.VertLeq(e1.Org, e2.Org)) { + return Geom.EdgeSign(e2.Sym.Org, e1.Org, e2.Org) <= 0; + } + return Geom.EdgeSign(e1.Sym.Org, e2.Org, e1.Org) >= 0; + } + return Geom.EdgeSign(e2.Sym.Org, event, e2.Org) <= 0; + } + if (e2.Sym.Org == event) { + return Geom.EdgeSign(e1.Sym.Org, event, e1.Org) >= 0; + } + + /* General case - compute signed distance *from* e1, e2 to event */ + t1 = Geom.EdgeEval(e1.Sym.Org, event, e1.Org); + t2 = Geom.EdgeEval(e2.Sym.Org, event, e2.Org); + return (t1 >= t2); + } + + + static void DeleteRegion(GLUtessellatorImpl tess, ActiveRegion reg) { + if (reg.fixUpperEdge) { + /* It was created with zero winding number, so it better be + * deleted with zero winding number (ie. it better not get merged + * with a real edge). + */ + assert (reg.eUp.winding == 0); + } + reg.eUp.activeRegion = null; + Dict.dictDelete(tess.dict, reg.nodeUp); /* __gl_dictListDelete */ + } + + + static boolean FixUpperEdge(ActiveRegion reg, GLUhalfEdge newEdge) +/* + * Replace an upper edge which needs fixing (see ConnectRightVertex). + */ { + assert (reg.fixUpperEdge); + if (!Mesh.__gl_meshDelete(reg.eUp)) return false; + reg.fixUpperEdge = false; + reg.eUp = newEdge; + newEdge.activeRegion = reg; + + return true; + } + + static ActiveRegion TopLeftRegion(ActiveRegion reg) { + GLUvertex org = reg.eUp.Org; + GLUhalfEdge e; + + /* Find the region above the uppermost edge with the same origin */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Org == org); + + /* If the edge above was a temporary edge introduced by ConnectRightVertex, + * now is the time to fix it. + */ + if (reg.fixUpperEdge) { + e = Mesh.__gl_meshConnect(RegionBelow(reg).eUp.Sym, reg.eUp.Lnext); + if (e == null) return null; + if (!FixUpperEdge(reg, e)) return null; + reg = RegionAbove(reg); + } + return reg; + } + + static ActiveRegion TopRightRegion(ActiveRegion reg) { + GLUvertex dst = reg.eUp.Sym.Org; + + /* Find the region above the uppermost edge with the same destination */ + do { + reg = RegionAbove(reg); + } while (reg.eUp.Sym.Org == dst); + return reg; + } + + static ActiveRegion AddRegionBelow(GLUtessellatorImpl tess, + ActiveRegion regAbove, + GLUhalfEdge eNewUp) +/* + * Add a new active region to the sweep line, *somewhere* below "regAbove" + * (according to where the new edge belongs in the sweep-line dictionary). + * The upper edge of the new region will be "eNewUp". + * Winding number and "inside" flag are not updated. + */ { + ActiveRegion regNew = new ActiveRegion(); + if (regNew == null) throw new RuntimeException(); + + regNew.eUp = eNewUp; + /* __gl_dictListInsertBefore */ + regNew.nodeUp = Dict.dictInsertBefore(tess.dict, regAbove.nodeUp, regNew); + if (regNew.nodeUp == null) throw new RuntimeException(); + regNew.fixUpperEdge = false; + regNew.sentinel = false; + regNew.dirty = false; + + eNewUp.activeRegion = regNew; + return regNew; + } + + static boolean IsWindingInside(GLUtessellatorImpl tess, int n) { + switch (tess.windingRule) { + case GLU.GLU_TESS_WINDING_ODD: + return (n & 1) != 0; + case GLU.GLU_TESS_WINDING_NONZERO: + return (n != 0); + case GLU.GLU_TESS_WINDING_POSITIVE: + return (n > 0); + case GLU.GLU_TESS_WINDING_NEGATIVE: + return (n < 0); + case GLU.GLU_TESS_WINDING_ABS_GEQ_TWO: + return (n >= 2) || (n <= -2); + } + /*LINTED*/ +// assert (false); + throw new InternalError(); + /*NOTREACHED*/ + } + + + static void ComputeWinding(GLUtessellatorImpl tess, ActiveRegion reg) { + reg.windingNumber = RegionAbove(reg).windingNumber + reg.eUp.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + } + + + static void FinishRegion(GLUtessellatorImpl tess, ActiveRegion reg) +/* + * Delete a region from the sweep line. This happens when the upper + * and lower chains of a region meet (at a vertex on the sweep line). + * The "inside" flag is copied to the appropriate mesh face (we could + * not do this before -- since the structure of the mesh is always + * changing, this face may not have even existed until now). + */ { + GLUhalfEdge e = reg.eUp; + GLUface f = e.Lface; + + f.inside = reg.inside; + f.anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */ + DeleteRegion(tess, reg); + } + + + static GLUhalfEdge FinishLeftRegions(GLUtessellatorImpl tess, + ActiveRegion regFirst, ActiveRegion regLast) +/* + * We are given a vertex with one or more left-going edges. All affected + * edges should be in the edge dictionary. Starting at regFirst.eUp, + * we walk down deleting all regions where both edges have the same + * origin vOrg. At the same time we copy the "inside" flag from the + * active region to the face, since at this point each face will belong + * to at most one region (this was not necessarily true until this point + * in the sweep). The walk stops at the region above regLast; if regLast + * is null we walk as far as possible. At the same time we relink the + * mesh if necessary, so that the ordering of edges around vOrg is the + * same as in the dictionary. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + + regPrev = regFirst; + ePrev = regFirst.eUp; + while (regPrev != regLast) { + regPrev.fixUpperEdge = false; /* placement was OK */ + reg = RegionBelow(regPrev); + e = reg.eUp; + if (e.Org != ePrev.Org) { + if (!reg.fixUpperEdge) { + /* Remove the last left-going edge. Even though there are no further + * edges in the dictionary with this origin, there may be further + * such edges in the mesh (if we are adding left edges to a vertex + * that has already been processed). Thus it is important to call + * FinishRegion rather than just DeleteRegion. + */ + FinishRegion(tess, regPrev); + break; + } + /* If the edge below was a temporary edge introduced by + * ConnectRightVertex, now is the time to fix it. + */ + e = Mesh.__gl_meshConnect(ePrev.Onext.Sym, e.Sym); + if (e == null) throw new RuntimeException(); + if (!FixUpperEdge(reg, e)) throw new RuntimeException(); + } + + /* Relink edges so that ePrev.Onext == e */ + if (ePrev.Onext != e) { + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev, e)) throw new RuntimeException(); + } + FinishRegion(tess, regPrev); /* may change reg.eUp */ + ePrev = reg.eUp; + regPrev = reg; + } + return ePrev; + } + + + static void AddRightEdges(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eFirst, GLUhalfEdge eLast, GLUhalfEdge eTopLeft, + boolean cleanUp) +/* + * Purpose: insert right-going edges into the edge dictionary, and update + * winding numbers and mesh connectivity appropriately. All right-going + * edges share a common origin vOrg. Edges are inserted CCW starting at + * eFirst; the last edge inserted is eLast.Sym.Lnext. If vOrg has any + * left-going edges already processed, then eTopLeft must be the edge + * such that an imaginary upward vertical segment from vOrg would be + * contained between eTopLeft.Sym.Lnext and eTopLeft; otherwise eTopLeft + * should be null. + */ { + ActiveRegion reg, regPrev; + GLUhalfEdge e, ePrev; + boolean firstTime = true; + + /* Insert the new right-going edges in the dictionary */ + e = eFirst; + do { + assert (Geom.VertLeq(e.Org, e.Sym.Org)); + AddRegionBelow(tess, regUp, e.Sym); + e = e.Onext; + } while (e != eLast); + + /* Walk *all* right-going edges from e.Org, in the dictionary order, + * updating the winding numbers of each region, and re-linking the mesh + * edges to match the dictionary ordering (if necessary). + */ + if (eTopLeft == null) { + eTopLeft = RegionBelow(regUp).eUp.Sym.Onext; + } + regPrev = regUp; + ePrev = eTopLeft; + for (; ;) { + reg = RegionBelow(regPrev); + e = reg.eUp.Sym; + if (e.Org != ePrev.Org) break; + + if (e.Onext != ePrev) { + /* Unlink e from its current position, and relink below ePrev */ + if (!Mesh.__gl_meshSplice(e.Sym.Lnext, e)) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(ePrev.Sym.Lnext, e)) throw new RuntimeException(); + } + /* Compute the winding number and "inside" flag for the new regions */ + reg.windingNumber = regPrev.windingNumber - e.winding; + reg.inside = IsWindingInside(tess, reg.windingNumber); + + /* Check for two outgoing edges with same slope -- process these + * before any intersection tests (see example in __gl_computeInterior). + */ + regPrev.dirty = true; + if (!firstTime && CheckForRightSplice(tess, regPrev)) { + AddWinding(e, ePrev); + DeleteRegion(tess, regPrev); + if (!Mesh.__gl_meshDelete(ePrev)) throw new RuntimeException(); + } + firstTime = false; + regPrev = reg; + ePrev = e; + } + regPrev.dirty = true; + assert (regPrev.windingNumber - e.winding == reg.windingNumber); + + if (cleanUp) { + /* Check for intersections between newly adjacent edges. */ + WalkDirtyRegions(tess, regPrev); + } + } + + + static void CallCombine(GLUtessellatorImpl tess, GLUvertex isect, + Object[] data, float[] weights, boolean needed) { + double[] coords = new double[3]; + + /* Copy coord data in case the callback changes it. */ + coords[0] = isect.coords[0]; + coords[1] = isect.coords[1]; + coords[2] = isect.coords[2]; + + Object[] outData = new Object[1]; + tess.callCombineOrCombineData(coords, data, weights, outData); + isect.data = outData[0]; + if (isect.data == null) { + if (!needed) { + isect.data = data[0]; + } else if (!tess.fatalError) { + /* The only way fatal error is when two edges are found to intersect, + * but the user has not provided the callback necessary to handle + * generated intersection points. + */ + tess.callErrorOrErrorData(GLU.GLU_TESS_NEED_COMBINE_CALLBACK); + tess.fatalError = true; + } + } + } + + static void SpliceMergeVertices(GLUtessellatorImpl tess, GLUhalfEdge e1, + GLUhalfEdge e2) +/* + * Two vertices with idential coordinates are combined into one. + * e1.Org is kept, while e2.Org is discarded. + */ { + Object[] data = new Object[4]; + float[] weights = new float[]{0.5f, 0.5f, 0.0f, 0.0f}; + + data[0] = e1.Org.data; + data[1] = e2.Org.data; + CallCombine(tess, e1.Org, data, weights, false); + if (!Mesh.__gl_meshSplice(e1, e2)) throw new RuntimeException(); + } + + static void VertexWeights(GLUvertex isect, GLUvertex org, GLUvertex dst, + float[] weights) +/* + * Find some weights which describe how the intersection vertex is + * a linear combination of "org" and "dest". Each of the two edges + * which generated "isect" is allocated 50% of the weight; each edge + * splits the weight between its org and dst according to the + * relative distance to "isect". + */ { + double t1 = Geom.VertL1dist(org, isect); + double t2 = Geom.VertL1dist(dst, isect); + + weights[0] = (float) (0.5 * t2 / (t1 + t2)); + weights[1] = (float) (0.5 * t1 / (t1 + t2)); + isect.coords[0] += weights[0] * org.coords[0] + weights[1] * dst.coords[0]; + isect.coords[1] += weights[0] * org.coords[1] + weights[1] * dst.coords[1]; + isect.coords[2] += weights[0] * org.coords[2] + weights[1] * dst.coords[2]; + } + + + static void GetIntersectData(GLUtessellatorImpl tess, GLUvertex isect, + GLUvertex orgUp, GLUvertex dstUp, + GLUvertex orgLo, GLUvertex dstLo) +/* + * We've computed a new intersection point, now we need a "data" pointer + * from the user so that we can refer to this new vertex in the + * rendering callbacks. + */ { + Object[] data = new Object[4]; + float[] weights = new float[4]; + float[] weights1 = new float[2]; + float[] weights2 = new float[2]; + + data[0] = orgUp.data; + data[1] = dstUp.data; + data[2] = orgLo.data; + data[3] = dstLo.data; + + isect.coords[0] = isect.coords[1] = isect.coords[2] = 0; + VertexWeights(isect, orgUp, dstUp, weights1); + VertexWeights(isect, orgLo, dstLo, weights2); + System.arraycopy(weights1, 0, weights, 0, 2); + System.arraycopy(weights2, 0, weights, 2, 2); + + CallCombine(tess, isect, data, weights, true); + } + + static boolean CheckForRightSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Org is above eLo, or eLo.Org is below eUp (depending on which + * origin is leftmost). + * + * The main purpose is to splice right-going edges with the same + * dest vertex and nearly identical slopes (ie. we can't distinguish + * the slopes numerically). However the splicing can also help us + * to recover from numerical errors. For example, suppose at one + * point we checked eUp and eLo, and decided that eUp.Org is barely + * above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * our test so that now eUp.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants. + * + * One possibility is to check these edges for intersection again + * (ie. CheckForIntersect). This is what we do if possible. However + * CheckForIntersect requires that tess.event lies between eUp and eLo, + * so that it has something to fall back on when the intersection + * calculation gives us an unusable answer. So, for those cases where + * we can't check for intersection, this routine fixes the problem + * by just splicing the offending vertex into the other edge. + * This is a guaranteed solution, no matter how degenerate things get. + * Basically this is a combinatorial solution to a numerical problem. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + + if (Geom.VertLeq(eUp.Org, eLo.Org)) { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Org, eLo.Org) > 0) return false; + + /* eUp.Org appears to be below eLo */ + if (!Geom.VertEq(eUp.Org, eLo.Org)) { + /* Splice eUp.Org into eLo */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp, eLo.Sym.Lnext)) throw new RuntimeException(); + regUp.dirty = regLo.dirty = true; + + } else if (eUp.Org != eLo.Org) { + /* merge the two vertices, discarding eUp.Org */ + tess.pq.pqDelete(eUp.Org.pqHandle); /* __gl_pqSortDelete */ + SpliceMergeVertices(tess, eLo.Sym.Lnext, eUp); + } + } else { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Org, eUp.Org) < 0) return false; + + /* eLo.Org appears to be above eUp, so splice eLo.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + } + return true; + } + + static boolean CheckForLeftSplice(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edge of "regUp", to make sure that the + * eUp.Sym.Org is above eLo, or eLo.Sym.Org is below eUp (depending on which + * destination is rightmost). + * + * Theoretically, this should always be true. However, splitting an edge + * into two pieces can change the results of previous tests. For example, + * suppose at one point we checked eUp and eLo, and decided that eUp.Sym.Org + * is barely above eLo. Then later, we split eLo into two edges (eg. from + * a splice operation like this one). This can change the result of + * the test so that now eUp.Sym.Org is incident to eLo, or barely below it. + * We must correct this condition to maintain the dictionary invariants + * (otherwise new edges might get inserted in the wrong place in the + * dictionary, and bad stuff will happen). + * + * We fix the problem by just splicing the offending vertex into the + * other edge. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUhalfEdge e; + + assert (!Geom.VertEq(eUp.Sym.Org, eLo.Sym.Org)); + + if (Geom.VertLeq(eUp.Sym.Org, eLo.Sym.Org)) { + if (Geom.EdgeSign(eUp.Sym.Org, eLo.Sym.Org, eUp.Org) < 0) return false; + + /* eLo.Sym.Org is above eUp, so splice eLo.Sym.Org into eUp */ + RegionAbove(regUp).dirty = regUp.dirty = true; + e = Mesh.__gl_meshSplitEdge(eUp); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, e)) throw new RuntimeException(); + e.Lface.inside = regUp.inside; + } else { + if (Geom.EdgeSign(eLo.Sym.Org, eUp.Sym.Org, eLo.Org) > 0) return false; + + /* eUp.Sym.Org is below eLo, so splice eUp.Sym.Org into eLo */ + regUp.dirty = regLo.dirty = true; + e = Mesh.__gl_meshSplitEdge(eLo); + if (e == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym)) throw new RuntimeException(); + e.Sym.Lface.inside = regUp.inside; + } + return true; + } + + + static boolean CheckForIntersect(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * Check the upper and lower edges of the given region to see if + * they intersect. If so, create the intersection and add it + * to the data structures. + * + * Returns true if adding the new intersection resulted in a recursive + * call to AddRightEdges(); in this case all "dirty" regions have been + * checked for intersections, and possibly regUp has been deleted. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + GLUvertex orgUp = eUp.Org; + GLUvertex orgLo = eLo.Org; + GLUvertex dstUp = eUp.Sym.Org; + GLUvertex dstLo = eLo.Sym.Org; + double tMinUp, tMaxLo; + GLUvertex isect = new GLUvertex(); + GLUvertex orgMin; + GLUhalfEdge e; + + assert (!Geom.VertEq(dstLo, dstUp)); + assert (Geom.EdgeSign(dstUp, tess.event, orgUp) <= 0); + assert (Geom.EdgeSign(dstLo, tess.event, orgLo) >= 0); + assert (orgUp != tess.event && orgLo != tess.event); + assert (!regUp.fixUpperEdge && !regLo.fixUpperEdge); + + if (orgUp == orgLo) return false; /* right endpoints are the same */ + + tMinUp = Math.min(orgUp.t, dstUp.t); + tMaxLo = Math.max(orgLo.t, dstLo.t); + if (tMinUp > tMaxLo) return false; /* t ranges do not overlap */ + + if (Geom.VertLeq(orgUp, orgLo)) { + if (Geom.EdgeSign(dstLo, orgUp, orgLo) > 0) return false; + } else { + if (Geom.EdgeSign(dstUp, orgLo, orgUp) < 0) return false; + } + + /* At this point the edges intersect, at least marginally */ + DebugEvent(tess); + + Geom.EdgeIntersect(dstUp, orgUp, dstLo, orgLo, isect); + /* The following properties are guaranteed: */ + assert (Math.min(orgUp.t, dstUp.t) <= isect.t); + assert (isect.t <= Math.max(orgLo.t, dstLo.t)); + assert (Math.min(dstLo.s, dstUp.s) <= isect.s); + assert (isect.s <= Math.max(orgLo.s, orgUp.s)); + + if (Geom.VertLeq(isect, tess.event)) { + /* The intersection point lies slightly to the left of the sweep line, + * so move it until it''s slightly to the right of the sweep line. + * (If we had perfect numerical precision, this would never happen + * in the first place). The easiest and safest thing to do is + * replace the intersection by tess.event. + */ + isect.s = tess.event.s; + isect.t = tess.event.t; + } + /* Similarly, if the computed intersection lies to the right of the + * rightmost origin (which should rarely happen), it can cause + * unbelievable inefficiency on sufficiently degenerate inputs. + * (If you have the test program, try running test54.d with the + * "X zoom" option turned on). + */ + orgMin = Geom.VertLeq(orgUp, orgLo) ? orgUp : orgLo; + if (Geom.VertLeq(orgMin, isect)) { + isect.s = orgMin.s; + isect.t = orgMin.t; + } + + if (Geom.VertEq(isect, orgUp) || Geom.VertEq(isect, orgLo)) { + /* Easy case -- intersection at one of the right endpoints */ + CheckForRightSplice(tess, regUp); + return false; + } + + if ((!Geom.VertEq(dstUp, tess.event) + && Geom.EdgeSign(dstUp, tess.event, isect) >= 0) + || (!Geom.VertEq(dstLo, tess.event) + && Geom.EdgeSign(dstLo, tess.event, isect) <= 0)) { + /* Very unusual -- the new upper or lower edge would pass on the + * wrong side of the sweep event, or through it. This can happen + * due to very small numerical errors in the intersection calculation. + */ + if (dstLo == tess.event) { + /* Splice dstLo into eUp, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eUp = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + AddRightEdges(tess, regUp, eUp.Sym.Lnext, eUp, eUp, true); + return true; + } + if (dstUp == tess.event) { + /* Splice dstUp into eLo, and process the new region(s) */ + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eUp.Lnext, eLo.Sym.Lnext)) throw new RuntimeException(); + regLo = regUp; + regUp = TopRightRegion(regUp); + e = RegionBelow(regUp).eUp.Sym.Onext; + regLo.eUp = eLo.Sym.Lnext; + eLo = FinishLeftRegions(tess, regLo, null); + AddRightEdges(tess, regUp, eLo.Onext, eUp.Sym.Onext, e, true); + return true; + } + /* Special case: called from ConnectRightVertex. If either + * edge passes on the wrong side of tess.event, split it + * (and wait for ConnectRightVertex to splice it appropriately). + */ + if (Geom.EdgeSign(dstUp, tess.event, isect) >= 0) { + RegionAbove(regUp).dirty = regUp.dirty = true; + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + eUp.Org.s = tess.event.s; + eUp.Org.t = tess.event.t; + } + if (Geom.EdgeSign(dstLo, tess.event, isect) <= 0) { + regUp.dirty = regLo.dirty = true; + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + eLo.Org.s = tess.event.s; + eLo.Org.t = tess.event.t; + } + /* leave the rest for ConnectRightVertex */ + return false; + } + + /* General case -- split both edges, splice into new vertex. + * When we do the splice operation, the order of the arguments is + * arbitrary as far as correctness goes. However, when the operation + * creates a new face, the work done is proportional to the size of + * the new face. We expect the faces in the processed part of + * the mesh (ie. eUp.Lface) to be smaller than the faces in the + * unprocessed original contours (which will be eLo.Sym.Lnext.Lface). + */ + if (Mesh.__gl_meshSplitEdge(eUp.Sym) == null) throw new RuntimeException(); + if (Mesh.__gl_meshSplitEdge(eLo.Sym) == null) throw new RuntimeException(); + if (!Mesh.__gl_meshSplice(eLo.Sym.Lnext, eUp)) throw new RuntimeException(); + eUp.Org.s = isect.s; + eUp.Org.t = isect.t; + eUp.Org.pqHandle = tess.pq.pqInsert(eUp.Org); /* __gl_pqSortInsert */ + if (eUp.Org.pqHandle == Long.MAX_VALUE) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + throw new RuntimeException(); + } + GetIntersectData(tess, eUp.Org, orgUp, dstUp, orgLo, dstLo); + RegionAbove(regUp).dirty = regUp.dirty = regLo.dirty = true; + return false; + } + + static void WalkDirtyRegions(GLUtessellatorImpl tess, ActiveRegion regUp) +/* + * When the upper or lower edge of any region changes, the region is + * marked "dirty". This routine walks through all the dirty regions + * and makes sure that the dictionary invariants are satisfied + * (see the comments at the beginning of this file). Of course + * new dirty regions can be created as we make changes to restore + * the invariants. + */ { + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp, eLo; + + for (; ;) { + /* Find the lowest dirty region (we walk from the bottom up). */ + while (regLo.dirty) { + regUp = regLo; + regLo = RegionBelow(regLo); + } + if (!regUp.dirty) { + regLo = regUp; + regUp = RegionAbove(regUp); + if (regUp == null || !regUp.dirty) { + /* We've walked all the dirty regions */ + return; + } + } + regUp.dirty = false; + eUp = regUp.eUp; + eLo = regLo.eUp; + + if (eUp.Sym.Org != eLo.Sym.Org) { + /* Check that the edge ordering is obeyed at the Dst vertices. */ + if (CheckForLeftSplice(tess, regUp)) { + + /* If the upper or lower edge was marked fixUpperEdge, then + * we no longer need it (since these edges are needed only for + * vertices which otherwise have no right-going edges). + */ + if (regLo.fixUpperEdge) { + DeleteRegion(tess, regLo); + if (!Mesh.__gl_meshDelete(eLo)) throw new RuntimeException(); + regLo = RegionBelow(regUp); + eLo = regLo.eUp; + } else if (regUp.fixUpperEdge) { + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + eUp = regUp.eUp; + } + } + } + if (eUp.Org != eLo.Org) { + if (eUp.Sym.Org != eLo.Sym.Org + && !regUp.fixUpperEdge && !regLo.fixUpperEdge + && (eUp.Sym.Org == tess.event || eLo.Sym.Org == tess.event)) { + /* When all else fails in CheckForIntersect(), it uses tess.event + * as the intersection location. To make this possible, it requires + * that tess.event lie between the upper and lower edges, and also + * that neither of these is marked fixUpperEdge (since in the worst + * case it might splice one of these edges into tess.event, and + * violate the invariant that fixable edges are the only right-going + * edge from their associated vertex). + */ + if (CheckForIntersect(tess, regUp)) { + /* WalkDirtyRegions() was called recursively; we're done */ + return; + } + } else { + /* Even though we can't use CheckForIntersect(), the Org vertices + * may violate the dictionary edge ordering. Check and correct this. + */ + CheckForRightSplice(tess, regUp); + } + } + if (eUp.Org == eLo.Org && eUp.Sym.Org == eLo.Sym.Org) { + /* A degenerate loop consisting of only two edges -- delete it. */ + AddWinding(eLo, eUp); + DeleteRegion(tess, regUp); + if (!Mesh.__gl_meshDelete(eUp)) throw new RuntimeException(); + regUp = RegionAbove(regLo); + } + } + } + + + static void ConnectRightVertex(GLUtessellatorImpl tess, ActiveRegion regUp, + GLUhalfEdge eBottomLeft) +/* + * Purpose: connect a "right" vertex vEvent (one where all edges go left) + * to the unprocessed portion of the mesh. Since there are no right-going + * edges, two regions (one above vEvent and one below) are being merged + * into one. "regUp" is the upper of these two regions. + * + * There are two reasons for doing this (adding a right-going edge): + * - if the two regions being merged are "inside", we must add an edge + * to keep them separated (the combined region would not be monotone). + * - in any case, we must leave some record of vEvent in the dictionary, + * so that we can merge vEvent with features that we have not seen yet. + * For example, maybe there is a vertical edge which passes just to + * the right of vEvent; we would like to splice vEvent into this edge. + * + * However, we don't want to connect vEvent to just any vertex. We don''t + * want the new edge to cross any other edges; otherwise we will create + * intersection vertices even when the input data had no self-intersections. + * (This is a bad thing; if the user's input data has no intersections, + * we don't want to generate any false intersections ourselves.) + * + * Our eventual goal is to connect vEvent to the leftmost unprocessed + * vertex of the combined region (the union of regUp and regLo). + * But because of unseen vertices with all right-going edges, and also + * new vertices which may be created by edge intersections, we don''t + * know where that leftmost unprocessed vertex is. In the meantime, we + * connect vEvent to the closest vertex of either chain, and mark the region + * as "fixUpperEdge". This flag says to delete and reconnect this edge + * to the next processed vertex on the boundary of the combined region. + * Quite possibly the vertex we connected to will turn out to be the + * closest one, in which case we won''t need to make any changes. + */ { + GLUhalfEdge eNew; + GLUhalfEdge eTopLeft = eBottomLeft.Onext; + ActiveRegion regLo = RegionBelow(regUp); + GLUhalfEdge eUp = regUp.eUp; + GLUhalfEdge eLo = regLo.eUp; + boolean degenerate = false; + + if (eUp.Sym.Org != eLo.Sym.Org) { + CheckForIntersect(tess, regUp); + } + + /* Possible new degeneracies: upper or lower edge of regUp may pass + * through vEvent, or may coincide with new intersection vertex + */ + if (Geom.VertEq(eUp.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eTopLeft.Sym.Lnext, eUp)) throw new RuntimeException(); + regUp = TopLeftRegion(regUp); + if (regUp == null) throw new RuntimeException(); + eTopLeft = RegionBelow(regUp).eUp; + FinishLeftRegions(tess, RegionBelow(regUp), regLo); + degenerate = true; + } + if (Geom.VertEq(eLo.Org, tess.event)) { + if (!Mesh.__gl_meshSplice(eBottomLeft, eLo.Sym.Lnext)) throw new RuntimeException(); + eBottomLeft = FinishLeftRegions(tess, regLo, null); + degenerate = true; + } + if (degenerate) { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + return; + } + + /* Non-degenerate situation -- need to add a temporary, fixable edge. + * Connect to the closer of eLo.Org, eUp.Org. + */ + if (Geom.VertLeq(eLo.Org, eUp.Org)) { + eNew = eLo.Sym.Lnext; + } else { + eNew = eUp; + } + eNew = Mesh.__gl_meshConnect(eBottomLeft.Onext.Sym, eNew); + if (eNew == null) throw new RuntimeException(); + + /* Prevent cleanup, otherwise eNew might disappear before we've even + * had a chance to mark it as a temporary edge. + */ + AddRightEdges(tess, regUp, eNew, eNew.Onext, eNew.Onext, false); + eNew.Sym.activeRegion.fixUpperEdge = true; + WalkDirtyRegions(tess, regUp); + } + +/* Because vertices at exactly the same location are merged together + * before we process the sweep event, some degenerate cases can't occur. + * However if someone eventually makes the modifications required to + * merge features which are close together, the cases below marked + * TOLERANCE_NONZERO will be useful. They were debugged before the + * code to merge identical vertices in the main loop was added. + */ + private static final boolean TOLERANCE_NONZERO = false; + + static void ConnectLeftDegenerate(GLUtessellatorImpl tess, + ActiveRegion regUp, GLUvertex vEvent) +/* + * The event vertex lies exacty on an already-processed edge or vertex. + * Adding the new vertex involves splicing it into the already-processed + * part of the mesh. + */ { + GLUhalfEdge e, eTopLeft, eTopRight, eLast; + ActiveRegion reg; + + e = regUp.eUp; + if (Geom.VertEq(e.Org, vEvent)) { + /* e.Org is an unprocessed vertex - just combine them, and wait + * for e.Org to be pulled from the queue + */ + assert (TOLERANCE_NONZERO); + SpliceMergeVertices(tess, e, vEvent.anEdge); + return; + } + + if (!Geom.VertEq(e.Sym.Org, vEvent)) { + /* General case -- splice vEvent into edge e which passes through it */ + if (Mesh.__gl_meshSplitEdge(e.Sym) == null) throw new RuntimeException(); + if (regUp.fixUpperEdge) { + /* This edge was fixable -- delete unused portion of original edge */ + if (!Mesh.__gl_meshDelete(e.Onext)) throw new RuntimeException(); + regUp.fixUpperEdge = false; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, e)) throw new RuntimeException(); + SweepEvent(tess, vEvent); /* recurse */ + return; + } + + /* vEvent coincides with e.Sym.Org, which has already been processed. + * Splice in the additional right-going edges. + */ + assert (TOLERANCE_NONZERO); + regUp = TopRightRegion(regUp); + reg = RegionBelow(regUp); + eTopRight = reg.eUp.Sym; + eTopLeft = eLast = eTopRight.Onext; + if (reg.fixUpperEdge) { + /* Here e.Sym.Org has only a single fixable edge going right. + * We can delete it since now we have some real right-going edges. + */ + assert (eTopLeft != eTopRight); /* there are some left edges too */ + DeleteRegion(tess, reg); + if (!Mesh.__gl_meshDelete(eTopRight)) throw new RuntimeException(); + eTopRight = eTopLeft.Sym.Lnext; + } + if (!Mesh.__gl_meshSplice(vEvent.anEdge, eTopRight)) throw new RuntimeException(); + if (!Geom.EdgeGoesLeft(eTopLeft)) { + /* e.Sym.Org had no left-going edges -- indicate this to AddRightEdges() */ + eTopLeft = null; + } + AddRightEdges(tess, regUp, eTopRight.Onext, eLast, eTopLeft, true); + } + + + static void ConnectLeftVertex(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Purpose: connect a "left" vertex (one where both edges go right) + * to the processed portion of the mesh. Let R be the active region + * containing vEvent, and let U and L be the upper and lower edge + * chains of R. There are two possibilities: + * + * - the normal case: split R into two regions, by connecting vEvent to + * the rightmost vertex of U or L lying to the left of the sweep line + * + * - the degenerate case: if vEvent is close enough to U or L, we + * merge vEvent into that edge chain. The subcases are: + * - merging with the rightmost vertex of U or L + * - merging with the active edge of U or L + * - merging with an already-processed portion of U or L + */ { + ActiveRegion regUp, regLo, reg; + GLUhalfEdge eUp, eLo, eNew; + ActiveRegion tmp = new ActiveRegion(); + + /* assert ( vEvent.anEdge.Onext.Onext == vEvent.anEdge ); */ + + /* Get a pointer to the active region containing vEvent */ + tmp.eUp = vEvent.anEdge.Sym; + /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */ + regUp = (ActiveRegion) Dict.dictKey(Dict.dictSearch(tess.dict, tmp)); + regLo = RegionBelow(regUp); + eUp = regUp.eUp; + eLo = regLo.eUp; + + /* Try merging with U or L first */ + if (Geom.EdgeSign(eUp.Sym.Org, vEvent, eUp.Org) == 0) { + ConnectLeftDegenerate(tess, regUp, vEvent); + return; + } + + /* Connect vEvent to rightmost processed vertex of either chain. + * e.Sym.Org is the vertex that we will connect to vEvent. + */ + reg = Geom.VertLeq(eLo.Sym.Org, eUp.Sym.Org) ? regUp : regLo; + + if (regUp.inside || reg.fixUpperEdge) { + if (reg == regUp) { + eNew = Mesh.__gl_meshConnect(vEvent.anEdge.Sym, eUp.Lnext); + if (eNew == null) throw new RuntimeException(); + } else { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(eLo.Sym.Onext.Sym, vEvent.anEdge); + if (tempHalfEdge == null) throw new RuntimeException(); + + eNew = tempHalfEdge.Sym; + } + if (reg.fixUpperEdge) { + if (!FixUpperEdge(reg, eNew)) throw new RuntimeException(); + } else { + ComputeWinding(tess, AddRegionBelow(tess, regUp, eNew)); + } + SweepEvent(tess, vEvent); + } else { + /* The new vertex is in a region which does not belong to the polygon. + * We don''t need to connect this vertex to the rest of the mesh. + */ + AddRightEdges(tess, regUp, vEvent.anEdge, vEvent.anEdge, null, true); + } + } + + + static void SweepEvent(GLUtessellatorImpl tess, GLUvertex vEvent) +/* + * Does everything necessary when the sweep line crosses a vertex. + * Updates the mesh and the edge dictionary. + */ { + ActiveRegion regUp, reg; + GLUhalfEdge e, eTopLeft, eBottomLeft; + + tess.event = vEvent; /* for access in EdgeLeq() */ + DebugEvent(tess); + + /* Check if this vertex is the right endpoint of an edge that is + * already in the dictionary. In this case we don't need to waste + * time searching for the location to insert new edges. + */ + e = vEvent.anEdge; + while (e.activeRegion == null) { + e = e.Onext; + if (e == vEvent.anEdge) { + /* All edges go right -- not incident to any processed edges */ + ConnectLeftVertex(tess, vEvent); + return; + } + } + + /* Processing consists of two phases: first we "finish" all the + * active regions where both the upper and lower edges terminate + * at vEvent (ie. vEvent is closing off these regions). + * We mark these faces "inside" or "outside" the polygon according + * to their winding number, and delete the edges from the dictionary. + * This takes care of all the left-going edges from vEvent. + */ + regUp = TopLeftRegion(e.activeRegion); + if (regUp == null) throw new RuntimeException(); + reg = RegionBelow(regUp); + eTopLeft = reg.eUp; + eBottomLeft = FinishLeftRegions(tess, reg, null); + + /* Next we process all the right-going edges from vEvent. This + * involves adding the edges to the dictionary, and creating the + * associated "active regions" which record information about the + * regions between adjacent dictionary edges. + */ + if (eBottomLeft.Onext == eTopLeft) { + /* No right-going edges -- add a temporary "fixable" edge */ + ConnectRightVertex(tess, regUp, eBottomLeft); + } else { + AddRightEdges(tess, regUp, eBottomLeft.Onext, eTopLeft, eTopLeft, true); + } + } + + +/* Make the sentinel coordinates big enough that they will never be + * merged with real input features. (Even with the largest possible + * input contour and the maximum tolerance of 1.0, no merging will be + * done with coordinates larger than 3 * GLU_TESS_MAX_COORD). + */ + private static final double SENTINEL_COORD = (4.0 * GLU.GLU_TESS_MAX_COORD); + + static void AddSentinel(GLUtessellatorImpl tess, double t) +/* + * We add two sentinel edges above and below all other edges, + * to avoid special cases at the top and bottom. + */ { + GLUhalfEdge e; + ActiveRegion reg = new ActiveRegion(); + if (reg == null) throw new RuntimeException(); + + e = Mesh.__gl_meshMakeEdge(tess.mesh); + if (e == null) throw new RuntimeException(); + + e.Org.s = SENTINEL_COORD; + e.Org.t = t; + e.Sym.Org.s = -SENTINEL_COORD; + e.Sym.Org.t = t; + tess.event = e.Sym.Org; /* initialize it */ + + reg.eUp = e; + reg.windingNumber = 0; + reg.inside = false; + reg.fixUpperEdge = false; + reg.sentinel = true; + reg.dirty = false; + reg.nodeUp = Dict.dictInsert(tess.dict, reg); /* __gl_dictListInsertBefore */ + if (reg.nodeUp == null) throw new RuntimeException(); + } + + + static void InitEdgeDict(final GLUtessellatorImpl tess) +/* + * We maintain an ordering of edge intersections with the sweep line. + * This order is maintained in a dynamic dictionary. + */ { + /* __gl_dictListNewDict */ + tess.dict = Dict.dictNewDict(tess, new Dict.DictLeq() { + public boolean leq(Object frame, Object key1, Object key2) { + return EdgeLeq(tess, (ActiveRegion) key1, (ActiveRegion) key2); + } + }); + if (tess.dict == null) throw new RuntimeException(); + + AddSentinel(tess, -SENTINEL_COORD); + AddSentinel(tess, SENTINEL_COORD); + } + + + static void DoneEdgeDict(GLUtessellatorImpl tess) { + ActiveRegion reg; + int fixedEdges = 0; + + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + while ((reg = (ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))) != null) { + /* + * At the end of all processing, the dictionary should contain + * only the two sentinel edges, plus at most one "fixable" edge + * created by ConnectRightVertex(). + */ + if (!reg.sentinel) { + assert (reg.fixUpperEdge); + assert (++fixedEdges == 1); + } + assert (reg.windingNumber == 0); + DeleteRegion(tess, reg); +/* __gl_meshDelete( reg.eUp );*/ + } + Dict.dictDeleteDict(tess.dict); /* __gl_dictListDeleteDict */ + } + + + static void RemoveDegenerateEdges(GLUtessellatorImpl tess) +/* + * Remove zero-length edges, and contours with fewer than 3 vertices. + */ { + GLUhalfEdge e, eNext, eLnext; + GLUhalfEdge eHead = tess.mesh.eHead; + + /*LINTED*/ + for (e = eHead.next; e != eHead; e = eNext) { + eNext = e.next; + eLnext = e.Lnext; + + if (Geom.VertEq(e.Org, e.Sym.Org) && e.Lnext.Lnext != e) { + /* Zero-length edge, contour has at least 3 edges */ + + SpliceMergeVertices(tess, eLnext, e); /* deletes e.Org */ + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); /* e is a self-loop */ + e = eLnext; + eLnext = e.Lnext; + } + if (eLnext.Lnext == e) { + /* Degenerate contour (one or two edges) */ + + if (eLnext != e) { + if (eLnext == eNext || eLnext == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(eLnext)) throw new RuntimeException(); + } + if (e == eNext || e == eNext.Sym) { + eNext = eNext.next; + } + if (!Mesh.__gl_meshDelete(e)) throw new RuntimeException(); + } + } + } + + static boolean InitPriorityQ(GLUtessellatorImpl tess) +/* + * Insert all vertices into the priority queue which determines the + * order in which vertices cross the sweep line. + */ { + PriorityQ pq; + GLUvertex v, vHead; + + /* __gl_pqSortNewPriorityQ */ + pq = tess.pq = PriorityQ.pqNewPriorityQ(new PriorityQ.Leq() { + public boolean leq(Object key1, Object key2) { + return Geom.VertLeq(((GLUvertex) key1), (GLUvertex) key2); + } + }); + if (pq == null) return false; + + vHead = tess.mesh.vHead; + for (v = vHead.next; v != vHead; v = v.next) { + v.pqHandle = pq.pqInsert(v); /* __gl_pqSortInsert */ + if (v.pqHandle == Long.MAX_VALUE) break; + } + if (v != vHead || !pq.pqInit()) { /* __gl_pqSortInit */ + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + tess.pq = null; + return false; + } + + return true; + } + + + static void DonePriorityQ(GLUtessellatorImpl tess) { + tess.pq.pqDeletePriorityQ(); /* __gl_pqSortDeletePriorityQ */ + } + + + static boolean RemoveDegenerateFaces(GLUmesh mesh) +/* + * Delete any degenerate faces with only two edges. WalkDirtyRegions() + * will catch almost all of these, but it won't catch degenerate faces + * produced by splice operations on already-processed edges. + * The two places this can happen are in FinishLeftRegions(), when + * we splice in a "temporary" edge produced by ConnectRightVertex(), + * and in CheckForLeftSplice(), where we splice already-processed + * edges to ensure that our dictionary invariants are not violated + * by numerical errors. + * + * In both these cases it is *very* dangerous to delete the offending + * edge at the time, since one of the routines further up the stack + * will sometimes be keeping a pointer to that edge. + */ { + GLUface f, fNext; + GLUhalfEdge e; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { + fNext = f.next; + e = f.anEdge; + assert (e.Lnext != e); + + if (e.Lnext.Lnext == e) { + /* A face with only two edges */ + AddWinding(e.Onext, e); + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + return true; + } + + public static boolean __gl_computeInterior(GLUtessellatorImpl tess) +/* + * __gl_computeInterior( tess ) computes the planar arrangement specified + * by the given contours, and further subdivides this arrangement + * into regions. Each region is marked "inside" if it belongs + * to the polygon, according to the rule given by tess.windingRule. + * Each interior region is guaranteed be monotone. + */ { + GLUvertex v, vNext; + + tess.fatalError = false; + + /* Each vertex defines an event for our sweep line. Start by inserting + * all the vertices in a priority queue. Events are processed in + * lexicographic order, ie. + * + * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y) + */ + RemoveDegenerateEdges(tess); + if (!InitPriorityQ(tess)) return false; /* if error */ + InitEdgeDict(tess); + + /* __gl_pqSortExtractMin */ + while ((v = (GLUvertex) tess.pq.pqExtractMin()) != null) { + for (; ;) { + vNext = (GLUvertex) tess.pq.pqMinimum(); /* __gl_pqSortMinimum */ + if (vNext == null || !Geom.VertEq(vNext, v)) break; + + /* Merge together all vertices at exactly the same location. + * This is more efficient than processing them one at a time, + * simplifies the code (see ConnectLeftDegenerate), and is also + * important for correct handling of certain degenerate cases. + * For example, suppose there are two identical edges A and B + * that belong to different contours (so without this code they would + * be processed by separate sweep events). Suppose another edge C + * crosses A and B from above. When A is processed, we split it + * at its intersection point with C. However this also splits C, + * so when we insert B we may compute a slightly different + * intersection point. This might leave two edges with a small + * gap between them. This kind of error is especially obvious + * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY). + */ + vNext = (GLUvertex) tess.pq.pqExtractMin(); /* __gl_pqSortExtractMin*/ + SpliceMergeVertices(tess, v.anEdge, vNext.anEdge); + } + SweepEvent(tess, v); + } + + /* Set tess.event for debugging purposes */ + /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */ + tess.event = ((ActiveRegion) Dict.dictKey(Dict.dictMin(tess.dict))).eUp.Org; + DebugEvent(tess); + DoneEdgeDict(tess); + DonePriorityQ(tess); + + if (!RemoveDegenerateFaces(tess.mesh)) return false; + Mesh.__gl_meshCheckMesh(tess.mesh); + + return true; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java new file mode 100644 index 000000000..ef89b1613 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessMono.java @@ -0,0 +1,241 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class TessMono { +/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region + * (what else would it do??) The region must consist of a single + * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this + * case means that any vertical line intersects the interior of the + * region in a single interval. + * + * Tessellation consists of adding interior edges (actually pairs of + * half-edges), to split the region into non-overlapping triangles. + * + * The basic idea is explained in Preparata and Shamos (which I don''t + * have handy right now), although their implementation is more + * complicated than this one. The are two edge chains, an upper chain + * and a lower chain. We process all vertices from both chains in order, + * from right to left. + * + * The algorithm ensures that the following invariant holds after each + * vertex is processed: the untessellated region consists of two + * chains, where one chain (say the upper) is a single edge, and + * the other chain is concave. The left vertex of the single edge + * is always to the left of all vertices in the concave chain. + * + * Each step consists of adding the rightmost unprocessed vertex to one + * of the two chains, and forming a fan of triangles from the rightmost + * of two chain endpoints. Determining whether we can add each triangle + * to the fan is a simple orientation test. By making the fan as large + * as possible, we restore the invariant (check it yourself). + */ + static boolean __gl_meshTessellateMonoRegion(GLUface face, boolean avoidDegenerateTris) { + GLUhalfEdge up, lo; + + /* All edges are oriented CCW around the boundary of the region. + * First, find the half-edge whose origin vertex is rightmost. + * Since the sweep goes from left to right, face->anEdge should + * be close to the edge we want. + */ + up = face.anEdge; + assert (up.Lnext != up && up.Lnext.Lnext != up); + + for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym) + ; + for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext) + ; + lo = up.Onext.Sym; + + boolean mustConnect = false; // hack for avoidDegenerateTris + + while (up.Lnext != lo) { + if (avoidDegenerateTris && !mustConnect) { + // Skip over regions where several vertices are collinear, + // to try to avoid producing degenerate (zero-area) triangles + // + // The "mustConnect" flag is a hack to try to avoid + // skipping too large regions and causing incorrect + // triangulations. This entire modification is overall + // not robust and needs more work + if (Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON) { + // Lines around lo + do { + lo = lo.Onext.Sym; + mustConnect = true; + } while (up.Lnext != lo && + Geom.EdgeCos(lo.Lnext.Org, lo.Org, lo.Lnext.Lnext.Org) <= -Geom.ONE_MINUS_EPSILON); + } else if (Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON) { + // Lines around up + do { + up = up.Lnext; + mustConnect = true; + } while (up.Lnext != lo && + Geom.EdgeCos(up.Onext.Sym.Org, up.Org, up.Onext.Sym.Onext.Sym.Org) <= -Geom.ONE_MINUS_EPSILON); + } + + if (up.Lnext == lo) + break; + } + + if (Geom.VertLeq(up.Sym.Org, lo.Org)) { + /* up.Sym.Org is on the left. It is safe to form triangles from lo.Org. + * The EdgeGoesLeft test guarantees progress even when some triangles + * are CW, given that the upper and lower chains are truly monotone. + */ + while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) + || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + mustConnect = false; + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + lo = lo.Onext.Sym; + } else { + /* lo.Org is on the left. We can make CCW triangles from up.Sym.Org. */ + while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) + || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0)) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym); + mustConnect = false; + if (tempHalfEdge == null) return false; + up = tempHalfEdge.Sym; + } + up = up.Lnext; + } + } + + /* Now lo.Org == up.Sym.Org == the leftmost vertex. The remaining region + * can be tessellated in a fan from this leftmost vertex. + */ + assert (lo.Lnext != up); + while (lo.Lnext.Lnext != up) { + GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo); + if (tempHalfEdge == null) return false; + lo = tempHalfEdge.Sym; + } + + return true; + } + + +/* __gl_meshTessellateInterior( mesh ) tessellates each region of + * the mesh which is marked "inside" the polygon. Each such region + * must be monotone. + */ + public static boolean __gl_meshTessellateInterior(GLUmesh mesh, boolean avoidDegenerateTris) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Make sure we don''t try to tessellate the new triangles. */ + next = f.next; + if (f.inside) { + if (!__gl_meshTessellateMonoRegion(f, avoidDegenerateTris)) return false; + } + } + + return true; + } + + +/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces + * which are not marked "inside" the polygon. Since further mesh operations + * on NULL faces are not allowed, the main purpose is to clean up the + * mesh so that exterior loops are not represented in the data structure. + */ + public static void __gl_meshDiscardExterior(GLUmesh mesh) { + GLUface f, next; + + /*LINTED*/ + for (f = mesh.fHead.next; f != mesh.fHead; f = next) { + /* Since f will be destroyed, save its next pointer. */ + next = f.next; + if (!f.inside) { + Mesh.__gl_meshZapFace(f); + } + } + } + + private static final int MARKED_FOR_DELETION = 0x7fffffff; + +/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the + * winding numbers on all edges so that regions marked "inside" the + * polygon have a winding number of "value", and regions outside + * have a winding number of 0. + * + * If keepOnlyBoundary is TRUE, it also deletes all edges which do not + * separate an interior region from an exterior one. + */ + public static boolean __gl_meshSetWindingNumber(GLUmesh mesh, int value, boolean keepOnlyBoundary) { + GLUhalfEdge e, eNext; + + for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { + eNext = e.next; + if (e.Sym.Lface.inside != e.Lface.inside) { + + /* This is a boundary edge (one side is interior, one is exterior). */ + e.winding = (e.Lface.inside) ? value : -value; + } else { + + /* Both regions are interior, or both are exterior. */ + if (!keepOnlyBoundary) { + e.winding = 0; + } else { + if (!Mesh.__gl_meshDelete(e)) return false; + } + } + } + return true; + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java new file mode 100644 index 000000000..a8aa41d9f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/glu/tessellator/TessState.java @@ -0,0 +1,59 @@ +/* +* Portions Copyright (C) 2003-2006 Sun Microsystems, Inc. +* All rights reserved. +*/ + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 2.0 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** NOTE: The Original Code (as defined below) has been licensed to Sun +** Microsystems, Inc. ("Sun") under the SGI Free Software License B +** (Version 1.1), shown above ("SGI License"). Pursuant to Section +** 3.2(3) of the SGI License, Sun is distributing the Covered Code to +** you under an alternative license ("Alternative License"). This +** Alternative License includes all of the provisions of the SGI License +** except that Section 2.2 and 11 are omitted. Any differences between +** the Alternative License and the SGI License are offered solely by Sun +** and not by SGI. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: The application programming interfaces +** established by SGI in conjunction with the Original Code are The +** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released +** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version +** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X +** Window System(R) (Version 1.3), released October 19, 1998. This software +** was created using the OpenGL(R) version 1.2.1 Sample Implementation +** published by SGI, but has not been independently verified as being +** compliant with the OpenGL(R) version 1.2.1 Specification. +** +** Author: Eric Veach, July 1994 +** Java Port: Pepijn Van Eeckhoudt, July 2003 +** Java Port: Nathan Parker Burg, August 2003 +*/ +package com.jogamp.opengl.impl.glu.tessellator; + +class TessState { + public static final int T_DORMANT = 0; + public static final int T_IN_POLYGON = 1; + public static final int T_IN_CONTOUR = 2; +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java new file mode 100644 index 000000000..ebefaf466 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLContext.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public abstract class MacOSXCGLContext extends GLContextImpl +{ + protected long nsContext; // NSOpenGLContext + protected long cglContext; // CGLContextObj + private CGLExt cglExt; + // Table that holds the addresses of the native C-language entry points for + // CGL extension functions. + private CGLExtProcAddressTable cglExtProcAddressTable; + + public MacOSXCGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public MacOSXCGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getCGLExt(); + } + + public CGLExt getCGLExt() { + if (cglExt == null) { + cglExt = new CGLExtImpl(this); + } + return cglExt; + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getCGLExtProcAddressTable(); + } + + public final CGLExtProcAddressTable getCGLExtProcAddressTable() { + return cglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return null; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return null; } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + return 0; // FIXME + } + + protected void destroyContextARBImpl(long _context) { + // FIXME + } + + /** + * Creates and initializes an appropriate OpenGl nsContext. Should only be + * called by {@link makeCurrentImpl()}. + */ + protected boolean create(boolean pbuffer, boolean floatingPoint) { + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getNSContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilitiesRequested = (GLCapabilities)config.getRequestedCapabilities(); + GLProfile glProfile = capabilitiesRequested.getGLProfile(); + if(glProfile.isGL3()) { + throw new GLException("GL3 profile currently not supported on MacOSX, due to the lack of a OpenGL 3.1 implementation"); + } + // HACK .. bring in OnScreen/PBuffer selection to the DrawableFactory !! + GLCapabilities capabilities = (GLCapabilities) capabilitiesRequested.clone(); + capabilities.setPBuffer(pbuffer); + capabilities.setPbufferFloatingPointBuffers(floatingPoint); + + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(capabilities); + if (pixelFormat == 0) { + throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); + } + config.setChosenPixelFormat(pixelFormat); + try { + int[] viewNotReady = new int[1]; + // Try to allocate a context with this + nsContext = CGL.createContext(share, + drawable.getNativeWindow().getSurfaceHandle(), + pixelFormat, + viewNotReady, 0); + if (nsContext == 0) { + if (viewNotReady[0] == 1) { + if (DEBUG) { + System.err.println("!!! View not ready for " + getClass().getName()); + } + // View not ready at the window system level -- this is OK + return false; + } + throw new GLException("Error creating NSOpenGLContext with requested pixel format"); + } + + if (!pbuffer && !capabilities.isBackgroundOpaque()) { + // Set the context opacity + CGL.setContextOpacity(nsContext, 0); + } + + GLCapabilities caps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(glProfile, pixelFormat); + config.setChosenCapabilities(caps); + } finally { + CGL.deletePixelFormat(pixelFormat); + } + if (!CGL.makeCurrentContext(nsContext)) { + throw new GLException("Error making nsContext current"); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + GLContextShareSet.contextCreated(this); + return true; + } + + protected int makeCurrentImpl() throws GLException { + if (0 == cglContext && drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if ( 0 == cglContext && 0 == nsContext) { + create(); + created = 0 != cglContext || 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName()); + } + } + + if ( 0 != cglContext ) { + if (CGL.kCGLNoError != CGL.CGLSetCurrentContext(cglContext)) { + throw new GLException("Error making cglContext current"); + } + } else { + if (!CGL.makeCurrentContext(nsContext)) { + throw new GLException("Error making nsContext current"); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if ( 0 != cglContext ) { + CGL.CGLReleaseContext(cglContext); + } else { + if (!CGL.clearCurrentContext(nsContext)) { + throw new GLException("Error freeing OpenGL nsContext"); + } + } + } + + protected void destroyImpl() throws GLException { + boolean hadContext = isCreated(); + if ( 0 != cglContext ) { + if (CGL.kCGLNoError != CGL.CGLDestroyContext(cglContext)) { + throw new GLException("Unable to delete OpenGL cglContext"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL cglContext " + cglContext); + } + cglContext = 0; + GLContextShareSet.contextDestroyed(this); + } else if ( 0 != nsContext ) { + if (!CGL.deleteContext(nsContext)) { + throw new GLException("Unable to delete OpenGL nsContext"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL nsContext " + nsContext); + } + nsContext = 0; + } + if(hadContext) { + GLContextShareSet.contextDestroyed(this); + } + } + + public boolean isCreated() { + return 0 != cglContext || 0 != nsContext ; + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getCGLContext(); + long src = 0; + if( 0 != dst ) { + src = ((MacOSXCGLContext) source).getCGLContext(); + if (src == 0) { + throw new GLException("Source OpenGL cglContext has not been created ; Destination has a cglContext."); + } + CGL.CGLCopyContext(src, dst, mask); + } else { + dst = getNSContext(); + src = ((MacOSXCGLContext) source).getNSContext(); + if (src == 0) { + throw new GLException("Source OpenGL nsContext has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL nsContext has not been created"); + } + CGL.copyContext(dst, src, mask); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println("!!! Initializing CGL extension address table"); + } + if (cglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + cglExtProcAddressTable = new CGLExtProcAddressTable(); + } + resetProcAddressTable(getCGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public String getPlatformExtensionsString() + { + return ""; + } + + protected void setSwapIntervalImpl(int interval) { + if ( 0 != cglContext ) { + int[] lval = new int[] { (int) interval } ; + CGL.CGLSetParameter(cglContext, CGL.kCGLCPSwapInterval, lval, 0); + } else if ( 0 != nsContext ) { + CGL.setSwapInterval(nsContext, interval); + } else { + throw new GLException("OpenGL context not current"); + } + currentSwapInterval = interval ; + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + // FIXME: apparently the Apple extension doesn't require a custom memory allocator + throw new GLException("Not yet implemented"); + } + + public boolean isFunctionAvailable(String glFunctionName) + { + return super.isFunctionAvailable(glFunctionName); + } + + public boolean isExtensionAvailable(String glExtensionName) { + if (glExtensionName.equals("GL_ARB_pbuffer") || + glExtensionName.equals("GL_ARB_pixel_format")) { + return true; + } + return super.isExtensionAvailable(glExtensionName); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + // Support for "mode switching" as described in MacOSXCGLDrawable + public abstract void setOpenGLMode(int mode); + public abstract int getOpenGLMode(); + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getCGLContext() { + return cglContext; + } + public long getNSContext() { + return nsContext; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java new file mode 100644 index 000000000..cf29d214b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawable.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.os.DynamicLookupHelper; + +public abstract class MacOSXCGLDrawable extends GLDrawableImpl { + // The Java2D/OpenGL pipeline on OS X uses low-level CGLContextObjs + // to represent the contexts for e.g. the Java2D back buffer. When + // the Java2D/JOGL bridge is active, this means that if we want to + // be able to share textures and display lists with the Java2D + // contexts, we need to use the CGL APIs rather than the NSOpenGL + // APIs on the JOGL side. For example, if we create a pbuffer using + // the NSOpenGL APIs and want to share textures and display lists + // between it and the Java2D back buffer, there is no way to do so, + // because the Java2D context is actually a CGLContextObj and the + // NSOpenGLContext's initWithFormat:shareContext: only accepts an + // NSOpenGLContext as its second argument. Of course there is no way + // to wrap an NSOpenGLContext around an arbitrary CGLContextObj. + // + // The situation we care most about is allowing a GLPbuffer to share + // textures, etc. with a GLJPanel when the Java2D/JOGL bridge is + // active; several of the demos rely on this functionality. We aim + // to get there by allowing a GLPBuffer to switch its implementation + // between using an NSOpenGLPixelBuffer and a CGLPBufferObj. In + // order to track whether this has been done we need to have the + // notion of a "mode" of both the MacOSXCGLDrawable and the + // MacOSXGLContext. Initially the mode is "unspecified", meaning it + // leans toward the default (NSOpenGL). If sharing is requested + // between either a GLJPanel and a GLPbuffer or a GLCanvas and a + // GLPbuffer, the GLPbuffer will be switched into the appropriate + // mode: CGL mode for a GLJPanel and NSOpenGL mode for a GLCanvas. + // To avoid thrashing we support exactly one such switch during the + // lifetime of a given GLPbuffer. This is not a fully general + // solution (for example, you can't share textures among a + // GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should + // be enough to get things off the ground. + public static final int NSOPENGL_MODE = 1; + public static final int CGL_MODE = 2; + + public MacOSXCGLDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + protected void setRealizedImpl() { + if(realized) { + if( NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface() ) { + throw new GLException("Couldn't lock surface"); + } + // locking the surface is essential to update surface data + unlockSurface(); + } + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (MacOSXCGLDrawableFactory) getFactoryImpl() ; + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + + // Support for "mode switching" as per above + public abstract void setOpenGLMode(int mode); + public abstract int getOpenGLMode(); +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java new file mode 100644 index 000000000..d10434252 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + public MacOSXCGLDrawableFactory() { + super(); + + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new MacOSXCGLGraphicsConfigurationFactory(); + + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.macosx.cgl.awt.MacOSXAWTCGLGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + } + + protected final GLDrawableImpl getSharedDrawable() { return null; } + protected final GLContextImpl getSharedContext() { return null; } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new MacOSXOnscreenCGLDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + return new MacOSXOffscreenCGLDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + return true; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + /** + * FIXME: Think about this .. + * should not be necessary ? .. + final List returnList = new ArrayList(); + final GLDrawableFactory factory = this; + Runnable r = new Runnable() { + public void run() { + returnList.add(new MacOSXPbufferCGLDrawable(factory, target)); + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLDrawableImpl) returnList.get(0); + */ + return new MacOSXPbufferCGLDrawable(this, target); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(); + NullWindow nw = new NullWindow(MacOSXCGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, screen, true)); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + return MacOSXExternalCGLContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + return false; + } + + public GLDrawable createExternalGLDrawable() { + // FIXME + throw new GLException("Not yet implemented"); + } + + public void loadGLULibrary() { + // Nothing to do; already loaded by native code; not much point in + // making it lazier on this platform + } + + public long dynamicLookupFunction(String glFuncName) { + return CGL.getProcAddress(glFuncName); + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("not supported in non AWT enviroment"); + } + + //------------------------------------------------------ + // Gamma-related functionality + // + + private static final int GAMMA_RAMP_LENGTH = 256; + + /** Returns the length of the computed gamma ramp for this OS and + hardware. Returns 0 if gamma changes are not supported. */ + protected int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected boolean setGammaRamp(float[] ramp) { + return CGL.setGammaRamp(ramp.length, + ramp, 0, + ramp, 0, + ramp, 0); + } + + protected Buffer getGammaRamp() { + return null; + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + CGL.resetGammaRamp(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java new file mode 100644 index 000000000..889d1c333 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; + +public class MacOSXCGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + long pixelformat; + + public MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilities capsChosen, GLCapabilities capsRequested, + long pixelformat) { + super(screen, capsChosen, capsRequested); + this.pixelformat=pixelformat; + } + + public Object clone() { + return super.clone(); + } + + protected void setChosenPixelFormat(long pixelformat) { + this.pixelformat=pixelformat; + } + + protected void setChosenCapabilities(GLCapabilities caps) { + super.setChosenCapabilities(caps); + } + + protected static final int[] cglInternalAttributeToken = new int[] { + CGL.kCGLPFAColorFloat, + CGL.NSOpenGLPFAPixelBuffer, + CGL.NSOpenGLPFADoubleBuffer, + CGL.NSOpenGLPFAStereo, + CGL.NSOpenGLPFAColorSize, + CGL.NSOpenGLPFAAlphaSize, + CGL.NSOpenGLPFADepthSize, + CGL.NSOpenGLPFAAccumSize, + CGL.NSOpenGLPFAStencilSize, + CGL.NSOpenGLPFASampleBuffers, + CGL.NSOpenGLPFASamples }; + + protected static int[] GLCapabilities2AttribList(GLCapabilities caps) { + int[] ivalues = new int[cglInternalAttributeToken.length]; + + for (int idx = 0; idx < cglInternalAttributeToken.length; idx++) { + int attr = cglInternalAttributeToken[idx]; + switch (attr) { + case CGL.kCGLPFAColorFloat: + ivalues[idx] = caps.getPbufferFloatingPointBuffers() ? 1 : 0; + break; + + case CGL.NSOpenGLPFAPixelBuffer: + ivalues[idx] = caps.isPBuffer() ? 1 : 0; + break; + + case CGL.NSOpenGLPFADoubleBuffer: + ivalues[idx] = (caps.getDoubleBuffered() ? 1 : 0); + break; + + case CGL.NSOpenGLPFAStereo: + ivalues[idx] = (caps.getStereo() ? 1 : 0); + break; + + case CGL.NSOpenGLPFAColorSize: + ivalues[idx] = (caps.getRedBits() + caps.getGreenBits() + caps.getBlueBits()); + break; + + case CGL.NSOpenGLPFAAlphaSize: + ivalues[idx] = caps.getAlphaBits(); + break; + + case CGL.NSOpenGLPFADepthSize: + ivalues[idx] = caps.getDepthBits(); + break; + + case CGL.NSOpenGLPFAAccumSize: + ivalues[idx] = (caps.getAccumRedBits() + caps.getAccumGreenBits() + caps.getAccumBlueBits() + caps.getAccumAlphaBits()); + break; + + case CGL.NSOpenGLPFAStencilSize: + ivalues[idx] = caps.getStencilBits(); + break; + + case CGL.NSOpenGLPFASampleBuffers: + ivalues[idx] = caps.getSampleBuffers() ? 1 : 0; + break; + + case CGL.NSOpenGLPFASamples: + ivalues[idx] = caps.getSampleBuffers() ? ivalues[idx] = caps.getNumSamples() : 0; + break; + + default: + break; + } + } + return ivalues; + } + + protected static long GLCapabilities2NSPixelFormat(GLCapabilities caps) { + int[] ivalues = GLCapabilities2AttribList(caps); + return CGL.createPixelFormat(cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } + + protected static GLCapabilities NSPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) { + return PixelFormat2GLCapabilities(glp, pixelFormat, true); + } + + protected static GLCapabilities CGLPixelFormat2GLCapabilities(GLProfile glp, long pixelFormat) { + return PixelFormat2GLCapabilities(glp, pixelFormat, false); + } + + private static GLCapabilities PixelFormat2GLCapabilities(GLProfile glp, long pixelFormat, boolean nsUsage) { + int[] ivalues = new int[cglInternalAttributeToken.length]; + + // On this platform the pixel format is associated with the + // context and not the drawable. However it's a reasonable + // approximation to just store the chosen pixel format up in the + // NativeWindow's AbstractGraphicsConfiguration, + // since the public API doesn't provide for a different GLCapabilities per context. + // Note: These restrictions of the platform's API might be considered as a bug anyways. + + // Figure out what attributes we really got + GLCapabilities caps = new GLCapabilities(glp); + if(nsUsage) { + CGL.queryPixelFormat(pixelFormat, cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } else { + CGL.CGLQueryPixelFormat(pixelFormat, cglInternalAttributeToken, 0, cglInternalAttributeToken.length, ivalues, 0); + } + for (int i = 0; i < cglInternalAttributeToken.length; i++) { + int attr = cglInternalAttributeToken[i]; + switch (attr) { + case CGL.kCGLPFAColorFloat: + caps.setPbufferFloatingPointBuffers(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAPixelBuffer: + caps.setPBuffer(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFADoubleBuffer: + caps.setDoubleBuffered(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAStereo: + caps.setStereo(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFAColorSize: + { + int bitSize = ivalues[i]; + if (bitSize == 32) + bitSize = 24; + bitSize /= 3; + caps.setRedBits(bitSize); + caps.setGreenBits(bitSize); + caps.setBlueBits(bitSize); + } + break; + + case CGL.NSOpenGLPFAAlphaSize: + caps.setAlphaBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFADepthSize: + caps.setDepthBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFAAccumSize: + { + int bitSize = ivalues[i] / 4; + caps.setAccumRedBits(bitSize); + caps.setAccumGreenBits(bitSize); + caps.setAccumBlueBits(bitSize); + caps.setAccumAlphaBits(bitSize); + } + break; + + case CGL.NSOpenGLPFAStencilSize: + caps.setStencilBits(ivalues[i]); + break; + + case CGL.NSOpenGLPFASampleBuffers: + caps.setSampleBuffers(ivalues[i] != 0); + break; + + case CGL.NSOpenGLPFASamples: + caps.setNumSamples(ivalues[i]); + break; + + default: + break; + } + } + + return caps; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..ada5fb1a7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.*; +import com.jogamp.nativewindow.impl.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on OSX platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class MacOSXCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public MacOSXCGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.macosx.MacOSXGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + return chooseGraphicsConfigurationStatic(capabilities, chooser, absScreen, false); + } + + protected static MacOSXCGLGraphicsConfiguration chooseGraphicsConfigurationStatic(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen, boolean usePBuffer) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + + return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilities)capabilities, (GLCapabilities)capabilities, 0); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java new file mode 100644 index 000000000..eba3cf50e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +import javax.media.nativewindow.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class MacOSXExternalCGLContext extends MacOSXCGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private MacOSXExternalCGLContext(Drawable drawable, long cglContext, long nsContext) { + super(drawable, null); + drawable.setExternalCGLContext(this); + this.cglContext = cglContext; + this.nsContext = nsContext; + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static MacOSXExternalCGLContext create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long pixelFormat = 0; + long currentDrawable = 0; + long cglContext = 0; + long nsContext = CGL.getCurrentContext(); // Check: MacOSX 10.3 .. + if( 0 != nsContext ) { + currentDrawable = CGL.getNSView(nsContext); + long ctx = CGL.getCGLContext(nsContext); + if (ctx == 0) { + throw new GLException("Error: NULL cglContext of nsContext 0x" +Long.toHexString(nsContext)); + } + pixelFormat = CGL.CGLGetPixelFormat(ctx); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create nsContext 0x"+Long.toHexString(nsContext)+ + ", cglContext 0x"+Long.toHexString(ctx)+ + ", pixelFormat 0x"+Long.toHexString(pixelFormat)); + } + } else { + cglContext = CGL.CGLGetCurrentContext(); + if (cglContext == 0) { + throw new GLException("Error: current cglContext null, no nsContext"); + } + pixelFormat = CGL.CGLGetPixelFormat(cglContext); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create cglContext 0x"+Long.toHexString(cglContext)+ + ", pixelFormat 0x"+Long.toHexString(pixelFormat)); + } + } + + if (0 == pixelFormat) { + throw new GLException("Error: current pixelformat of current cglContext 0x"+Long.toHexString(cglContext)+" is null"); + } + GLCapabilities caps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(glp, pixelFormat); + if(DEBUG) { + System.err.println("MacOSXExternalCGLContext Create "+caps); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps, pixelFormat); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(currentDrawable); + return new MacOSXExternalCGLContext(new Drawable(factory, nw), cglContext, nsContext); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + protected void create() { + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + protected void swapBuffers() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities)config.getChosenCapabilities(); + if(caps.isOnscreen()) { + if (CGL.kCGLNoError != CGL.CGLFlushDrawable(cglContext)) { + throw new GLException("Error swapping buffers"); + } + } + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.CGL_MODE) + throw new GLException("OpenGL mode switching not supported for external GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.CGL_MODE; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends MacOSXCGLDrawable { + MacOSXExternalCGLContext extCtx; + + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + void setExternalCGLContext(MacOSXExternalCGLContext externalContext) { + extCtx = externalContext; + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + + protected void swapBuffersImpl() { + if (extCtx != null) { + extCtx.swapBuffers(); + } + } + + public void setOpenGLMode(int mode) { + if (mode != CGL_MODE) + throw new GLException("OpenGL mode switching not supported for external GLContext's drawables"); + } + + public int getOpenGLMode() { + return CGL_MODE; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java new file mode 100644 index 000000000..89e293665 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLContext.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext +{ + public MacOSXOffscreenCGLContext(MacOSXPbufferCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public int getOffscreenContextPixelDataType() { + GL gl = getGL(); + return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; + } + + public int getOffscreenContextReadBuffer() { + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + return true; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java new file mode 100644 index 000000000..adaa48f34 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOffscreenCGLDrawable.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOffscreenCGLDrawable extends MacOSXPbufferCGLDrawable { + + public MacOSXOffscreenCGLDrawable(GLDrawableFactory factory, + NativeWindow target) { + super(factory, target); + } + + public GLContext createContext(GLContext shareWith) { + return new MacOSXOffscreenCGLContext(this, shareWith); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java new file mode 100644 index 000000000..c4eaee489 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLContext.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOnscreenCGLContext extends MacOSXCGLContext { + protected MacOSXOnscreenCGLDrawable drawable; + + public MacOSXOnscreenCGLContext(MacOSXOnscreenCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + int ret = super.makeCurrentImpl(); + if ((ret == CONTEXT_CURRENT) || + (ret == CONTEXT_CURRENT_NEW)) { + // Assume the canvas might have been resized or moved and tell the OpenGL + // context to update itself. This used to be done only upon receiving a + // reshape event but that doesn't appear to be sufficient. An experiment + // was also done to add a HierarchyBoundsListener to the GLCanvas and + // do this updating only upon reshape of this component or reshape or movement + // of an ancestor, but this also wasn't sufficient and left garbage on the + // screen in some situations. + CGL.updateContext(nsContext); + } else { + if (!isOptimizable()) { + // This can happen if the window currently is zero-sized, for example. + // Make sure we don't leave the surface locked in this case. + drawable.unlockSurface(); + lockRes = NativeWindow.LOCK_SURFACE_NOT_READY; + } + } + return ret; + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY)) { + drawable.unlockSurface(); + } + } + } + + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + protected void swapBuffers() { + if (!CGL.flushBuffer(nsContext)) { + throw new GLException("Error swapping buffers"); + } + } + + protected void update() throws GLException { + if (nsContext == 0) { + throw new GLException("Context not created"); + } + CGL.updateContext(nsContext); + } + + protected void create() { + create(false, false); + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.NSOPENGL_MODE) + throw new GLException("OpenGL mode switching not supported for on-screen GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.NSOPENGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java new file mode 100644 index 000000000..6ee023867 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXOnscreenCGLDrawable.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import java.lang.ref.WeakReference; +import java.security.*; +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable { + private List/*<WeakReference<GLContext>>*/ createdContexts = + new ArrayList(); + + protected MacOSXOnscreenCGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + MacOSXOnscreenCGLContext context = + new MacOSXOnscreenCGLContext(this, shareWith); + // NOTE: we need to keep track of the created contexts in order to + // implement swapBuffers() because of how Mac OS X implements its + // OpenGL window interface + synchronized (this) { + List newContexts = new ArrayList(); + newContexts.addAll(createdContexts); + newContexts.add(new WeakReference(context)); + createdContexts = newContexts; + } + return context; + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + + protected void swapBuffersImpl() { + for (Iterator iter = createdContexts.iterator(); iter.hasNext(); ) { + WeakReference ref = (WeakReference) iter.next(); + MacOSXOnscreenCGLContext ctx = (MacOSXOnscreenCGLContext) ref.get(); + // FIXME: clear out unreachable contexts + if (ctx != null) { + ctx.swapBuffers(); + } + } + } + + public void setOpenGLMode(int mode) { + if (mode != NSOPENGL_MODE) + throw new GLException("OpenGL mode switching not supported for on-screen GLDrawables"); + } + + public int getOpenGLMode() { + return NSOPENGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java new file mode 100644 index 000000000..52a892b70 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -0,0 +1,359 @@ +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.nio.PointerBuffer; +import java.security.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXPbufferCGLContext extends MacOSXCGLContext { + protected MacOSXPbufferCGLDrawable drawable; + + // State for render-to-texture and render-to-texture-rectangle support + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + private static boolean isTigerOrLater; + + static { + String osVersion = Debug.getProperty("os.version", false, AccessController.getContext()); + StringTokenizer tok = new StringTokenizer(osVersion, ". "); + int major = Integer.parseInt(tok.nextToken()); + int minor = Integer.parseInt(tok.nextToken()); + isTigerOrLater = ((major > 10) || (minor > 3)); + } + + public MacOSXPbufferCGLContext(MacOSXPbufferCGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + initOpenGLImpl(); + } + + public void bindPbufferToTexture() { + GL gl = getGL(); + gl.glBindTexture(textureTarget, texture); + // FIXME: not clear whether this is really necessary, but since + // the API docs seem to imply it is and since it doesn't seem to + // impact performance, leaving it in + CGL.setContextTextureImageToPBuffer(nsContext, drawable.getPbuffer(), GL.GL_FRONT); + } + + public void releasePbufferFromTexture() { + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getPbuffer() == 0) { + if (DEBUG) { + System.err.println("Pbuffer not instantiated yet for " + this); + } + // pbuffer not instantiated yet + return CONTEXT_NOT_CURRENT; + } + + if (getOpenGLMode() != drawable.getOpenGLMode()) { + setOpenGLMode(drawable.getOpenGLMode()); + } + + boolean created = false; + if (nsContext == 0) { + create(); + created = 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created OpenGL context " + toHexString(nsContext) + " for " + getClass().getName()); + } + } + + if (!impl.makeCurrent(nsContext)) { + throw new GLException("Error making nsContext current"); + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + // Initialize render-to-texture support if requested + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + GL gl = getGL(); + boolean rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); + if (rect) { + if (!gl.isExtensionAvailable("GL_EXT_texture_rectangle")) { + System.err.println("MacOSXPbufferCGLContext: WARNING: GL_EXT_texture_rectangle extension not " + + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); + rect = false; + } + } + textureTarget = (rect ? GL2.GL_TEXTURE_RECTANGLE : GL.GL_TEXTURE_2D); + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + texture = tmp[0]; + gl.glBindTexture(textureTarget, texture); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if (!impl.release(nsContext)) { + throw new GLException("Error releasing OpenGL nsContext"); + } + } + + protected void destroyImpl() throws GLException { + if (nsContext != 0) { + if (!impl.destroy(nsContext)) { + throw new GLException("Unable to delete OpenGL context"); + } + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + nsContext); + } + nsContext = 0; + GLContextShareSet.contextDestroyed(this); + } + } + + protected void setSwapIntervalImpl(int interval) { + if (nsContext == 0) { + throw new GLException("OpenGL context not current"); + } + impl.setSwapInterval(nsContext, interval); + currentSwapInterval = impl.getSwapInterval() ; + } + + public int getFloatingPointMode() { + return GLPbuffer.APPLE_FLOAT; + } + + protected void create() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers() && + !isTigerOrLater) { + throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later"); + } + // Change our OpenGL mode to match that of any share context before we create ourselves + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + if (other != null) { + setOpenGLMode(other.getOpenGLMode()); + } + // Will throw exception upon error + nsContext = impl.create(); + + if (!impl.makeCurrent(nsContext)) { + throw new GLException("Error making nsContext current"); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + } + + //--------------------------------------------------------------------------- + // OpenGL "mode switching" functionality + // + private boolean haveSetOpenGLMode = false; + // FIXME: should consider switching the default mode based on + // whether the Java2D/JOGL bridge is active -- need to ask ourselves + // whether it's more likely that we will share with a GLCanvas or a + // GLJPanel when the bridge is turned on + private int openGLMode = MacOSXCGLDrawable.NSOPENGL_MODE; + // Implementation object (either NSOpenGL-based or CGL-based) + protected Impl impl; + + public void setOpenGLMode(int mode) { + if (mode == openGLMode) { + return; + } + if (haveSetOpenGLMode) { + throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once"); + } + destroyImpl(); + drawable.setOpenGLMode(mode); + openGLMode = mode; + haveSetOpenGLMode = true; + if (DEBUG) { + System.err.println("Switching PBuffer context mode to " + + ((mode == MacOSXCGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE")); + } + initOpenGLImpl(); + } + + public int getOpenGLMode() { + return openGLMode; + } + + private void initOpenGLImpl() { + switch (openGLMode) { + case MacOSXCGLDrawable.NSOPENGL_MODE: + impl = new NSOpenGLImpl(); + break; + case MacOSXCGLDrawable.CGL_MODE: + impl = new CGLImpl(); + break; + default: + throw new InternalError("Illegal implementation mode " + openGLMode); + } + } + + // Abstract interface for implementation of this context (either + // NSOpenGL-based or CGL-based) + interface Impl { + public long create(); + public boolean destroy(long ctx); + public boolean makeCurrent(long ctx); + public boolean release(long ctx); + public void setSwapInterval(long ctx, int interval); + public int getSwapInterval(); + } + + // NSOpenGLContext-based implementation + class NSOpenGLImpl implements Impl { + public long create() { + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers() && + !isTigerOrLater) { + throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later"); + } + if (!MacOSXPbufferCGLContext.this.create(true, capabilities.getPbufferFloatingPointBuffers())) { + throw new GLException("Error creating context for pbuffer"); + } + // Must now associate the pbuffer with our newly-created context + CGL.setContextPBuffer(nsContext, drawable.getPbuffer()); + return nsContext; + } + + public boolean destroy(long ctx) { + return CGL.deleteContext(ctx); + } + + public boolean makeCurrent(long ctx) { + return CGL.makeCurrentContext(ctx); + } + + public boolean release(long ctx) { + return CGL.clearCurrentContext(ctx); + } + + private int currentSwapInterval = 0 ; + + public void setSwapInterval(long ctx, int interval) { + CGL.setSwapInterval(ctx, interval); + currentSwapInterval = interval ; + } + public int getSwapInterval() { + return currentSwapInterval; + } + } + + class CGLImpl implements Impl { + public long create() { + // Find and configure share context + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(MacOSXPbufferCGLContext.this); + long share = 0; + if (other != null) { + // Reconfigure pbuffer-based GLContexts + if (other instanceof MacOSXPbufferCGLContext) { + MacOSXPbufferCGLContext ctx = (MacOSXPbufferCGLContext) other; + ctx.setOpenGLMode(MacOSXCGLDrawable.CGL_MODE); + } else { + if (other.getOpenGLMode() != MacOSXCGLDrawable.CGL_MODE) { + throw new GLException("Can't share between NSOpenGLContexts and CGLContextObjs"); + } + } + share = other.getNSContext(); + // Note we don't check for a 0 return value, since switching + // the context's mode causes it to be destroyed and not + // re-initialized until the next makeCurrent + } + + // Set up pixel format attributes + // FIXME: shall go into MacOSXCGLGraphicsConfiguration + int[] attrs = new int[256]; + int i = 0; + attrs[i++] = CGL.kCGLPFAPBuffer; + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + if (capabilities.getPbufferFloatingPointBuffers()) + attrs[i++] = CGL.kCGLPFAColorFloat; + if (capabilities.getDoubleBuffered()) + attrs[i++] = CGL.kCGLPFADoubleBuffer; + if (capabilities.getStereo()) + attrs[i++] = CGL.kCGLPFAStereo; + attrs[i++] = CGL.kCGLPFAColorSize; + attrs[i++] = (capabilities.getRedBits() + + capabilities.getGreenBits() + + capabilities.getBlueBits()); + attrs[i++] = CGL.kCGLPFAAlphaSize; + attrs[i++] = capabilities.getAlphaBits(); + attrs[i++] = CGL.kCGLPFADepthSize; + attrs[i++] = capabilities.getDepthBits(); + // FIXME: should validate stencil size as is done in MacOSXWindowSystemInterface.m + attrs[i++] = CGL.kCGLPFAStencilSize; + attrs[i++] = capabilities.getStencilBits(); + attrs[i++] = CGL.kCGLPFAAccumSize; + attrs[i++] = (capabilities.getAccumRedBits() + + capabilities.getAccumGreenBits() + + capabilities.getAccumBlueBits() + + capabilities.getAccumAlphaBits()); + if (capabilities.getSampleBuffers()) { + attrs[i++] = CGL.kCGLPFASampleBuffers; + attrs[i++] = 1; + attrs[i++] = CGL.kCGLPFASamples; + attrs[i++] = capabilities.getNumSamples(); + } + + // Use attribute array to select pixel format + PointerBuffer fmt = PointerBuffer.allocateDirect(1); + long[] numScreens = new long[1]; + int res = CGL.CGLChoosePixelFormat(attrs, 0, fmt, numScreens, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while choosing pixel format"); + } + + // Create new context + PointerBuffer ctx = PointerBuffer.allocateDirect(1); + if (DEBUG) { + System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + } + res = CGL.CGLCreateContext(fmt.get(0), share, ctx); + CGL.CGLDestroyPixelFormat(fmt.get(0)); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while creating context"); + } + // Attach newly-created context to the pbuffer + res = CGL.CGLSetPBuffer(ctx.get(0), drawable.getPbuffer(), 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while attaching context to pbuffer"); + } + return ctx.get(0); + } + + public boolean destroy(long ctx) { + return (CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError); + } + + public boolean makeCurrent(long ctx) { + return CGL.CGLSetCurrentContext(ctx) == CGL.kCGLNoError; + } + + public boolean release(long ctx) { + return (CGL.CGLSetCurrentContext(0) == CGL.kCGLNoError); + } + + public void setSwapInterval(long ctx, int interval) { + // For now not supported (not really relevant for off-screen contexts anyway) + } + public int getSwapInterval() { + return 0; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java new file mode 100644 index 000000000..afdc40dbb --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { + private static final boolean DEBUG = Debug.debug("MacOSXPbufferCGLDrawable"); + + // State for render-to-texture and render-to-texture-rectangle support + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + // NSOpenGLPbuffer (for normal mode) + // CGLPbufferObj (for CGL_MODE situation, i.e., when Java2D/JOGL bridge is active) + // Note that we can not store this in the NativeWindow because the + // semantic is that contains an NSView + protected long pBuffer; + + public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + initOpenGLImpl(); + createPbuffer(); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + createPbuffer(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new MacOSXPbufferCGLContext(this, shareWith); + } + + public void destroy() { + if (this.pBuffer != 0) { + NativeWindow nw = getNativeWindow(); + impl.destroy(pBuffer); + this.pBuffer = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + if (DEBUG) { + System.err.println("Destroyed pbuffer: " + pBuffer); + } + } + } + + public long getPbuffer() { + return pBuffer; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + + private void createPbuffer() { + NativeWindow nw = getNativeWindow(); + DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + GLProfile glProfile = capabilities.getGLProfile(); + int renderTarget; + if (glProfile.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle()) { + renderTarget = GL2.GL_TEXTURE_RECTANGLE; + } else { + int w = getNextPowerOf2(getWidth()); + int h = getNextPowerOf2(getHeight()); + ((SurfaceChangeable)nw).setSize(w, h); + renderTarget = GL.GL_TEXTURE_2D; + } + + int internalFormat = GL.GL_RGBA; + if (capabilities.getPbufferFloatingPointBuffers()) { + // FIXME: want to check availability of GL_APPLE_float_pixels + // extension, but need valid OpenGL context in order to do so -- + // in worst case would need to create dummy window / GLCanvas + // (undesirable) -- could maybe also do this with pbuffers + /* + if (!gl.isExtensionAvailable("GL_APPLE_float_pixels")) { + throw new GLException("Floating-point support (GL_APPLE_float_pixels) not available"); + } + */ + if(glProfile.isGL2GL3()) { + switch (capabilities.getRedBits()) { + case 16: internalFormat = GL2.GL_RGBA_FLOAT16_APPLE; break; + case 32: internalFormat = GL2.GL_RGBA_FLOAT32_APPLE; break; + default: throw new GLException("Invalid floating-point bit depth (only 16 and 32 supported)"); + } + } else { + internalFormat = GL.GL_RGBA; + } + } + + pBuffer = impl.create(renderTarget, internalFormat, getWidth(), getHeight()); + if (pBuffer == 0) { + throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); + } + + ((SurfaceChangeable)nw).setSurfaceHandle(pBuffer); + + } + + private int getNextPowerOf2(int number) { + if (((number-1) & number) == 0) { + //ex: 8 -> 0b1000; 8-1=7 -> 0b0111; 0b1000&0b0111 == 0 + return number; + } + int power = 0; + while (number > 0) { + number = number>>1; + power++; + } + return (1<<power); + } + + //--------------------------------------------------------------------------- + // OpenGL "mode switching" functionality + // + private boolean haveSetOpenGLMode = false; + // FIXME: should consider switching the default mode based on + // whether the Java2D/JOGL bridge is active -- need to ask ourselves + // whether it's more likely that we will share with a GLCanvas or a + // GLJPanel when the bridge is turned on + private int openGLMode = NSOPENGL_MODE; + // Implementation object (either NSOpenGL-based or CGL-based) + protected Impl impl; + + public void setOpenGLMode(int mode) { + if (mode == openGLMode) { + return; + } + if (haveSetOpenGLMode) { + throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once"); + } + destroy(); + openGLMode = mode; + haveSetOpenGLMode = true; + if (DEBUG) { + System.err.println("Switching PBuffer drawable mode to " + + ((mode == MacOSXCGLDrawable.NSOPENGL_MODE) ? "NSOPENGL_MODE" : "CGL_MODE")); + } + initOpenGLImpl(); + createPbuffer(); + } + + public int getOpenGLMode() { + return openGLMode; + } + + private void initOpenGLImpl() { + switch (openGLMode) { + case NSOPENGL_MODE: + impl = new NSOpenGLImpl(); + break; + case CGL_MODE: + impl = new CGLImpl(); + break; + default: + throw new InternalError("Illegal implementation mode " + openGLMode); + } + } + + // Abstract interface for implementation of this drawable (either + // NSOpenGL-based or CGL-based) + interface Impl { + public long create(int renderTarget, int internalFormat, int width, int height); + public void destroy(long pbuffer); + } + + // NSOpenGLPixelBuffer implementation + class NSOpenGLImpl implements Impl { + public long create(int renderTarget, int internalFormat, int width, int height) { + return CGL.createPBuffer(renderTarget, internalFormat, width, height); + } + + public void destroy(long pbuffer) { + CGL.destroyPBuffer(pbuffer); + } + } + + // CGL implementation + class CGLImpl implements Impl { + public long create(int renderTarget, int internalFormat, int width, int height) { + PointerBuffer pbuffer = PointerBuffer.allocateDirect(1); + int res = CGL.CGLCreatePBuffer(width, height, renderTarget, internalFormat, 0, pbuffer); + if (res != CGL.kCGLNoError) { + throw new GLException("Error creating CGL-based pbuffer: error code " + res); + } + return pbuffer.get(0); + } + + public void destroy(long pbuffer) { + int res = CGL.CGLDestroyPBuffer(pbuffer); + if (res != CGL.kCGLNoError) { + throw new GLException("Error destroying CGL-based pbuffer: error code " + res); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java new file mode 100644 index 000000000..eff01ca18 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLDrawableFactory.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import java.lang.reflect.InvocationTargetException; +import java.nio.*; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.awt.*; +import com.jogamp.opengl.impl.macosx.cgl.*; + +public class MacOSXAWTCGLDrawableFactory extends MacOSXCGLDrawableFactory { + + public MacOSXAWTCGLDrawableFactory() { + super(); + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + return true; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + return new MacOSXJava2DCGLContext(shareWith); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..0d59da32e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.macosx.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.macosx.cgl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.macosx.*; + +public class MacOSXAWTCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public MacOSXAWTCGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: got "+absScreen); + } + + long displayHandle = 0; + + MacOSXGraphicsDevice macDevice = new MacOSXGraphicsDevice(); + DefaultGraphicsScreen macScreen = new DefaultGraphicsScreen(macDevice, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("MacOSXAWTCGLGraphicsConfigurationFactory: made "+macScreen); + } + + GraphicsConfiguration gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + MacOSXCGLGraphicsConfiguration macConfig = (MacOSXCGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(macDevice).chooseGraphicsConfiguration(capabilities, + chooser, + macScreen); + + if (macConfig == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+macScreen); + } + + // FIXME: we have nothing to match .. so choose the default + return new AWTGraphicsConfiguration(awtScreen, macConfig.getChosenCapabilities(), macConfig.getRequestedCapabilities(), gc, macConfig); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java new file mode 100644 index 000000000..97a1435bc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXJava2DCGLContext.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.macosx.cgl.awt; + +import com.jogamp.opengl.impl.macosx.cgl.*; + +import java.awt.Graphics; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.awt.*; +import com.jogamp.opengl.impl.macosx.cgl.*; + +/** MacOSXCGLContext implementation supporting the Java2D/JOGL bridge + * on Mac OS X. The external GLDrawable mechanism does not work on Mac + * OS X due to how drawables and contexts are operated upon on this + * platform, so it is necessary to supply an alternative means to + * create, make current, and destroy contexts on the Java2D "drawable" + * on the Mac platform. + */ + +public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGLContext { + private Graphics graphics; + + // FIXME: ignoring context sharing for the time being; will need to + // rethink this in particular if using FBOs to implement the + // Java2D/OpenGL pipeline on Mac OS X + + public MacOSXJava2DCGLContext(GLContext shareWith) { + super(null, shareWith); + } + + public void setGraphics(Graphics g) { + this.graphics = g; + } + + protected int makeCurrentImpl() throws GLException { + boolean created = false; + if (nsContext == 0) { + create(); + created = 0 != nsContext ; + if(!created) { + return CONTEXT_NOT_CURRENT; + } + if (DEBUG) { + System.err.println("!!! Created GL nsContext for " + getClass().getName()); + } + created = true; + } + + if (!Java2D.makeOGLContextCurrentOnSurface(graphics, nsContext)) { + throw new GLException("Error making context current"); + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void create() { + // Find and configure share context + MacOSXCGLContext other = (MacOSXCGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + // Reconfigure pbuffer-based GLContexts + if (other instanceof MacOSXPbufferCGLContext) { + MacOSXPbufferCGLContext ctx = (MacOSXPbufferCGLContext) other; + ctx.setOpenGLMode(MacOSXCGLDrawable.CGL_MODE); + } else { + if (other.getOpenGLMode() != MacOSXCGLDrawable.CGL_MODE) { + throw new GLException("Can't share between NSOpenGLContexts and CGLContextObjs"); + } + } + share = other.getNSContext(); + // Note we don't check for a 0 return value, since switching + // the context's mode causes it to be destroyed and not + // re-initialized until the next makeCurrent + } + + if (DEBUG) { + System.err.println("!!! Share context is " + toHexString(share) + " for " + getClass().getName()); + } + + long ctx = Java2D.createOGLContextOnSurface(graphics, share); + if (ctx == 0) { + return; + } + // FIXME: think about GLContext sharing + nsContext = ctx; + } + + protected void releaseImpl() throws GLException { + // FIXME: would need another primitive in the Java2D class in + // order to implement this; hopefully should not matter for + // correctness + } + + protected void destroyImpl() throws GLException { + if (nsContext != 0) { + Java2D.destroyOGLContext(nsContext); + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + nsContext); + } + nsContext = 0; + // FIXME + // GLContextShareSet.contextDestroyed(this); + } + } + + public void setOpenGLMode(int mode) { + if (mode != MacOSXCGLDrawable.CGL_MODE) + throw new GLException("OpenGL mode switching not supported for Java2D GLContexts"); + } + + public int getOpenGLMode() { + return MacOSXCGLDrawable.CGL_MODE; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java new file mode 100644 index 000000000..87a37da04 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { + private long hwnd, hdc; + + public WindowsDummyWGLDrawable(GLDrawableFactory factory, GLProfile glp) { + super(factory, new NullWindow(WindowsWGLGraphicsConfigurationFactory.createDefaultGraphicsConfiguration(glp, null, true, true)), true); + // All entries to CreateDummyWindow must synchronize on one object + // to avoid accidentally registering the dummy window class twice + synchronized (WindowsDummyWGLDrawable.class) { + hwnd = WGL.CreateDummyWindow(0, 0, 1, 1); + } + hdc = WGL.GetDC(hwnd); + NullWindow nw = (NullWindow) getNativeWindow(); + nw.setSurfaceHandle(hdc); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + // Choose a (hopefully hardware-accelerated) OpenGL pixel format for this device context + GLCapabilities caps = (GLCapabilities) config.getChosenCapabilities(); + caps.setDepthBits(16); + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps); + int pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + if ((pixelFormat == 0) || + (!WGL.SetPixelFormat(hdc, pixelFormat, pfd))) { + destroy(); + } + } + + public void setSize(int width, int height) { + } + + public int getWidth() { + return 1; + } + + public int getHeight() { + return 1; + } + + public GLContext createContext(GLContext shareWith) { + if (hdc == 0) { + // Construction failed + return null; + } + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + return new WindowsWGLContext(this, shareWith); + } + + public void destroy() { + if (hdc != 0) { + WGL.ReleaseDC(hwnd, hdc); + hdc = 0; + } + if (hwnd != 0) { + WGL.ShowWindow(hwnd, WGL.SW_HIDE); + WGL.DestroyWindow(hwnd); + hwnd = 0; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java new file mode 100755 index 000000000..e712d8568 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsExternalWGLContext extends WindowsWGLContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private WindowsExternalWGLContext(Drawable drawable, long hglrc, WindowsWGLGraphicsConfiguration cfg) { + super(drawable, null); + this.context = hglrc; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created external OpenGL context " + toHexString(hglrc) + " for " + this); + } + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + cfg.updateCapabilitiesByWGL(this); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static WindowsExternalWGLContext create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + long hglrc = WGL.wglGetCurrentContext(); + if (hglrc == 0) { + throw new GLException("Error: attempted to make an external GLContext without a context current"); + } + int pfdID = WGL.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat"); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(hdc); + + return new WindowsExternalWGLContext(new Drawable(factory, nw), hglrc, cfg); + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends WindowsWGLDrawable { + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java new file mode 100755 index 000000000..74db45932 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { + + private WindowsExternalWGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, true); + } + + protected static WindowsExternalWGLDrawable create(GLDrawableFactory factory, GLProfile glp) { + long hdc = WGL.wglGetCurrentDC(); + if (0==hdc) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + int pfdID = WGL.GetPixelFormat(hdc); + if (pfdID == 0) { + throw new GLException("Error: attempted to make an external GLContext without a valid pixelformat"); + } + + AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(); + WindowsWGLGraphicsConfiguration cfg = WindowsWGLGraphicsConfiguration.create(hdc, pfdID, glp, aScreen, true, true); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(hdc); + + cfg.updateGraphicsConfiguration(factory, nw); + + return new WindowsExternalWGLDrawable(factory, nw); + } + + + public GLContext createContext(GLContext shareWith) { + return new WindowsWGLContext(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java new file mode 100644 index 000000000..25d93b50e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLContext.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOffscreenWGLContext extends WindowsWGLContext { + public WindowsOffscreenWGLContext(WindowsOffscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public int getOffscreenContextPixelDataType() { + return GL.GL_UNSIGNED_BYTE; + } + + public int getOffscreenContextReadBuffer() { + // On Windows these contexts are always single-buffered + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // We can take care of this in the DIB creation (see below) + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java new file mode 100644 index 000000000..bf466d455 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsOffscreenWGLDrawable extends WindowsWGLDrawable { + private long origbitmap; + private long hbitmap; + + public WindowsOffscreenWGLDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + create(); + } + + protected void setRealizedImpl() { + if(realized) { + create(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOffscreenWGLContext(this, shareWith); + } + + private void create() { + NativeWindow nw = getNativeWindow(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getRequestedCapabilities(); + int width = getWidth(); + int height = getHeight(); + BITMAPINFO info = BITMAPINFO.create(); + BITMAPINFOHEADER header = info.getBmiHeader(); + int bitsPerPixel = (capabilities.getRedBits() + + capabilities.getGreenBits() + + capabilities.getBlueBits() + + capabilities.getAlphaBits()); + header.setBiSize(header.size()); + header.setBiWidth(width); + // NOTE: negating the height causes the DIB to be in top-down row + // order rather than bottom-up; ends up being correct during pixel + // readback + header.setBiHeight(-1 * height); + header.setBiPlanes((short) 1); + header.setBiBitCount((short) bitsPerPixel); + header.setBiXPelsPerMeter(0); + header.setBiYPelsPerMeter(0); + header.setBiClrUsed(0); + header.setBiClrImportant(0); + header.setBiCompression(WGL.BI_RGB); + header.setBiSizeImage(width * height * bitsPerPixel / 8); + + long hdc = WGL.CreateCompatibleDC(0); + if (hdc == 0) { + System.out.println("LastError: " + WGL.GetLastError()); + throw new GLException("Error creating device context for offscreen OpenGL context"); + } + ((SurfaceChangeable)nw).setSurfaceHandle(hdc); + + hbitmap = WGL.CreateDIBSection(hdc, info, WGL.DIB_RGB_COLORS, null, 0, 0); + if (hbitmap == 0) { + WGL.DeleteDC(hdc); + hdc = 0; + throw new GLException("Error creating offscreen bitmap of width " + width + + ", height " + height); + } + if ((origbitmap = WGL.SelectObject(hdc, hbitmap)) == 0) { + WGL.DeleteObject(hbitmap); + hbitmap = 0; + WGL.DeleteDC(hdc); + hdc = 0; + throw new GLException("Error selecting bitmap into new device context"); + } + + config.updateGraphicsConfiguration(getFactory(), nw); + } + + public void destroy() { + NativeWindow nw = getNativeWindow(); + if (nw.getSurfaceHandle() != 0) { + // Must destroy bitmap and device context + WGL.SelectObject(nw.getSurfaceHandle(), origbitmap); + WGL.DeleteObject(hbitmap); + WGL.DeleteDC(nw.getSurfaceHandle()); + origbitmap = 0; + hbitmap = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java new file mode 100644 index 000000000..aeb13110e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLContext.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLContext extends WindowsWGLContext { + protected WindowsOnscreenWGLDrawable drawable; + + public WindowsOnscreenWGLContext(WindowsOnscreenWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + int ret = super.makeCurrentImpl(); + return ret; + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + super.releaseImpl(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java new file mode 100644 index 000000000..401b8c3c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOnscreenWGLDrawable.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsOnscreenWGLDrawable extends WindowsWGLDrawable { + protected WindowsOnscreenWGLDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsOnscreenWGLContext(this, shareWith); + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java new file mode 100644 index 000000000..a9e02e11f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLContext.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsPbufferWGLContext extends WindowsWGLContext { + private static final boolean DEBUG = Debug.debug("WindowsPbufferWGLContext"); + + // State for render-to-texture and render-to-texture-rectangle support + private WindowsPbufferWGLDrawable drawable; + private boolean rtt; // render-to-texture? + private boolean hasRTT; // render-to-texture extension available? + private boolean rect; // render-to-texture-rectangle? + private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV + private int texture; // actual texture object + + public WindowsPbufferWGLContext(WindowsPbufferWGLDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public void bindPbufferToTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + GL gl = getGL(); + WGLExt wglExt = getWGLExt(); + gl.glBindTexture(textureTarget, texture); + if (rtt && hasRTT) { + if (!wglExt.wglBindTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Binding of pbuffer to texture failed: " + wglGetLastError()); + } + } + // FIXME: comment is wrong now + // Note that if the render-to-texture extension is not supported, + // we perform a glCopyTexImage2D in swapBuffers(). + } + + public void releasePbufferFromTexture() { + if (!rtt) { + throw new GLException("Shouldn't try to bind a pbuffer to a texture if render-to-texture hasn't been " + + "specified in its GLCapabilities"); + } + if (rtt && hasRTT) { + WGLExt wglExt = getWGLExt(); + if (!wglExt.wglReleaseTexImageARB(drawable.getPbuffer(), WGLExt.WGL_FRONT_LEFT_ARB)) { + throw new GLException("Releasing of pbuffer from texture failed: " + wglGetLastError()); + } + } + } + + protected int makeCurrentImpl() throws GLException { + int res = super.makeCurrentImpl(); + if (DEBUG && VERBOSE) { + System.err.println("WindowsPbufferWGLContext: super.makeCurrentImpl() = " + res); + } + if (res == CONTEXT_CURRENT_NEW) { + GLCapabilities capabilities = drawable.getChosenGLCapabilities(); + + // Initialize render-to-texture support if requested + GL gl = getGL(); + rtt = capabilities.getPbufferRenderToTexture(); + rect = gl.isGL2GL3() && capabilities.getPbufferRenderToTextureRectangle(); + + if (rtt) { + if (DEBUG) { + System.err.println("Initializing render-to-texture support"); + } + + if (!gl.isExtensionAvailable("WGL_ARB_render_texture")) { + System.err.println("WindowsPbufferWGLContext: WARNING: WGL_ARB_render_texture extension not " + + "supported; implementing render_to_texture support using slow texture readback"); + } else { + hasRTT = true; + + if (rect && !gl.isExtensionAvailable("GL_NV_texture_rectangle")) { + System.err.println("WindowsPbufferWGLContext: WARNING: GL_NV_texture_rectangle extension not " + + "supported; skipping requested render_to_texture_rectangle support for pbuffer"); + rect = false; + } + if (rect) { + if (DEBUG) { + System.err.println(" Using render-to-texture-rectangle"); + } + textureTarget = GL2.GL_TEXTURE_RECTANGLE_ARB; + } else { + if (DEBUG) { + System.err.println(" Using vanilla render-to-texture"); + } + textureTarget = GL.GL_TEXTURE_2D; + } + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + texture = tmp[0]; + gl.glBindTexture(textureTarget, texture); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); + gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); + gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0); + } + } + } + return res; + } + + public int getFloatingPointMode() { + return drawable.getFloatingPointMode(); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java new file mode 100644 index 000000000..c7034e93b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; + +public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { + private long cachedParentHdc; + private WGLExt cachedWGLExt; // cached WGLExt instance from parent GLCanvas, + // needed to destroy pbuffer + private long buffer; // pbuffer handle + + private int floatMode; + + public WindowsPbufferWGLDrawable(GLDrawableFactory factory, NativeWindow target, + WindowsWGLDrawable dummyDrawable, + WGLExt wglExt) { + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + createPbuffer(dummyDrawable.getNativeWindow().getSurfaceHandle(), wglExt); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + throw new GLException("Recreation via setRealized not supported."); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new WindowsPbufferWGLContext(this, shareWith); + } + + public void destroy() { + NativeWindow nw = getNativeWindow(); + if(0!=buffer) { + WGLExt wglExt = cachedWGLExt; + if (nw.getSurfaceHandle() != 0) { + // Must release DC and pbuffer + // NOTE that since the context is not current, glGetError() can + // not be called here, so we skip the use of any composable + // pipelines (see WindowsOnscreenWGLContext.makeCurrentImpl) + if (wglExt.wglReleasePbufferDCARB(buffer, nw.getSurfaceHandle()) == 0) { + throw new GLException("Error releasing pbuffer device context: error code " + WGL.GetLastError()); + } + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } + if (!wglExt.wglDestroyPbufferARB(buffer)) { + throw new GLException("Error destroying pbuffer: error code " + WGL.GetLastError()); + } + buffer = 0; + } + } + + public long getPbuffer() { + return buffer; + } + + public int getFloatingPointMode() { + return floatMode; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } + + private void createPbuffer(long parentHdc, WGLExt wglExt) { + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + int[] floatModeTmp = new int[1]; + int niattribs = 0; + int width, height; + + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities)config.getRequestedCapabilities(); + GLProfile glProfile = capabilities.getGLProfile(); + + if (DEBUG) { + System.out.println("Pbuffer parentHdc = " + toHexString(parentHdc)); + System.out.println("Pbuffer caps: " + capabilities); + } + + if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, + wglExt, + true, + floatModeTmp)){ + throw new GLException("Pbuffer-related extensions not supported"); + } + + floatMode = floatModeTmp[0]; + boolean rtt = capabilities.getPbufferRenderToTexture(); + boolean rect = capabilities.getPbufferRenderToTextureRectangle(); + boolean useFloat = capabilities.getPbufferFloatingPointBuffers(); + boolean ati = false; + + if (useFloat) { + ati = (floatMode == GLPbuffer.ATI_FLOAT); + } + + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int nformats; + int[] nformatsTmp = new int[1]; + if (!wglExt.wglChoosePixelFormatARB(parentHdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + nformatsTmp, 0)) { + throw new GLException("pbuffer creation error: wglChoosePixelFormat() failed"); + } + nformats = nformatsTmp[0]; + if (nformats <= 0) { + throw new GLException("pbuffer creation error: Couldn't find a suitable pixel format"); + } + + boolean haveMultisample = wglExt.isExtensionAvailable("WGL_ARB_multisample"); + + if (DEBUG) { + System.err.println("" + nformats + " suitable pixel formats found"); + // query pixel format + iattributes[0] = WGLExt.WGL_RED_BITS_ARB; + iattributes[1] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[2] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[3] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[4] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[5] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); + iattributes[6] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[7] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[8] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + int[] ivalues = new int[9]; + for (int i = 0; i < nformats; i++) { + if (!wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[i], 0, 9, iattributes, 0, ivalues, 0)) { + throw new GLException("Error while querying pixel format " + pformats[i] + + "'s (index " + i + "'s) capabilities for debugging"); + } + System.err.print("pixel format " + pformats[i] + " (index " + i + "): "); + System.err.print( "r: " + ivalues[0]); + System.err.print(" g: " + ivalues[1]); + System.err.print(" b: " + ivalues[2]); + System.err.print(" a: " + ivalues[3]); + System.err.print(" depth: " + ivalues[4]); + if (haveMultisample) { + System.err.print(" multisample: " + ivalues[6]); + } + System.err.print(" samples: " + ivalues[7]); + if (useFloat) { + if (ati) { + if (ivalues[5] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { + System.err.print(" [ati float]"); + } else if (ivalues[5] != WGLExt.WGL_TYPE_RGBA_ARB) { + System.err.print(" [unknown pixel type " + ivalues[5] + "]"); + } + } else { + if (ivalues[5] != 0) { + System.err.print(" [float]"); + } + } + } + + if (ivalues[8] != 0) { + System.err.print(" [pbuffer]"); + } + System.err.println(); + } + } + + long tmpBuffer = 0; + int whichFormat = -1; + // Loop is a workaround for bugs in NVidia's recent drivers + for (whichFormat = 0; whichFormat < nformats; whichFormat++) { + int format = pformats[whichFormat]; + + // Create the p-buffer. + niattribs = 0; + + if (rtt) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FORMAT_ARB; + if (useFloat) { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_FLOAT_RGB_NV; + } else { + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_RGBA_ARB; + } + + iattributes[niattribs++] = WGLExt.WGL_TEXTURE_TARGET_ARB; + iattributes[niattribs++] = rect ? WGLExt.WGL_TEXTURE_RECTANGLE_NV : WGLExt.WGL_TEXTURE_2D_ARB; + + iattributes[niattribs++] = WGLExt.WGL_MIPMAP_TEXTURE_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + + iattributes[niattribs++] = WGLExt.WGL_PBUFFER_LARGEST_ARB; + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = 0; + + tmpBuffer = wglExt.wglCreatePbufferARB(parentHdc, format, getWidth(), getHeight(), iattributes, 0); + if (tmpBuffer != 0) { + // Done + break; + } + } + + if (tmpBuffer == 0) { + throw new GLException("pbuffer creation error: wglCreatePbuffer() failed: tried " + nformats + + " pixel formats, last error was: " + wglGetLastError()); + } + + // Get the device context. + long tmpHdc = wglExt.wglGetPbufferDCARB(tmpBuffer); + if (tmpHdc == 0) { + throw new GLException("pbuffer creation error: wglGetPbufferDC() failed"); + } + + NativeWindow nw = getNativeWindow(); + // Set up instance variables + buffer = tmpBuffer; + ((SurfaceChangeable)nw).setSurfaceHandle(tmpHdc); + cachedWGLExt = wglExt; + cachedParentHdc = parentHdc; + + // Re-query chosen pixel format + { + niattribs = 0; + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + iattributes[niattribs++] = (useFloat ? (ati ? WGLExt.WGL_PIXEL_TYPE_ARB : WGLExt.WGL_FLOAT_COMPONENTS_NV) : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLE_BUFFERS_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = (haveMultisample ? WGLExt.WGL_SAMPLES_ARB : WGLExt.WGL_RED_BITS_ARB); + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + int[] ivalues = new int[niattribs]; + if (wglExt.wglGetPixelFormatAttribivARB(parentHdc, pformats[whichFormat], 0, niattribs, iattributes, 0, ivalues, 0)) { + GLCapabilities newCaps = WindowsWGLGraphicsConfiguration.AttribList2GLCapabilities(glProfile, iattributes, niattribs, ivalues, true, false, true); + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { + if (DEBUG) { + System.err.println("Unable to describe pixel format (Continue: true) " + whichFormat + "/" + nformats + " pfdID " + pformats[whichFormat]+":\n\t"+newCaps); + } + } + if(newCaps.isOnscreen()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps+"\n\t"+newCaps); + } + config.setCapsPFD(newCaps, pfd, pformats[whichFormat], true); + } else { + PIXELFORMATDESCRIPTOR pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(parentHdc, pformats[whichFormat], pfd.size(), pfd) == 0) { + throw new GLException("Unable to describe pixel format " + pformats[whichFormat]); + } + GLCapabilities newCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, false, true); + if(newCaps.isOnscreen()) { + throw new GLException("Error: Selected Onscreen Caps for PBuffer: "+newCaps+"\n\t"+newCaps); + } + config.setCapsPFD(newCaps, pfd, pformats[whichFormat], false); + } + } + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_WIDTH_ARB, tmp, 0 ); + width = tmp[0]; + wglExt.wglQueryPbufferARB( buffer, WGLExt.WGL_PBUFFER_HEIGHT_ARB, tmp, 0 ); + height = tmp[0]; + ((SurfaceChangeable)nw).setSize(width, height); + } + + private static String wglGetLastError() { + return WindowsWGLDrawableFactory.wglGetLastError(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java new file mode 100644 index 000000000..0f1f9813f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLContext.java @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public class WindowsWGLContext extends GLContextImpl { + protected long hglrc; + private boolean wglGetExtensionsStringEXTInitialized; + private boolean wglGetExtensionsStringEXTAvailable; + private boolean wglMakeContextCurrentInitialized; + private boolean wglMakeContextCurrentARBAvailable; + private boolean wglMakeContextCurrentEXTAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; + private WGLExt wglExt; + // Table that holds the addresses of the native C-language entry points for + // WGL extension functions. + private WGLExtProcAddressTable wglExtProcAddressTable; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "wglAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "wglFreeMemoryNV"); + + extensionNameMap = new HashMap(); + extensionNameMap.put("GL_ARB_pbuffer", "WGL_ARB_pbuffer"); + extensionNameMap.put("GL_ARB_pixel_format", "WGL_ARB_pixel_format"); + } + + // FIXME: figure out how to hook back in the Java 2D / JOGL bridge + public WindowsWGLContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public WindowsWGLContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public Object getPlatformGLExtensions() { + return getWGLExt(); + } + + public WGLExt getWGLExt() { + if (wglExt == null) { + wglExt = new WGLExtImpl(this); + } + return wglExt; + } + + public boolean wglMakeContextCurrent(long hDrawDC, long hReadDC, long hglrc) { + WGLExt wglExt = getWGLExt(); + if (!wglMakeContextCurrentInitialized) { + wglMakeContextCurrentARBAvailable = isFunctionAvailable("wglMakeContextCurrentARB"); + wglMakeContextCurrentEXTAvailable = isFunctionAvailable("wglMakeContextCurrentEXT"); + wglMakeContextCurrentInitialized = true; + if(DEBUG) { + System.err.println("WindowsWGLContext.wglMakeContextCurrent: ARB "+wglMakeContextCurrentARBAvailable+", EXT "+wglMakeContextCurrentEXTAvailable); + } + } + if(wglMakeContextCurrentARBAvailable) { + return wglExt.wglMakeContextCurrentARB(hDrawDC, hReadDC, hglrc); + } else if(wglMakeContextCurrentEXTAvailable) { + return wglExt.wglMakeContextCurrentEXT(hDrawDC, hReadDC, hglrc); + } + return WGL.wglMakeCurrent(hDrawDC, hglrc); + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getWGLExtProcAddressTable(); + } + + public final WGLExtProcAddressTable getWGLExtProcAddressTable() { + return wglExtProcAddressTable; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return functionNameMap; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } + + protected void destroyContextARBImpl(long context) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(context); + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + WGLExt wglExt; + if(null==factory.getSharedContext()) { + wglExt = getWGLExt(); + } else { + wglExt = ((WindowsWGLContext)factory.getSharedContext()).getWGLExt(); + } + + boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + long _context=0; + + int attribs[] = { + /* 0 */ WGLExt.WGL_CONTEXT_MAJOR_VERSION_ARB, major, + /* 2 */ WGLExt.WGL_CONTEXT_MINOR_VERSION_ARB, minor, + /* 4 */ WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, WGLExt.WGL_CONTEXT_LAYER_PLANE_ARB, // default + /* 6 */ WGLExt.WGL_CONTEXT_FLAGS_ARB, 0, + /* 8 */ 0, 0, + /* 10 */ 0 + }; + + if ( major > 3 || major == 3 && minor >= 2 ) { + // FIXME: Verify with a None drawable binding (default framebuffer) + attribs[8+0] = WGLExt.WGL_CONTEXT_PROFILE_MASK_ARB; + if( ctBwdCompat ) { + attribs[8+1] = WGLExt.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } else { + attribs[8+1] = WGLExt.WGL_CONTEXT_CORE_PROFILE_BIT_ARB; + } + } + + if ( major >= 3 ) { + if( !ctBwdCompat && ctFwdCompat ) { + attribs[6+1] |= WGLExt.WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if( ctDebug) { + attribs[6+1] |= WGLExt.WGL_CONTEXT_DEBUG_BIT_ARB; + } + } + + _context = wglExt.wglCreateContextAttribsARB(drawable.getNativeWindow().getSurfaceHandle(), share, attribs, 0); + if(0==_context) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContextARB couldn't create "+getGLVersion(null, major, minor, ctp, "@creation")); + } + } else { + // In contrast to GLX no verification with a drawable binding, ie default framebuffer, is necessary, + // if no 3.2 is available creation fails already! + // Nevertheless .. we do it .. + if (!WGL.wglMakeCurrent(drawable.getNativeWindow().getSurfaceHandle(), _context)) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContextARB couldn't make current "+getGLVersion(null, major, minor, ctp, "@creation")); + } + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(_context); + _context = 0; + } + } + return _context; + } + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link #makeCurrentImpl()}. + */ + protected void create() { + if(0!=context) { + throw new GLException("context is not null: "+context); + } + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); + GLCapabilities glCaps = drawable.getChosenGLCapabilities(); + + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("Internal error: attempted to create OpenGL context without an associated drawable"); + } + // Windows can set up sharing of display lists after creation time + WindowsWGLContext other = (WindowsWGLContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getHGLRC(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + } + + int minor[] = new int[1]; + int major[] = new int[1]; + int ctp[] = new int[1]; + boolean createContextARBTried = false; + + // utilize the shared context's GLXExt in case it was using the ARB method and it already exists + if(null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod()) { + if(DEBUG) { + System.err.println("WindowsWGLContext.createContext using shared Context: "+factory.getSharedContext()); + } + hglrc = createContextARB(share, true, major, minor, ctp); + createContextARBTried = true; + } + + long temp_hglrc = 0; + if(0==hglrc) { + // To use WGL_ARB_create_context, we have to make a temp context current, + // so we are able to use GetProcAddress + temp_hglrc = WGL.wglCreateContext(drawable.getNativeWindow().getSurfaceHandle()); + if (temp_hglrc == 0) { + throw new GLException("Unable to create temp OpenGL context for device context " + toHexString(drawable.getNativeWindow().getSurfaceHandle())); + } + if (!WGL.wglMakeCurrent(drawable.getNativeWindow().getSurfaceHandle(), temp_hglrc)) { + throw new GLException("Error making temp context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + if( createContextARBTried || + !isFunctionAvailable("wglCreateContextAttribsARB") || + !isExtensionAvailable("WGL_ARB_create_context") ) { + if(glCaps.getGLProfile().isGL3()) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + throw new GLException("Unable to create OpenGL >= 3.1 context (no WGL_ARB_create_context)"); + } + + // continue with temp context for GL < 3.0 + hglrc = temp_hglrc; + return; + } + hglrc = createContextARB(share, true, major, minor, ctp); + createContextARBTried=true; + } + + if(0!=hglrc) { + share = 0; // mark as shared .. + + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + throw new GLException("Cannot make previous verified context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } else { + if(glCaps.getGLProfile().isGL3()) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(temp_hglrc); + throw new GLException("WindowsWGLContext.createContext failed, but context > GL2 requested "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")+", "); + } + if(DEBUG) { + System.err.println("WindowsWGLContext.createContext failed, fall back to !ARB context "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")); + } + + // continue with temp context for GL < 3.0 + hglrc = temp_hglrc; + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + WGL.wglMakeCurrent(0, 0); + WGL.wglDeleteContext(hglrc); + throw new GLException("Error making old context current: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } + + if(0!=share) { + if (!WGL.wglShareLists(share, hglrc)) { + throw new GLException("wglShareLists(" + toHexString(share) + + ", " + toHexString(hglrc) + ") failed: error code 0x" + + Integer.toHexString(WGL.GetLastError())); + } + } + GLContextShareSet.contextCreated(this); + } + + protected int makeCurrentImpl() throws GLException { + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (hglrc == 0) { + create(); + created = true; + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + } + + if (WGL.wglGetCurrentContext() != hglrc) { + if (!wglMakeContextCurrent(drawable.getNativeWindow().getSurfaceHandle(), drawableRead.getNativeWindow().getSurfaceHandle(), hglrc)) { + throw new GLException("Error making context current: 0x" + Integer.toHexString(WGL.GetLastError()) + ", " + this); + } else { + if (DEBUG && VERBOSE) { + System.err.println(getThreadName() + ": wglMakeCurrent(hdc " + toHexString(drawable.getNativeWindow().getSurfaceHandle()) + + ", hglrc " + toHexString(hglrc) + ") succeeded"); + } + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + + WindowsWGLGraphicsConfiguration config = + (WindowsWGLGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateCapabilitiesByWGL(this); + + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + if (!wglMakeContextCurrent(0, 0, 0)) { + throw new GLException("Error freeing OpenGL context: 0x" + Integer.toHexString(WGL.GetLastError())); + } + } + + protected void destroyImpl() throws GLException { + if (DEBUG) { + Exception e = new Exception(getThreadName() + ": !!! Destroyed OpenGL context " + toHexString(hglrc)); + e.printStackTrace(); + } + if (hglrc != 0) { + if (!WGL.wglDeleteContext(hglrc)) { + throw new GLException("Unable to delete OpenGL context"); + } + hglrc = 0; + GLContextShareSet.contextDestroyed(this); + } + } + + public boolean isCreated() { + return (hglrc != 0); + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getHGLRC(); + long src = ((WindowsWGLContext) source).getHGLRC(); + if (src == 0) { + throw new GLException("Source OpenGL context has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL context has not been created"); + } + if (!WGL.wglCopyContext(src, dst, mask)) { + throw new GLException("wglCopyContext failed"); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing WGL extension address table for " + this); + } + wglGetExtensionsStringEXTInitialized=false; + wglGetExtensionsStringEXTAvailable=false; + wglMakeContextCurrentInitialized=false; + wglMakeContextCurrentARBAvailable=false; + wglMakeContextCurrentEXTAvailable=false; + + if (wglExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + wglExtProcAddressTable = new WGLExtProcAddressTable(); + } + resetProcAddressTable(getWGLExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public String getPlatformExtensionsString() { + if (!wglGetExtensionsStringEXTInitialized) { + wglGetExtensionsStringEXTAvailable = (WGL.wglGetProcAddress("wglGetExtensionsStringEXT") != 0); + wglGetExtensionsStringEXTInitialized = true; + } + if (wglGetExtensionsStringEXTAvailable) { + return getWGLExt().wglGetExtensionsStringEXT(); + } else { + return ""; + } + } + + protected void setSwapIntervalImpl(int interval) { + WGLExt wglExt = getWGLExt(); + if (wglExt.isExtensionAvailable("WGL_EXT_swap_control")) { + if ( wglExt.wglSwapIntervalEXT(interval) ) { + currentSwapInterval = interval ; + } + } + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + return getWGLExt().wglAllocateMemoryNV(arg0, arg1, arg2, arg3); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getHGLRC() { + return hglrc; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java new file mode 100644 index 000000000..43c1ff5e0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawable.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public abstract class WindowsWGLDrawable extends GLDrawableImpl { + private static final int MAX_SET_PIXEL_FORMAT_FAIL_COUNT = 5; + private static final boolean PROFILING = Debug.debug("WindowsWGLDrawable.profiling"); + private static final int PROFILING_TICKS = 200; + private int profilingLockSurfaceTicks; + private long profilingLockSurfaceTime; + private int profilingUnlockSurfaceTicks; + private long profilingUnlockSurfaceTime; + private int profilingSwapBuffersTicks; + private long profilingSwapBuffersTime; + + + public WindowsWGLDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + protected void setRealizedImpl() { + if(!realized) { + return; // nothing todo .. + } + + if(NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface()) { + throw new GLException("WindowsWGLDrawable.setRealized(true): lockSurface - surface not ready"); + } + try { + NativeWindow nativeWindow = getNativeWindow(); + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)nativeWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(getFactory(), nativeWindow); + if (DEBUG) { + System.err.println("!!! WindowsWGLDrawable.setRealized(true): "+config); + } + } finally { + unlockSurface(); + } + } + + protected void swapBuffersImpl() { + boolean didLock = false; + + if ( !isSurfaceLocked() ) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + + long startTime = 0; + if (PROFILING) { + startTime = System.currentTimeMillis(); + } + + if (!WGL.SwapBuffers(getNativeWindow().getSurfaceHandle()) && (WGL.GetLastError() != 0)) { + throw new GLException("Error swapping buffers"); + } + + if (PROFILING) { + long endTime = System.currentTimeMillis(); + profilingSwapBuffersTime += (endTime - startTime); + int ticks = PROFILING_TICKS; + if (++profilingSwapBuffersTicks == ticks) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + ticks + " calls (" + + ((float) profilingSwapBuffersTime / (float) ticks) + " ms/call)"); + profilingSwapBuffersTime = 0; + profilingSwapBuffersTicks = 0; + } + } + } finally { + if (didLock) { + unlockSurface(); + } + } + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (WindowsWGLDrawableFactory) getFactoryImpl() ; + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java new file mode 100644 index 000000000..a4bf89b81 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import java.util.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import javax.media.opengl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + +public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + private static final boolean VERBOSE = Debug.verbose(); + + // Handle to GLU32.dll + // FIXME: this should go away once we delete support for the C GLU library + private long hglu32; + + // Handle to core OpenGL32.dll + private long hopengl32; + + public WindowsWGLDrawableFactory() { + super(); + + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new WindowsWGLGraphicsConfigurationFactory(); + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + + loadOpenGL32Library(); + + sharedDrawable = new WindowsDummyWGLDrawable(this, null); + WindowsWGLContext ctx = (WindowsWGLContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + canCreateGLPbuffer = ctx.getGL().isExtensionAvailable("GL_ARB_pbuffer"); + ctx.release(); + sharedContext = ctx; + if(null==sharedContext) { + throw new GLException("Couldn't init shared resources"); + } + if (DEBUG) { + System.err.println("!!! SharedContext: "+sharedContext+", pbuffer supported "+canCreateGLPbuffer); + } + } + + WindowsDummyWGLDrawable sharedDrawable=null; + WindowsWGLContext sharedContext=null; + boolean canCreateGLPbuffer = false; + + protected final GLDrawableImpl getSharedDrawable() { + validate(); + return sharedDrawable; + } + + protected final GLContextImpl getSharedContext() { + validate(); + return sharedContext; + } + + public void shutdown() { + super.shutdown(); + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! CTX : "+sharedContext); + System.err.println("!!! Drawable: "+sharedDrawable); + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + if(null!=sharedContext) { + sharedContext.destroy(); // implies release, if current + } + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + } + } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new WindowsOnscreenWGLDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + return new WindowsOffscreenWGLDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + validate(); + return canCreateGLPbuffer; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + final List returnList = new ArrayList(); + final GLDrawableFactory factory = this; + final WindowsWGLContext _sharedContext = sharedContext; + final WindowsDummyWGLDrawable _sharedDrawable = sharedDrawable; + Runnable r = new Runnable() { + public void run() { + GLContext lastContext = GLContext.getCurrent(); + if (lastContext != null) { + lastContext.release(); + } + _sharedContext.makeCurrent(); + WGLExt wglExt = _sharedContext.getWGLExt(); + try { + GLDrawableImpl pbufferDrawable = new WindowsPbufferWGLDrawable(factory, target, + _sharedDrawable, + wglExt); + returnList.add(pbufferDrawable); + } finally { + _sharedContext.release(); + if (lastContext != null) { + lastContext.makeCurrent(); + } + } + } + }; + maybeDoSingleThreadedWorkaround(r); + return (GLDrawableImpl) returnList.get(0); + } + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + validate(); + AbstractGraphicsScreen screen = DefaultGraphicsScreen.createDefault(); + NullWindow nw = new NullWindow(WindowsWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capabilities, chooser, screen) ); + nw.setSize(width, height); + return nw; + } + + public GLContext createExternalGLContext() { + validate(); + return WindowsExternalWGLContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + validate(); + return true; + } + + public GLDrawable createExternalGLDrawable() { + validate(); + return WindowsExternalWGLDrawable.create(this, null); + } + + public void loadOpenGL32Library() { + validate(); + if (hopengl32 == 0) { + hopengl32 = WGL.LoadLibraryA("OpenGL32"); + if (DEBUG) { + if (hopengl32 == 0) { + System.err.println("WindowsWGLDrawableFactory: Could not load OpenGL32.dll - maybe an embedded device"); + } + } + } + } + + public void loadGLULibrary() { + validate(); + if (hglu32 == 0) { + hglu32 = WGL.LoadLibraryA("GLU32"); + if (hglu32 == 0) { + throw new GLException("Error loading GLU32.DLL"); + } + } + } + + public long dynamicLookupFunction(String glFuncName) { + validate(); + long res = WGL.wglGetProcAddress(glFuncName); + if (res == 0) { + // It may happen that a driver doesn't return the OpenGL32 core function pointer + // with wglGetProcAddress (e.g. NVidia GL 3.1) - hence we have to look harder. + if (hopengl32 != 0) { + res = WGL.GetProcAddress(hopengl32, glFuncName); + } + } + if (res == 0) { + // GLU routines aren't known to the OpenGL function lookup + if (hglu32 != 0) { + res = WGL.GetProcAddress(hglu32, glFuncName); + } + } + return res; + } + + static String wglGetLastError() { + long err = WGL.GetLastError(); + String detail = null; + switch ((int) err) { + case WGL.ERROR_INVALID_PIXEL_FORMAT: detail = "ERROR_INVALID_PIXEL_FORMAT"; break; + case WGL.ERROR_NO_SYSTEM_RESOURCES: detail = "ERROR_NO_SYSTEM_RESOURCES"; break; + case WGL.ERROR_INVALID_DATA: detail = "ERROR_INVALID_DATA"; break; + case WGL.ERROR_PROC_NOT_FOUND: detail = "ERROR_PROC_NOT_FOUND"; break; + case WGL.ERROR_INVALID_WINDOW_HANDLE:detail = "ERROR_INVALID_WINDOW_HANDLE"; break; + default: detail = "(Unknown error code " + err + ")"; break; + } + return detail; + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + validate(); + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + validate(); + throw new GLException("Unimplemented on this platform"); + } + + //------------------------------------------------------ + // Gamma-related functionality + // + + private static final int GAMMA_RAMP_LENGTH = 256; + + protected int getGammaRampLength() { + return GAMMA_RAMP_LENGTH; + } + + protected boolean setGammaRamp(float[] ramp) { + short[] rampData = new short[3 * GAMMA_RAMP_LENGTH]; + for (int i = 0; i < GAMMA_RAMP_LENGTH; i++) { + short scaledValue = (short) (ramp[i] * 65535); + rampData[i] = scaledValue; + rampData[i + GAMMA_RAMP_LENGTH] = scaledValue; + rampData[i + 2 * GAMMA_RAMP_LENGTH] = scaledValue; + } + + long screenDC = WGL.GetDC(0); + boolean res = WGL.SetDeviceGammaRamp(screenDC, ShortBuffer.wrap(rampData)); + WGL.ReleaseDC(0, screenDC); + return res; + } + + protected Buffer getGammaRamp() { + ShortBuffer rampData = ShortBuffer.wrap(new short[3 * GAMMA_RAMP_LENGTH]); + long screenDC = WGL.GetDC(0); + boolean res = WGL.GetDeviceGammaRamp(screenDC, rampData); + WGL.ReleaseDC(0, screenDC); + if (!res) { + return null; + } + return rampData; + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) { + // getGammaRamp failed earlier + return; + } + long screenDC = WGL.GetDC(0); + WGL.SetDeviceGammaRamp(screenDC, originalGammaRamp); + WGL.ReleaseDC(0, screenDC); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java new file mode 100644 index 000000000..aed4012a4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +public class WindowsWGLGraphicsConfiguration extends DefaultGraphicsConfiguration implements Cloneable { + // Keep this under the same debug flag as the drawable factory for convenience + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + protected static final int MAX_PFORMATS = 256; + protected static final int MAX_ATTRIBS = 256; + + private PIXELFORMATDESCRIPTOR pixelfmt; + private int pixelfmtID; + private boolean isChosen = false; + private GLCapabilitiesChooser chooser; + private boolean choosenByWGLPixelFormat=false; + + public WindowsWGLGraphicsConfiguration(AbstractGraphicsScreen screen, GLCapabilities capsChosen, GLCapabilities capsRequested, + PIXELFORMATDESCRIPTOR pixelfmt, int pixelfmtID, GLCapabilitiesChooser chooser) { + super(screen, capsChosen, capsRequested); + this.chooser=chooser; + this.pixelfmt = pixelfmt; + this.pixelfmtID = pixelfmtID; + } + + public static WindowsWGLGraphicsConfiguration create(long hdc, int pfdID, + GLProfile glp, AbstractGraphicsScreen screen, boolean onscreen, boolean usePBuffer) + { + if(pfdID<=0) { + throw new GLException("Invalid pixelformat id "+pfdID); + } + if(null==glp) { + glp = GLProfile.getDefault(); + } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); + if (WGL.DescribePixelFormat(hdc, pfdID, pfd.size(), pfd) == 0) { + throw new GLException("Unable to describe pixel format " + pfdID); + } + + GLCapabilities caps = PFD2GLCapabilities(glp, pfd, onscreen, usePBuffer); + if(null==caps) { + throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+", pfdID "+pfdID); + } + WindowsWGLGraphicsConfiguration cfg = new WindowsWGLGraphicsConfiguration(screen, caps, caps, pfd, pfdID, new DefaultGLCapabilitiesChooser()); + cfg.setCapsPFD(caps, pfd, pfdID, false); + + return cfg; + } + + public Object clone() { + return super.clone(); + } + + /** Update config - before having a valid context */ + protected void updateGraphicsConfiguration(GLDrawableFactory factory, NativeWindow nativeWindow) { + WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration(chooser, factory, nativeWindow); + } + + /** Update config - after having a valid and current context */ + protected void updateCapabilitiesByWGL(GLContextImpl context) { + if(choosenByWGLPixelFormat) return; // already done .. + + GLCapabilities capabilities = (GLCapabilities) getRequestedCapabilities(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + GLProfile glp = capabilities.getGLProfile(); + + WGLExt wglExt = (WGLExt) context.getPlatformGLExtensions(); + GLDrawable drawable = context.getGLDrawable(); + NativeWindow nativeWindow = drawable.getNativeWindow(); + long hdc = nativeWindow.getSurfaceHandle(); + + GLCapabilities[] caps = HDC2GLCapabilities(wglExt, hdc, getPixelFormatID(), glp, true, onscreen, usePBuffer); + if(null!=caps && null!=caps[0]) { + setCapsPFD(caps[0], getPixelFormat(), getPixelFormatID(), true); + } + } + + protected void setCapsPFD(GLCapabilities caps, PIXELFORMATDESCRIPTOR pfd, int pfdID, boolean choosenByWGLPixelFormat) { + this.pixelfmt = pfd; + this.pixelfmtID = pfdID; + setChosenCapabilities(caps); + this.isChosen=true; + this.choosenByWGLPixelFormat=choosenByWGLPixelFormat; + if (DEBUG) { + System.err.println("*** setCapsPFD: WGL-Choosen "+choosenByWGLPixelFormat+", pfdID "+pfdID+", "+caps); + } + } + + public boolean getCapabilitiesChosen() { + return isChosen; + } + + public PIXELFORMATDESCRIPTOR getPixelFormat() { return pixelfmt; } + public int getPixelFormatID() { return pixelfmtID; } + public boolean isChoosenByWGL() { return choosenByWGLPixelFormat; } + + private static int haveWGLChoosePixelFormatARB = -1; + private static int haveWGLARBMultisample = -1; + + public static GLCapabilities[] HDC2GLCapabilities(WGLExt wglExt, long hdc, int pfdIDOnly, + GLProfile glp, boolean relaxed, boolean onscreen, boolean usePBuffer) { + + if(haveWGLChoosePixelFormatARB<0) { + haveWGLChoosePixelFormatARB = wglExt.isExtensionAvailable("WGL_ARB_pixel_format")?1:0; + } + if(haveWGLARBMultisample<0) { + haveWGLARBMultisample = wglExt.isExtensionAvailable("WGL_ARB_multisample")?1:0; + } + if (0==haveWGLChoosePixelFormatARB) { + return null; + } + + // Produce a list of GLCapabilities to give to the + // GLCapabilitiesChooser. + // Use wglGetPixelFormatAttribivARB instead of + // DescribePixelFormat to get higher-precision information + // about the pixel format (should make the GLCapabilities + // more precise as well...i.e., remove the + // "HardwareAccelerated" bit, which is basically + // meaningless, and put in whether it can render to a + // window, to a pbuffer, or to a pixmap) + GLCapabilities[] availableCaps = null; + int numFormats = 0; + int niattribs = 0; + int[] iattributes = new int [2*MAX_ATTRIBS]; + int[] iresults = new int [2*MAX_ATTRIBS]; + + iattributes[0] = WGLExt.WGL_NUMBER_PIXEL_FORMATS_ARB; + if (wglExt.wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, iattributes, 0, iresults, 0)) { + numFormats = iresults[0]; + + if (DEBUG) { + System.err.println("wglGetPixelFormatAttribivARB reported WGL_NUMBER_PIXEL_FORMATS = " + numFormats); + } + + if(pfdIDOnly>0 && pfdIDOnly>numFormats) { + throw new GLException("Invalid pixelformat ID " + pfdIDOnly + " (should be between 1 and " + numFormats + ")"); + } + + // Should we be filtering out the pixel formats which aren't + // applicable, as we are doing here? + // We don't have enough information in the GLCapabilities to + // represent those that aren't... + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCELERATION_ARB; + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + if (1==haveWGLARBMultisample) { + iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; + iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; + } + + if(pfdIDOnly>0) { + availableCaps = new GLCapabilities[1]; + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, pfdIDOnly, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("Error getting pixel format attributes for pixel format " + pfdIDOnly + " of device context"); + } + availableCaps[0] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, + relaxed, onscreen, usePBuffer); + } else { + availableCaps = new GLCapabilities[numFormats]; + for (int i = 0; i < numFormats; i++) { + if (!wglExt.wglGetPixelFormatAttribivARB(hdc, i+1, 0, niattribs, iattributes, 0, iresults, 0)) { + throw new GLException("Error getting pixel format attributes for pixel format " + (i + 1) + " of device context"); + } + availableCaps[i] = AttribList2GLCapabilities(glp, iattributes, niattribs, iresults, + relaxed, onscreen, usePBuffer); + } + } + } else { + long lastErr = WGL.GetLastError(); + // Intel Extreme graphics fails with a zero error code + if (lastErr != 0) { + throw new GLException("Unable to enumerate pixel formats of window using wglGetPixelFormatAttribivARB: error code " + WGL.GetLastError()); + } + } + return availableCaps; + } + + public static boolean GLCapabilities2AttribList(GLCapabilities caps, + int[] iattributes, + WGLExt wglExt, + boolean pbuffer, + int[] floatMode) throws GLException { + if (!wglExt.isExtensionAvailable("WGL_ARB_pixel_format")) { + return false; + } + + int niattribs = 0; + + iattributes[niattribs++] = WGLExt.WGL_SUPPORT_OPENGL_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + if (pbuffer) { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_PBUFFER_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = WGLExt.WGL_DRAW_TO_WINDOW_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + + iattributes[niattribs++] = WGLExt.WGL_DOUBLE_BUFFER_ARB; + if (caps.getDoubleBuffered()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_STEREO_ARB; + if (caps.getStereo()) { + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = GL.GL_FALSE; + } + + iattributes[niattribs++] = WGLExt.WGL_DEPTH_BITS_ARB; + iattributes[niattribs++] = caps.getDepthBits(); + iattributes[niattribs++] = WGLExt.WGL_RED_BITS_ARB; + iattributes[niattribs++] = caps.getRedBits(); + iattributes[niattribs++] = WGLExt.WGL_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAlphaBits(); + iattributes[niattribs++] = WGLExt.WGL_STENCIL_BITS_ARB; + iattributes[niattribs++] = caps.getStencilBits(); + if (caps.getAccumRedBits() > 0 || + caps.getAccumGreenBits() > 0 || + caps.getAccumBlueBits() > 0 || + caps.getAccumAlphaBits() > 0) { + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BITS_ARB; + iattributes[niattribs++] = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits() + + caps.getAccumAlphaBits()); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_RED_BITS_ARB; + iattributes[niattribs++] = caps.getAccumRedBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_GREEN_BITS_ARB; + iattributes[niattribs++] = caps.getAccumGreenBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_BLUE_BITS_ARB; + iattributes[niattribs++] = caps.getAccumBlueBits(); + iattributes[niattribs++] = WGLExt.WGL_ACCUM_ALPHA_BITS_ARB; + iattributes[niattribs++] = caps.getAccumAlphaBits(); + } + + if (wglExt.isExtensionAvailable("WGL_ARB_multisample")) { + if (caps.getSampleBuffers()) { + iattributes[niattribs++] = WGLExt.WGL_SAMPLE_BUFFERS_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + iattributes[niattribs++] = WGLExt.WGL_SAMPLES_ARB; + iattributes[niattribs++] = caps.getNumSamples(); + } + } + + boolean rtt = caps.getPbufferRenderToTexture(); + boolean rect = caps.getPbufferRenderToTextureRectangle(); + boolean useFloat = caps.getPbufferFloatingPointBuffers(); + boolean ati = false; + if (pbuffer) { + // Check some invariants and set up some state + if (rect && !rtt) { + throw new GLException("Render-to-texture-rectangle requires render-to-texture to be specified"); + } + + if (rect) { + if (!wglExt.isExtensionAvailable("GL_NV_texture_rectangle")) { + throw new GLException("Render-to-texture-rectangle requires GL_NV_texture_rectangle extension"); + } + } + + if (useFloat) { + if (!wglExt.isExtensionAvailable("WGL_ATI_pixel_format_float") && + !wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { + throw new GLException("Floating-point pbuffers not supported by this hardware"); + } + + // Prefer NVidia extension over ATI + if (wglExt.isExtensionAvailable("WGL_NV_float_buffer")) { + ati = false; + floatMode[0] = GLPbuffer.NV_FLOAT; + } else { + ati = true; + floatMode[0] = GLPbuffer.ATI_FLOAT; + } + if (DEBUG) { + System.err.println("Using " + (ati ? "ATI" : "NVidia") + " floating-point extension"); + } + } + + // See whether we need to change the pixel type to support ATI's + // floating-point pbuffers + if (useFloat && ati) { + if (rtt) { + throw new GLException("Render-to-floating-point-texture not supported on ATI hardware"); + } else { + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_FLOAT_ARB; + } + } else { + if (!rtt) { + // Currently we don't support non-truecolor visuals in the + // GLCapabilities, so we don't offer the option of making + // color-index pbuffers. + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; + } + } + + if (useFloat && !ati) { + iattributes[niattribs++] = WGLExt.WGL_FLOAT_COMPONENTS_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } + + if (rtt) { + if (useFloat) { + assert(!ati); + if (!rect) { + throw new GLException("Render-to-floating-point-texture only supported on NVidia hardware with render-to-texture-rectangle"); + } + iattributes[niattribs++] = WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV; + iattributes[niattribs++] = GL.GL_TRUE; + } else { + iattributes[niattribs++] = rect ? WGLExt.WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV : WGLExt.WGL_BIND_TO_TEXTURE_RGB_ARB; + iattributes[niattribs++] = GL.GL_TRUE; + } + } + } else { + iattributes[niattribs++] = WGLExt.WGL_PIXEL_TYPE_ARB; + iattributes[niattribs++] = WGLExt.WGL_TYPE_RGBA_ARB; + } + iattributes[niattribs++] = 0; + + return true; + } + + public static final int WINDOW_BIT = 1 << 0 ; + public static final int BITMAP_BIT = 1 << 1 ; + public static final int PBUFFER_BIT = 1 << 2 ; + + public static int WGLConfig2DrawableTypeBits(int[] iattribs, + int niattribs, + int[] iresults) { + int val = 0; + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + if(iresults[i] == GL.GL_TRUE) val |= WINDOW_BIT; + break; + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + if(iresults[i] == GL.GL_TRUE) val |= BITMAP_BIT; + break; + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + if(iresults[i] == GL.GL_TRUE) val |= PBUFFER_BIT; + break; + } + } + return val; + } + + public static boolean WGLConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & BITMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities AttribList2GLCapabilities(GLProfile glp, int[] iattribs, + int niattribs, + int[] iresults, + boolean relaxed, boolean onscreen, boolean usePBuffer) { + GLCapabilities res = new GLCapabilities(glp); + int drawableTypeBits = WGLConfig2DrawableTypeBits(iattribs, niattribs, iresults); + if(WGLConfigDrawableTypeVerify(drawableTypeBits, onscreen, usePBuffer)) { + res.setOnscreen(onscreen); + res.setPBuffer(usePBuffer); + } else if(relaxed) { + res.setOnscreen( 0 != (drawableTypeBits & WINDOW_BIT) ); + res.setPBuffer ( 0 != (drawableTypeBits & PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("WGL DrawableType does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (drawableTypeBits & WINDOW_BIT) )+", pbuffer "+( 0 != (drawableTypeBits & PBUFFER_BIT) )+", pixmap "+( 0 != (drawableTypeBits & BITMAP_BIT))+")"); + } + return null; + } + + for (int i = 0; i < niattribs; i++) { + int attr = iattribs[i]; + switch (attr) { + case WGLExt.WGL_DRAW_TO_WINDOW_ARB: + case WGLExt.WGL_DRAW_TO_BITMAP_ARB: + case WGLExt.WGL_DRAW_TO_PBUFFER_ARB: + break; + + case WGLExt.WGL_ACCELERATION_ARB: + res.setHardwareAccelerated(iresults[i] == WGLExt.WGL_FULL_ACCELERATION_ARB); + break; + + case WGLExt.WGL_SUPPORT_OPENGL_ARB: + if (iresults[i] != GL.GL_TRUE) { + return null; + } + break; + + case WGLExt.WGL_DEPTH_BITS_ARB: + res.setDepthBits(iresults[i]); + break; + + case WGLExt.WGL_STENCIL_BITS_ARB: + res.setStencilBits(iresults[i]); + break; + + case WGLExt.WGL_DOUBLE_BUFFER_ARB: + res.setDoubleBuffered(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_STEREO_ARB: + res.setStereo(iresults[i] == GL.GL_TRUE); + break; + + case WGLExt.WGL_PIXEL_TYPE_ARB: + // Fail softly with unknown results here + if (iresults[i] == WGLExt.WGL_TYPE_RGBA_ARB|| + iresults[i] == WGLExt.WGL_TYPE_RGBA_FLOAT_ARB) { + res.setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_FLOAT_COMPONENTS_NV: + if (iresults[i] != 0) { + res.setPbufferFloatingPointBuffers(true); + } + break; + + case WGLExt.WGL_RED_BITS_ARB: + res.setRedBits(iresults[i]); + break; + + case WGLExt.WGL_GREEN_BITS_ARB: + res.setGreenBits(iresults[i]); + break; + + case WGLExt.WGL_BLUE_BITS_ARB: + res.setBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ALPHA_BITS_ARB: + res.setAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_RED_BITS_ARB: + res.setAccumRedBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_GREEN_BITS_ARB: + res.setAccumGreenBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_BLUE_BITS_ARB: + res.setAccumBlueBits(iresults[i]); + break; + + case WGLExt.WGL_ACCUM_ALPHA_BITS_ARB: + res.setAccumAlphaBits(iresults[i]); + break; + + case WGLExt.WGL_SAMPLE_BUFFERS_ARB: + res.setSampleBuffers(iresults[i] != 0); + break; + + case WGLExt.WGL_SAMPLES_ARB: + res.setNumSamples(iresults[i]); + break; + + default: + throw new GLException("Unknown pixel format attribute " + iattribs[i]); + } + } + return res; + } + + // PIXELFORMAT + + public static GLCapabilities PFD2GLCapabilities(GLProfile glp, PIXELFORMATDESCRIPTOR pfd, boolean onscreen, boolean usePBuffer) { + if ((pfd.getDwFlags() & WGL.PFD_SUPPORT_OPENGL) == 0) { + return null; + } + GLCapabilities res = new GLCapabilities(glp); + res.setRedBits (pfd.getCRedBits()); + res.setGreenBits (pfd.getCGreenBits()); + res.setBlueBits (pfd.getCBlueBits()); + res.setAlphaBits (pfd.getCAlphaBits()); + res.setAccumRedBits (pfd.getCAccumRedBits()); + res.setAccumGreenBits(pfd.getCAccumGreenBits()); + res.setAccumBlueBits (pfd.getCAccumBlueBits()); + res.setAccumAlphaBits(pfd.getCAccumAlphaBits()); + res.setDepthBits (pfd.getCDepthBits()); + res.setStencilBits (pfd.getCStencilBits()); + res.setDoubleBuffered((pfd.getDwFlags() & WGL.PFD_DOUBLEBUFFER) != 0); + res.setStereo ((pfd.getDwFlags() & WGL.PFD_STEREO) != 0); + res.setHardwareAccelerated( ((pfd.getDwFlags() & WGL.PFD_GENERIC_FORMAT) == 0) || + ((pfd.getDwFlags() & WGL.PFD_GENERIC_ACCELERATED) != 0) ); + res.setOnscreen ( onscreen && ((pfd.getDwFlags() & WGL.PFD_DRAW_TO_WINDOW) != 0) ); + res.setPBuffer ( usePBuffer ); + /* FIXME: Missing ?? + if (GLXUtil.isMultisampleAvailable()) { + res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); + } + res.setBackgroundOpaque(glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_TYPE, tmp, 0) != GLX.GLX_NONE); + try { + res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); + } catch (Exception e) {} + */ + return res; + } + + public static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilities caps) { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(); + int pfdFlags = (WGL.PFD_SUPPORT_OPENGL | + WGL.PFD_GENERIC_ACCELERATED); + if (caps.getDoubleBuffered()) { + pfdFlags |= WGL.PFD_DOUBLEBUFFER; + } + if (caps.isOnscreen()) { + pfdFlags |= WGL.PFD_DRAW_TO_WINDOW; + } else { + pfdFlags |= WGL.PFD_DRAW_TO_BITMAP; + } + if (caps.getStereo()) { + pfdFlags |= WGL.PFD_STEREO; + } + pfd.setDwFlags(pfdFlags); + pfd.setIPixelType((byte) WGL.PFD_TYPE_RGBA); + pfd.setCColorBits((byte) colorDepth); + pfd.setCRedBits ((byte) caps.getRedBits()); + pfd.setCGreenBits((byte) caps.getGreenBits()); + pfd.setCBlueBits ((byte) caps.getBlueBits()); + pfd.setCAlphaBits((byte) caps.getAlphaBits()); + int accumDepth = (caps.getAccumRedBits() + + caps.getAccumGreenBits() + + caps.getAccumBlueBits()); + pfd.setCAccumBits ((byte) accumDepth); + pfd.setCAccumRedBits ((byte) caps.getAccumRedBits()); + pfd.setCAccumGreenBits((byte) caps.getAccumGreenBits()); + pfd.setCAccumBlueBits ((byte) caps.getAccumBlueBits()); + pfd.setCAccumAlphaBits((byte) caps.getAccumAlphaBits()); + pfd.setCDepthBits((byte) caps.getDepthBits()); + pfd.setCStencilBits((byte) caps.getStencilBits()); + pfd.setILayerType((byte) WGL.PFD_MAIN_PLANE); + + /* FIXME: Missing: + caps.getSampleBuffers() + caps.getNumSamples () + } + caps.getBackgroundOpaque() + try { + caps.getPbufferFloatingPointBuffers() + } catch (Exception e) {} + */ + return pfd; + } + + public static PIXELFORMATDESCRIPTOR createPixelFormatDescriptor() { + PIXELFORMATDESCRIPTOR pfd = PIXELFORMATDESCRIPTOR.create(); + pfd.setNSize((short) pfd.size()); + pfd.setNVersion((short) 1); + return pfd; + } + + public String toString() { + return "WindowsWGLGraphicsConfiguration["+getScreen()+", pfdID " + pixelfmtID + ", wglChoosen "+choosenByWGLPixelFormat+ + ",\n\trequested " + getRequestedCapabilities() + + ",\n\tchosen " + getChosenCapabilities() + + "]"; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..ab3227257 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.windows.wgl; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import com.jogamp.nativewindow.impl.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on Windows platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class WindowsWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public WindowsWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.windows.WindowsGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GLCapabilities caps = (GLCapabilities)capabilities; + return chooseGraphicsConfigurationStatic(caps, chooser, absScreen); + } + + protected static WindowsWGLGraphicsConfiguration createDefaultGraphicsConfiguration(GLProfile glp, AbstractGraphicsScreen absScreen, boolean onscreen, boolean usePBuffer) { + GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(onscreen); // FIXME DBLBUFOFFSCRN + caps.setOnscreen (onscreen); + caps.setPBuffer (usePBuffer); + + if(null==absScreen) { + absScreen = DefaultGraphicsScreen.createScreenDevice(0); + } + return new WindowsWGLGraphicsConfiguration(absScreen, caps, caps, WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps), -1, null); + + } + + protected static WindowsWGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilities caps, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if(null==absScreen) { + absScreen = DefaultGraphicsScreen.createScreenDevice(0); + } + GLCapabilities caps2 = (GLCapabilities) caps.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + return new WindowsWGLGraphicsConfiguration(absScreen, caps2, caps, WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(caps2), -1, + (GLCapabilitiesChooser)chooser); + } + + protected static void updateGraphicsConfiguration(CapabilitiesChooser chooser, + GLDrawableFactory _factory, NativeWindow nativeWindow) { + WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory) _factory; + if (nativeWindow == null) { + throw new IllegalArgumentException("NativeWindow is null"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + boolean choosenBywGLPixelFormat = false; + WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration) nativeWindow.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities capabilities = (GLCapabilities) config.getRequestedCapabilities(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + GLProfile glProfile = capabilities.getGLProfile(); + long hdc = nativeWindow.getSurfaceHandle(); + + if (DEBUG) { + Exception ex = new Exception("WindowsWGLGraphicsConfigurationFactory got HDC "+toHexString(hdc)); + ex.printStackTrace(); + System.err.println("WindowsWGLGraphicsConfigurationFactory got NW "+nativeWindow); + } + + PIXELFORMATDESCRIPTOR pfd = null; + int pixelFormat = -1; // 1-based pixel format + boolean pixelFormatSet = false; + GLCapabilities chosenCaps = null; + + if (onscreen) { + if ((pixelFormat = WGL.GetPixelFormat(hdc)) != 0) { + // Pixelformat already set by either + // - a previous updateGraphicsConfiguration() call on the same HDC, + // - the graphics driver, copying the HDC's pixelformat to the new one, + // - or the Java2D/OpenGL pipeline's configuration + if (DEBUG) { + System.err.println("!!!! NOTE: pixel format already chosen for HDC: " + toHexString(hdc)+ + ", pixelformat "+pixelFormat); + } + pixelFormatSet = true; + } + + GLCapabilities[] availableCaps = null; + int numFormats = 0; + pfd = WindowsWGLGraphicsConfiguration.createPixelFormatDescriptor(); + // Produce a recommended pixel format selection for the GLCapabilitiesChooser. + // Use wglChoosePixelFormatARB if user requested multisampling and if we have it available + factory.sharedContext.makeCurrent(); + WGLExt wglExt = factory.sharedContext.getWGLExt(); + + int recommendedPixelFormat = pixelFormat; // 1-based pixel format + boolean haveWGLChoosePixelFormatARB = false; + boolean gotAvailableCaps = false; + if (wglExt != null) { + try { + haveWGLChoosePixelFormatARB = wglExt.isExtensionAvailable("WGL_ARB_pixel_format"); + if (haveWGLChoosePixelFormatARB) { + if(pixelFormat<=0) { + int[] iattributes = new int [2*WindowsWGLGraphicsConfiguration.MAX_ATTRIBS]; + float[] fattributes = new float[1]; + + if(WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(capabilities, + iattributes, + wglExt, + false, + null)) { + int[] pformats = new int[WindowsWGLGraphicsConfiguration.MAX_PFORMATS]; + int[] numFormatsTmp = new int[1]; + if (wglExt.wglChoosePixelFormatARB(hdc, + iattributes, 0, + fattributes, 0, + WindowsWGLGraphicsConfiguration.MAX_PFORMATS, + pformats, 0, + numFormatsTmp, 0)) { + numFormats = numFormatsTmp[0]; + if (recommendedPixelFormat<=0 && numFormats > 0) { + recommendedPixelFormat = pformats[0]; + if (DEBUG) { + System.err.println(getThreadName() + ": Used wglChoosePixelFormatARB to recommend pixel format " + recommendedPixelFormat); + } + } + } else { + if (DEBUG) { + System.err.println(getThreadName() + ": wglChoosePixelFormatARB failed: " + WGL.GetLastError() ); + Thread.dumpStack(); + } + } + if (DEBUG) { + if (recommendedPixelFormat <= 0) { + System.err.print(getThreadName() + ": wglChoosePixelFormatARB didn't recommend a pixel format: "+WGL.GetLastError()); + if (capabilities.getSampleBuffers()) { + System.err.print(" for multisampled GLCapabilities"); + } + System.err.println(); + } + } + } + } + + availableCaps = WindowsWGLGraphicsConfiguration.HDC2GLCapabilities(wglExt, hdc, -1, glProfile, pixelFormatSet, onscreen, usePBuffer); + gotAvailableCaps = null!=availableCaps ; + choosenBywGLPixelFormat = gotAvailableCaps ; + } else if (DEBUG) { + System.err.println(getThreadName() + ": wglChoosePixelFormatARB not available"); + } + } finally { + factory.sharedContext.release(); + } + } + + if (!gotAvailableCaps) { + if (DEBUG) { + System.err.println(getThreadName() + ": Using ChoosePixelFormat ... (LastError: "+WGL.GetLastError()+")"); + } + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capabilities); + recommendedPixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + if (DEBUG) { + System.err.println(getThreadName() + ": ChoosePixelFormat(HDC "+toHexString(hdc)+") = " + recommendedPixelFormat + " (LastError: "+WGL.GetLastError()+")"); + System.err.println(getThreadName() + ": Used " + capabilities); + } + + numFormats = WGL.DescribePixelFormat(hdc, 1, 0, null); + if (numFormats == 0) { + throw new GLException("Unable to enumerate pixel formats of window " + + toHexString(hdc) + " for GLCapabilitiesChooser (LastError: "+WGL.GetLastError()+")"); + } + availableCaps = new GLCapabilities[numFormats]; + for (int i = 0; i < numFormats; i++) { + if (WGL.DescribePixelFormat(hdc, 1 + i, pfd.size(), pfd) == 0) { + throw new GLException("Error describing pixel format " + (1 + i) + " of device context"); + } + availableCaps[i] = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, onscreen, usePBuffer); + } + } + + // NOTE: officially, should make a copy of all of these + // GLCapabilities to avoid mutation by the end user during the + // chooseCapabilities call, but for the time being, assume they + // won't be changed + + if(pixelFormat<=0) { + if(null!=chooser) { + // Supply information to chooser + try { + pixelFormat = chooser.chooseCapabilities(capabilities, availableCaps, recommendedPixelFormat) + 1; + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + pixelFormat = -1; + } + } else { + pixelFormat = recommendedPixelFormat; + } + if (pixelFormat <= 0) { + // keep on going .. + if(DEBUG) { + System.err.println("WindowsWGLGraphicsConfigurationFactory.updateGraphicsConfiguration .. unable to choose config, using first"); + } + pixelFormat = 1; // default .. + } else if ( pixelFormat > numFormats ) { + // keep on going .. + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 1.." + numFormats + ", got "+pixelFormat+")"); + } + pixelFormat = 1; // default .. + } + } + chosenCaps = availableCaps[pixelFormat-1]; + if (DEBUG) { + System.err.println(getThreadName() + ": Chosen pixel format (" + pixelFormat + "):"); + System.err.println(chosenCaps); + } + if (WGL.DescribePixelFormat(hdc, pixelFormat, pfd.size(), pfd) == 0) { + throw new GLException("Error re-describing the chosen pixel format: " + WGL.GetLastError()); + } + } else { + // For now, use ChoosePixelFormat for offscreen surfaces until + // we figure out how to properly choose an offscreen- + // compatible pixel format + pfd = WindowsWGLGraphicsConfiguration.GLCapabilities2PFD(capabilities); + pixelFormat = WGL.ChoosePixelFormat(hdc, pfd); + } + if(!pixelFormatSet) { + if (!WGL.SetPixelFormat(hdc, pixelFormat, pfd)) { + long lastError = WGL.GetLastError(); + if (DEBUG) { + System.err.println(getThreadName() + ": SetPixelFormat failed: current context = " + WGL.wglGetCurrentContext() + + ", current DC = " + WGL.wglGetCurrentDC()); + System.err.println(getThreadName() + ": GetPixelFormat(hdc " + toHexString(hdc) + ") returns " + WGL.GetPixelFormat(hdc)); + } + throw new GLException("Unable to set pixel format " + pixelFormat + " for device context " + toHexString(hdc) + ": error code " + lastError); + } + pixelFormatSet=true; + } + // Reuse the previously-constructed GLCapabilities because it + // turns out that using DescribePixelFormat on some pixel formats + // (which, for example, support full-scene antialiasing) for some + // reason return that they are not OpenGL-capable + if (chosenCaps != null) { + capabilities = chosenCaps; + } else { + capabilities = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, pfd, onscreen, usePBuffer); + } + config.setCapsPFD(capabilities, pfd, pixelFormat, choosenBywGLPixelFormat); + } + + protected static String getThreadName() { + return Thread.currentThread().getName(); + } + public static String toHexString(long hex) { + return "0x" + Long.toHexString(hex); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java new file mode 100644 index 000000000..02cfd14c3 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.windows.wgl.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.windows.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.windows.wgl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.windows.*; + +public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); + + public WindowsAWTWGLGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: got "+absScreen); + } + GraphicsConfiguration gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + long displayHandle = 0; + + WindowsGraphicsDevice winDevice = new WindowsGraphicsDevice(); + DefaultGraphicsScreen winScreen = new DefaultGraphicsScreen(winDevice, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: made "+winScreen); + } + + WindowsWGLGraphicsConfiguration winConfig = (WindowsWGLGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(winDevice).chooseGraphicsConfiguration(capabilities, + chooser, + winScreen); + + if (winConfig == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+winScreen); + } + + if(DEBUG) { + System.err.println("WindowsAWTWGLGraphicsConfigurationFactory: chosen "+winConfig); + } + + // FIXME: we have nothing to match .. so choose the default + return new AWTGraphicsConfiguration(awtScreen, winConfig.getChosenCapabilities(), winConfig.getRequestedCapabilities(), gc, winConfig); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java new file mode 100644 index 000000000..ec0eaf94f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; + +import com.jogamp.nativewindow.impl.x11.*; + +public class GLXUtil { + public static boolean isMultisampleAvailable(long display) { + X11Lib.XLockDisplay(display); + try { + String exts = GLX.glXGetClientString(display, GLX.GLX_EXTENSIONS); + if (exts != null) { + return (exts.indexOf("GLX_ARB_multisample") >= 0); + } + return false; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + /** Workaround for apparent issue with ATI's proprietary drivers + where direct contexts still send GLX tokens for GL calls */ + public static String getVendorName(long display) { + X11Lib.XLockDisplay(display); + try { + return GLX.glXGetClientString(display, GLX.GLX_VENDOR); + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + public static boolean isVendorNVIDIA(String vendor) { + return vendor != null && vendor.startsWith("NVIDIA") ; + } + + public static boolean isVendorATI(String vendor) { + return vendor != null && vendor.startsWith("ATI") ; + } + + public static boolean isVendorATI(long display) { + return isVendorATI(getVendorName(display)); + } + + public static boolean isVendorNVIDIA(long display) { + return isVendorNVIDIA(getVendorName(display)); + } + + public static void getGLXVersion(long display, int major[], int minor[]) { + if(0 == display) { + throw new GLException("null display handle"); + } + if(major.length<1||minor.length<1) { + throw new GLException("passed int arrays size is not >= 1"); + } + + if (!GLX.glXQueryVersion(display, major, 0, minor, 0)) { + throw new GLException("glXQueryVersion failed"); + } + + // Work around bugs in ATI's Linux drivers where they report they + // only implement GLX version 1.2 on the server side + if (major[0] == 1 && minor[0] == 2) { + String str = GLX.glXGetClientString(display, GLX.GLX_VERSION); + try { + // e.g. "1.3" + major[0] = Integer.valueOf(str.substring(0, 1)).intValue(); + minor[0] = Integer.valueOf(str.substring(2, 3)).intValue(); + } catch (Exception e) { + major[0] = 1; + minor[0] = 2; + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java new file mode 100644 index 000000000..1f148bead --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11DummyGLXDrawable.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11DummyGLXDrawable extends X11OnscreenGLXDrawable { + + private long dummyWindow = 0; + + /** + * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, + * we cannot switch the Display as we please, + * hence we reuse the target's screen configuration. + */ + public X11DummyGLXDrawable(X11GraphicsScreen screen, GLDrawableFactory factory, GLProfile glp) { + super(factory, + new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + new GLCapabilities(glp), null, screen))); + this.realized = true; + + NullWindow nw = (NullWindow) getNativeWindow(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities caps = (GLCapabilities) config.getChosenCapabilities(); + + X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + long dpy = device.getHandle(); + int scrn = screen.getIndex(); + long visualID = config.getVisualID(); + + X11Lib.XLockDisplay(dpy); + try{ + dummyWindow = X11Lib.CreateDummyWindow(dpy, scrn, visualID); + } finally { + X11Lib.XUnlockDisplay(dpy); + } + nw.setSurfaceHandle( dummyWindow ); + } + + public void setSize(int width, int height) { + } + + public int getWidth() { + return 1; + } + + public int getHeight() { + return 1; + } + + public void destroy() { + if(0!=dummyWindow) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long dpy = config.getScreen().getDevice().getHandle(); + X11Lib.DestroyDummyWindow(dpy, dummyWindow); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java new file mode 100755 index 000000000..139c0deed --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11ExternalGLXContext extends X11GLXContext { + private boolean firstMakeCurrent = true; + private boolean created = true; + private GLContext lastContext; + + private X11ExternalGLXContext(Drawable drawable, long context) { + super(drawable, null); + this.context = context; + GLContextShareSet.contextCreated(this); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + getGLStateTracker().setEnabled(false); // external context usage can't track state in Java + } + + protected static X11ExternalGLXContext create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long context = GLX.glXGetCurrentContext(); + if (context == 0) { + throw new GLException("Error: current context null"); + } + long display = GLX.glXGetCurrentDisplay(); + if (display == 0) { + throw new GLException("Error: current display null"); + } + long drawable = GLX.glXGetCurrentDrawable(); + if (drawable == 0) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable/context current"); + } + int[] val = new int[1]; + GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + + GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); + X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); + + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(drawable); + return new X11ExternalGLXContext(new Drawable(factory, nw), context); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + protected void create() { + } + + public int makeCurrent() throws GLException { + // Save last context if necessary to allow external GLContexts to + // talk to other GLContexts created by this library + GLContext cur = getCurrent(); + if (cur != null && cur != this) { + lastContext = cur; + setCurrent(null); + } + return super.makeCurrent(); + } + + public void release() throws GLException { + super.release(); + setCurrent(lastContext); + lastContext = null; + } + + protected int makeCurrentImpl() throws GLException { + if (firstMakeCurrent) { + firstMakeCurrent = false; + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } + + protected void releaseImpl() throws GLException { + } + + protected void destroyImpl() throws GLException { + created = false; + GLContextShareSet.contextDestroyed(this); + } + + public boolean isCreated() { + return created; + } + + // Need to provide the display connection to extension querying APIs + static class Drawable extends X11GLXDrawable { + Drawable(GLDrawableFactory factory, NativeWindow comp) { + super(factory, comp, true); + } + + public GLContext createContext(GLContext shareWith) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + throw new GLException("Should not call this"); + } + + public int getHeight() { + throw new GLException("Should not call this"); + } + + public void setSize(int width, int height) { + throw new GLException("Should not call this"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java new file mode 100755 index 000000000..f10bd38c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.NullWindow; + + +public class X11ExternalGLXDrawable extends X11GLXDrawable { + private int fbConfigID; + private int renderType; + + private X11ExternalGLXDrawable(GLDrawableFactory factory, NativeWindow component, int renderType) { + super(factory, component, true); + + this.renderType = renderType; + + // Need GLXFBConfig ID in order to properly create new contexts + // on this drawable + X11GLXGraphicsConfiguration cfg = (X11GLXGraphicsConfiguration) component.getGraphicsConfiguration(); + fbConfigID = cfg.getFBConfigID(); + } + + protected static X11ExternalGLXDrawable create(GLDrawableFactory factory, GLProfile glp) { + ((GLDrawableFactoryImpl)factory).lockToolkit(); + try { + long context = GLX.glXGetCurrentContext(); + if (context == 0) { + throw new GLException("Error: current context null"); + } + long display = GLX.glXGetCurrentDisplay(); + if (display == 0) { + throw new GLException("Error: current display null"); + } + long drawable = GLX.glXGetCurrentDrawable(); + if (drawable == 0) { + throw new GLException("Error: attempted to make an external GLDrawable without a drawable current"); + } + int[] val = new int[1]; + GLX.glXQueryContext(display, context, GLX.GLX_SCREEN, val, 0); + X11GraphicsScreen x11Screen = (X11GraphicsScreen) X11GraphicsScreen.createScreenDevice(display, val[0]); + + GLX.glXQueryContext(display, context, GLX.GLX_FBCONFIG_ID, val, 0); + X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); + + int w, h; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_WIDTH, val, 0); + w=val[0]; + GLX.glXQueryDrawable(display, drawable, GLX.GLX_HEIGHT, val, 0); + h=val[0]; + + GLX.glXQueryContext(display, context, GLX.GLX_RENDER_TYPE, val, 0); + if ((val[0] & GLX.GLX_RGBA_TYPE) == 0) { + if (DEBUG) { + System.err.println("X11ExternalGLXDrawable: WARNING: forcing GLX_RGBA_TYPE for newly created contexts (current 0x"+Integer.toHexString(val[0])+")"); + } + } + NullWindow nw = new NullWindow(cfg); + nw.setSurfaceHandle(drawable); + nw.setSize(w, h); + return new X11ExternalGLXDrawable(factory, nw, GLX.GLX_RGBA_TYPE); + } finally { + ((GLDrawableFactoryImpl)factory).unlockToolkit(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new Context(this, shareWith); + } + + public void setSize(int newWidth, int newHeight) { + throw new GLException("Should not call this"); + } + + public int getWidth() { + return getNativeWindow().getWidth(); + } + + public int getHeight() { + return getNativeWindow().getHeight(); + } + + class Context extends X11GLXContext { + Context(X11GLXDrawable drawable, GLContext shareWith) { + super(drawable, shareWith); + } + + protected void create() { + createContext(true); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java new file mode 100644 index 000000000..dce25978c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -0,0 +1,582 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import java.nio.*; +import java.util.*; +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.glx.*; +import com.jogamp.nativewindow.impl.x11.*; +import com.jogamp.gluegen.runtime.ProcAddressTable; + +public abstract class X11GLXContext extends GLContextImpl { + protected long context; + private boolean glXQueryExtensionsStringInitialized; + private boolean glXQueryExtensionsStringAvailable; + private static final Map/*<String, String>*/ functionNameMap; + private static final Map/*<String, String>*/ extensionNameMap; + private GLXExt glXExt; + // Table that holds the addresses of the native C-language entry points for + // GLX extension functions. + private GLXExtProcAddressTable glXExtProcAddressTable; + + static { + functionNameMap = new HashMap(); + functionNameMap.put("glAllocateMemoryNV", "glXAllocateMemoryNV"); + functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); + + extensionNameMap = new HashMap(); + extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer"); + extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough + } + + public X11GLXContext(GLDrawableImpl drawable, GLDrawableImpl drawableRead, + GLContext shareWith) { + super(drawable, drawableRead, shareWith); + } + + public X11GLXContext(GLDrawableImpl drawable, + GLContext shareWith) { + this(drawable, null, shareWith); + } + + public final ProcAddressTable getPlatformExtProcAddressTable() { + return getGLXExtProcAddressTable(); + } + + public final GLXExtProcAddressTable getGLXExtProcAddressTable() { + return glXExtProcAddressTable; + } + + public Object getPlatformGLExtensions() { + return getGLXExt(); + } + + public GLXExt getGLXExt() { + if (glXExt == null) { + glXExt = new GLXExtImpl(this); + } + return glXExt; + } + + protected Map/*<String, String>*/ getFunctionNameMap() { return functionNameMap; } + + protected Map/*<String, String>*/ getExtensionNameMap() { return extensionNameMap; } + + protected boolean glXMakeContextCurrent(long dpy, long writeDrawable, long readDrawable, long ctx) { + boolean res = false; + + try { + res = GLX.glXMakeContextCurrent(dpy, writeDrawable, readDrawable, ctx); + } catch (RuntimeException re) { + if(DEBUG) { + System.err.println("X11GLXContext.glXMakeContextCurrent failed: "+re+", with "+ + "dpy "+toHexString(dpy)+ + ", write "+toHexString(writeDrawable)+ + ", read "+toHexString(readDrawable)+ + ", ctx "+toHexString(ctx)); + re.printStackTrace(); + } + } + return res; + } + + protected void destroyContextARBImpl(long _context) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, _context); + } + + protected long createContextARBImpl(long share, boolean direct, int ctp, int major, int minor) { + X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + GLXExt glXExt; + if(null==factory.getSharedContext()) { + glXExt = getGLXExt(); + } else { + glXExt = ((X11GLXContext)factory.getSharedContext()).getGLXExt(); + } + + boolean ctBwdCompat = 0 != ( CTX_PROFILE_COMPAT & ctp ) ; + boolean ctFwdCompat = 0 != ( CTX_OPTION_FORWARD & ctp ) ; + boolean ctDebug = 0 != ( CTX_OPTION_DEBUG & ctp ) ; + + long _context=0; + + int attribs[] = { + /* 0 */ GLX.GLX_CONTEXT_MAJOR_VERSION_ARB, major, + /* 2 */ GLX.GLX_CONTEXT_MINOR_VERSION_ARB, minor, + /* 4 */ GLX.GLX_RENDER_TYPE, GLX.GLX_RGBA_TYPE, // default + /* 6 */ GLX.GLX_CONTEXT_FLAGS_ARB, 0, + /* 8 */ 0, 0, + /* 10 */ 0 + }; + + if ( major > 3 || major == 3 && minor >= 2 ) { + // FIXME: Verify with a None drawable binding (default framebuffer) + attribs[8+0] = GLX.GLX_CONTEXT_PROFILE_MASK_ARB; + if( ctBwdCompat ) { + attribs[8+1] = GLX.GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } else { + attribs[8+1] = GLX.GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + } + } + + if ( major >= 3 ) { + if( !ctBwdCompat && ctFwdCompat ) { + attribs[6+1] |= GLX.GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if( ctDebug) { + attribs[6+1] |= GLX.GLX_CONTEXT_DEBUG_BIT_ARB; + } + } + + try { + _context = glXExt.glXCreateContextAttribsARB(display, config.getFBConfig(), share, direct, attribs, 0); + } catch (RuntimeException re) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB glXCreateContextAttribsARB failed: "+re+", with "+getGLVersion(null, major, minor, ctp, "@creation")); + re.printStackTrace(); + } + } + if(0==_context) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB couldn't create "+getGLVersion(null, major, minor, ctp, "@creation")); + } + } else { + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + _context)) { + if(DEBUG) { + System.err.println("X11GLXContext.createContextARB couldn't make current "+getGLVersion(null, major, minor, ctp, "@creation")); + } + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, _context); + _context = 0; + } + } + return _context; + } + + /** + * Creates and initializes an appropriate OpenGL context. Should only be + * called by {@link #create()}. + * Note: The direct parameter may be overwritten by the direct state of a shared context. + */ + protected void createContext(boolean direct) { + if(0!=context) { + throw new GLException("context is not null: "+context); + } + X11GLXDrawableFactory factory = (X11GLXDrawableFactory)drawable.getFactoryImpl(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + long display = config.getScreen().getDevice().getHandle(); + + X11GLXContext other = (X11GLXContext) GLContextShareSet.getShareContext(this); + long share = 0; + if (other != null) { + share = other.getContext(); + if (share == 0) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context"); + } + direct = GLX.glXIsDirect(display, share); + } + + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + GLProfile glp = glCaps.getGLProfile(); + isVendorATI = factory.isVendorATI(); + + if(config.getFBConfigID()<0) { + // not able to use FBConfig + if(glp.isGL3()) { + throw new GLException("Unable to create OpenGL >= 3.1 context"); + } + context = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct); + if (context == 0) { + throw new GLException("Unable to create context(0)"); + } + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + return; + } + + int minor[] = new int[1]; + int major[] = new int[1]; + int ctp[] = new int[1]; + boolean createContextARBTried = false; + + // utilize the shared context's GLXExt in case it was using the ARB method and it already exists + if(null!=factory.getSharedContext() && factory.getSharedContext().isCreatedWithARBMethod()) { + if(DEBUG) { + System.err.println("X11GLXContext.createContext using shared Context: "+factory.getSharedContext()); + } + context = createContextARB(share, direct, major, minor, ctp); + createContextARBTried = true; + } + + long temp_context = 0; + if(0==context) { + // To use GLX_ARB_create_context, we have to make a temp context current, + // so we are able to use GetProcAddress + temp_context = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct); + if (temp_context == 0) { + throw new GLException("Unable to create temp OpenGL context(1)"); + } + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + temp_context)) { + throw new GLException("Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); // use GL_VERSION + + if( createContextARBTried || + !isFunctionAvailable("glXCreateContextAttribsARB") || + !isExtensionAvailable("GLX_ARB_create_context") ) { + if(glp.isGL3()) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("Unable to create OpenGL >= 3.1 context (failed GLX_ARB_create_context), GLProfile "+glp+", Drawable "+drawable); + } + + // continue with temp context for GL < 3.0 + context = temp_context; + return; + } + context = createContextARB(share, direct, major, minor, ctp); + createContextARBTried=true; + } + + if(0!=context) { + if(0!=temp_context) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Cannot make previous verified context current"); + } + } + } else { + if(glp.isGL3()) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("X11GLXContext.createContext failed, but context > GL2 requested "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")+", "); + } + if(DEBUG) { + System.err.println("X11GLXContext.createContext failed, fall back to !ARB context "+getGLVersion(null, major[0], minor[0], ctp[0], "@creation")); + } + + // continue with temp context for GL <= 3.0 + context = temp_context; + if (!glXMakeContextCurrent(display, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + glXMakeContextCurrent(display, 0, 0, 0); + GLX.glXDestroyContext(display, temp_context); + throw new GLException("Error making context(1) current: display "+toHexString(display)+", context "+toHexString(context)+", drawable "+drawable); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected int makeCurrentImpl() throws GLException { + int lockRes = drawable.lockSurface(); + boolean exceptionOccurred = false; + try { + if (lockRes == NativeWindow.LOCK_SURFACE_NOT_READY) { + return CONTEXT_NOT_CURRENT; + } + return makeCurrentImplAfterLock(); + } catch (RuntimeException e) { + exceptionOccurred = true; + throw e; + } finally { + if (exceptionOccurred || + (isOptimizable() && lockRes != NativeWindow.LOCK_SURFACE_NOT_READY) && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + // Note: Usually the surface shall be locked within [makeCurrent .. swap .. release] + protected void releaseImpl() throws GLException { + try { + releaseImplAfterLock(); + } finally { + if (!isOptimizable() && drawable.isSurfaceLocked()) { + drawable.unlockSurface(); + } + } + } + + protected int makeCurrentImplAfterLock() throws GLException { + long dpy = drawable.getNativeWindow().getDisplayHandle(); + + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (drawable.getNativeWindow().getSurfaceHandle() == 0) { + throw new GLException("drawable not properly initialized: "+drawable); + } + boolean created = false; + if (context == 0) { + create(); + created = true; + GLContextShareSet.contextCreated(this); + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Created GL context for " + getClass().getName()); + } + } + + if (GLX.glXGetCurrentContext() != context) { + + if (!glXMakeContextCurrent(dpy, + drawable.getNativeWindow().getSurfaceHandle(), + drawableRead.getNativeWindow().getSurfaceHandle(), + context)) { + throw new GLException("Error making context current: "+this); + } + if (DEBUG && (VERBOSE || created)) { + System.err.println(getThreadName() + ": glXMakeCurrent(display " + + toHexString(dpy)+ + ", drawable " + toHexString(drawable.getNativeWindow().getSurfaceHandle()) + + ", drawableRead " + toHexString(drawableRead.getNativeWindow().getSurfaceHandle()) + + ", context " + toHexString(context) + ") succeeded"); + } + } + + if (created) { + setGLFunctionAvailability(false, -1, -1, CTX_PROFILE_COMPAT|CTX_OPTION_ANY); + return CONTEXT_CURRENT_NEW; + } + return CONTEXT_CURRENT; + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void releaseImplAfterLock() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (!glXMakeContextCurrent(drawable.getNativeWindow().getDisplayHandle(), 0, 0, 0)) { + throw new GLException("Error freeing OpenGL context"); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void destroyImpl() throws GLException { + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + if (context != 0) { + if (DEBUG) { + System.err.println("glXDestroyContext(" + + toHexString(drawable.getNativeWindow().getDisplayHandle()) + + ", " + + toHexString(context) + ")"); + } + GLX.glXDestroyContext(drawable.getNativeWindow().getDisplayHandle(), context); + if (DEBUG) { + System.err.println("!!! Destroyed OpenGL context " + context); + } + context = 0; + GLContextShareSet.contextDestroyed(this); + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + public boolean isCreated() { + return (context != 0); + } + + public void copy(GLContext source, int mask) throws GLException { + long dst = getContext(); + long src = ((X11GLXContext) source).getContext(); + if (src == 0) { + throw new GLException("Source OpenGL context has not been created"); + } + if (dst == 0) { + throw new GLException("Destination OpenGL context has not been created"); + } + if (drawable.getNativeWindow().getDisplayHandle() == 0) { + throw new GLException("Connection to X display not yet set up"); + } + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + GLX.glXCopyContext(drawable.getNativeWindow().getDisplayHandle(), src, dst, mask); + // Should check for X errors and raise GLException + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + protected void updateGLProcAddressTable(int major, int minor, int ctp) { + if (DEBUG) { + System.err.println(getThreadName() + ": !!! Initializing GLX extension address table"); + } + glXQueryExtensionsStringInitialized = false; + glXQueryExtensionsStringAvailable = false; + + if (glXExtProcAddressTable == null) { + // FIXME: cache ProcAddressTables by capability bits so we can + // share them among contexts with the same capabilities + glXExtProcAddressTable = new GLXExtProcAddressTable(); + } + resetProcAddressTable(getGLXExtProcAddressTable()); + super.updateGLProcAddressTable(major, minor, ctp); + } + + public synchronized String getPlatformExtensionsString() { + if (!glXQueryExtensionsStringInitialized) { + glXQueryExtensionsStringAvailable = + getDrawableImpl().getDynamicLookupHelper().dynamicLookupFunction("glXQueryExtensionsString") != 0; + glXQueryExtensionsStringInitialized = true; + } + if (glXQueryExtensionsStringAvailable) { + GLDrawableFactoryImpl factory = getDrawableImpl().getFactoryImpl(); + factory.lockToolkit(); + try { + String ret = GLX.glXQueryExtensionsString(drawable.getNativeWindow().getDisplayHandle(), + drawable.getNativeWindow().getScreenIndex()); + if (DEBUG) { + System.err.println("!!! GLX extensions: " + ret); + } + return ret; + } finally { + factory.unlockToolkit(); + } + } else { + return ""; + } + } + + public boolean isExtensionAvailable(String glExtensionName) { + if (glExtensionName.equals("GL_ARB_pbuffer") || + glExtensionName.equals("GL_ARB_pixel_format")) { + return getGLDrawable().getFactory().canCreateGLPbuffer( + drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getScreen().getDevice() ); + } + return super.isExtensionAvailable(glExtensionName); + } + + + private int hasSwapIntervalSGI = 0; + + protected void setSwapIntervalImpl(int interval) { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + GLCapabilities glCaps = (GLCapabilities) config.getChosenCapabilities(); + if(!glCaps.isOnscreen()) return; + + getDrawableImpl().getFactoryImpl().lockToolkit(); + try { + GLXExt glXExt = getGLXExt(); + if(0==hasSwapIntervalSGI) { + try { + hasSwapIntervalSGI = glXExt.isExtensionAvailable("GLX_SGI_swap_control")?1:-1; + } catch (Throwable t) { hasSwapIntervalSGI=1; } + } + if (hasSwapIntervalSGI>0) { + try { + if( 0 == glXExt.glXSwapIntervalSGI(interval) ) { + currentSwapInterval = interval; + } + } catch (Throwable t) { hasSwapIntervalSGI=-1; } + } + } finally { + getDrawableImpl().getFactoryImpl().unlockToolkit(); + } + } + + public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { + return getGLXExt().glXAllocateMemoryNV(arg0, arg1, arg2, arg3); + } + + public int getOffscreenContextPixelDataType() { + throw new GLException("Should not call this"); + } + + public int getOffscreenContextReadBuffer() { + throw new GLException("Should not call this"); + } + + public boolean offscreenImageNeedsVerticalFlip() { + throw new GLException("Should not call this"); + } + + public void bindPbufferToTexture() { + throw new GLException("Should not call this"); + } + + public void releasePbufferFromTexture() { + throw new GLException("Should not call this"); + } + + public boolean isOptimizable() { + return (super.isOptimizable() && !isVendorATI); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + public long getContext() { + return context; + } + + private boolean isVendorATI = false; + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java new file mode 100644 index 000000000..95dfc0a1c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.os.DynamicLookupHelper; + +public abstract class X11GLXDrawable extends GLDrawableImpl { + protected X11GLXDrawable(GLDrawableFactory factory, NativeWindow comp, boolean realized) { + super(factory, comp, realized); + } + + public DynamicLookupHelper getDynamicLookupHelper() { + return (X11GLXDrawableFactory) getFactoryImpl() ; + } + + protected void setRealizedImpl() { + if(!realized) { + return; // nothing to do + } + + if(NativeWindow.LOCK_SURFACE_NOT_READY == lockSurface()) { + throw new GLException("X11GLXDrawable.setRealized(true): lockSurface - surface not ready"); + } + try { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration)getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + config.updateGraphicsConfiguration(); + + if (DEBUG) { + System.err.println("!!! X11GLXDrawable.setRealized(true): "+config); + } + } finally { + unlockSurface(); + } + } + + protected void swapBuffersImpl() { + boolean didLock = false; + if (!isSurfaceLocked()) { + // Usually the surface shall be locked within [makeCurrent .. swap .. release] + if (lockSurface() == NativeWindow.LOCK_SURFACE_NOT_READY) { + return; + } + didLock = true; + } + try { + GLX.glXSwapBuffers(component.getDisplayHandle(), component.getSurfaceHandle()); + } finally { + if (didLock) { + unlockSurface(); + } + } + } + + //--------------------------------------------------------------------------- + // Internals only below this point + // +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java new file mode 100644 index 000000000..d8e5f7646 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.common.os.DynamicLookupHelper; +import java.nio.*; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.gluegen.runtime.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.common.JogampRuntimeException; +import com.jogamp.common.util.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { + + public X11GLXDrawableFactory() { + super(); + // Must initialize GLX support eagerly in case a pbuffer is the + // first thing instantiated + GLProcAddressHelper.resetProcAddressTable(GLX.getGLXProcAddressTable(), this); + // Register our GraphicsConfigurationFactory implementations + // The act of constructing them causes them to be registered + new X11GLXGraphicsConfigurationFactory(); + try { + ReflectionUtil.createInstance("com.jogamp.opengl.impl.x11.glx.awt.X11AWTGLXGraphicsConfigurationFactory", + new Object[] {}); + } catch (JogampRuntimeException jre) { /* n/a .. */ } + + X11GraphicsDevice sharedDevice = new X11GraphicsDevice(X11Util.createThreadLocalDisplay(null)); + vendorName = GLXUtil.getVendorName(sharedDevice.getHandle()); + isVendorATI = GLXUtil.isVendorATI(vendorName); + isVendorNVIDIA = GLXUtil.isVendorNVIDIA(vendorName); + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(sharedDevice.getHandle()); // ATI hack .. + } + sharedScreen = new X11GraphicsScreen(sharedDevice, 0); + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + try{ + sharedDrawable = new X11DummyGLXDrawable(sharedScreen, this, null); + X11GLXContext ctx = (X11GLXContext) sharedDrawable.createContext(null); + ctx.makeCurrent(); + ctx.release(); + sharedContext = ctx; + }finally{ + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } + if(null==sharedContext) { + throw new GLException("Couldn't init shared resources"); + } + if (DEBUG) { + System.err.println("!!! Vendor: "+vendorName+", ATI: "+isVendorATI+", NV: "+isVendorNVIDIA); + System.err.println("!!! SharedScreen: "+sharedScreen); + System.err.println("!!! SharedContext: "+sharedContext); + } + } + + private X11GraphicsScreen sharedScreen; + private String vendorName; + private boolean isVendorATI; + private boolean isVendorNVIDIA; + + public String getVendorName() { return vendorName; } + public boolean isVendorATI() { return isVendorATI; } + public boolean isVendorNVIDIA() { return isVendorNVIDIA; } + + private X11DummyGLXDrawable sharedDrawable=null; + private X11GLXContext sharedContext=null; + + protected final GLDrawableImpl getSharedDrawable() { + validate(); + return sharedDrawable; + } + + protected final GLContextImpl getSharedContext() { + validate(); + return sharedContext; + } + + public void shutdown() { + super.shutdown(); + if (DEBUG) { + System.err.println("!!! Shutdown Shared:"); + System.err.println("!!! CTX : "+sharedContext); + System.err.println("!!! Drawable: "+sharedDrawable); + System.err.println("!!! Screen : "+sharedScreen); + Exception e = new Exception("Debug"); + e.printStackTrace(); + } + if(null!=sharedContext) { + sharedContext.destroy(); // implies release, if current + } + if(null!=sharedDrawable) { + sharedDrawable.destroy(); + } + if(null!=sharedScreen) { + X11GraphicsDevice sharedDevice = (X11GraphicsDevice) sharedScreen.getDevice(); + if(null!=sharedDevice) { + X11Util.closeThreadLocalDisplay(null); + } + sharedScreen = null; + } + X11Util.shutdown( !isVendorATI(), DEBUG ); + } + + public GLDrawableImpl createOnscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + return new X11OnscreenGLXDrawable(this, target); + } + + protected GLDrawableImpl createOffscreenDrawable(NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + return new X11OffscreenGLXDrawable(this, target); + } + + public boolean canCreateGLPbuffer(AbstractGraphicsDevice device) { + validate(); + return glxVersionGreaterEqualThan(device, 1, 3); + } + + private boolean glxVersionsQueried = false; + private int glxVersionMajor=0, glxVersionMinor=0; + public boolean glxVersionGreaterEqualThan(AbstractGraphicsDevice device, int majorReq, int minorReq) { + validate(); + if (!glxVersionsQueried) { + if(null == device) { + device = (X11GraphicsDevice) sharedScreen.getDevice(); + } + if(null == device) { + throw new GLException("FIXME: No AbstractGraphicsDevice (passed or shared-device"); + } + long display = device.getHandle(); + int[] major = new int[1]; + int[] minor = new int[1]; + + GLXUtil.getGLXVersion(display, major, minor); + if (DEBUG) { + System.err.println("!!! GLX version: major " + major[0] + + ", minor " + minor[0]); + } + + glxVersionMajor = major[0]; + glxVersionMinor = minor[0]; + glxVersionsQueried = true; + } + return ( glxVersionMajor > majorReq ) || ( glxVersionMajor == majorReq && glxVersionMinor >= minorReq ) ; + } + + protected GLDrawableImpl createGLPbufferDrawableImpl(final NativeWindow target) { + validate(); + if (target == null) { + throw new IllegalArgumentException("Null target"); + } + + GLDrawableImpl pbufferDrawable; + + /** + * Due to the ATI Bug https://bugzilla.mozilla.org/show_bug.cgi?id=486277, + * we need to have a context current on the same Display to create a PBuffer. + * The dummy context shall also use the same Display, + * since switching Display in this regard is another ATI bug. + */ + boolean usedSharedContext=false; + if( isVendorATI() && null == GLContext.getCurrent() ) { + sharedContext.makeCurrent(); + usedSharedContext=true; + } + if( isVendorATI() ) { + X11Util.markGlobalDisplayUndeletable(target.getDisplayHandle()); // ATI hack .. + } + try { + pbufferDrawable = new X11PbufferGLXDrawable(this, target); + } finally { + if(usedSharedContext) { + sharedContext.release(); + } + } + return pbufferDrawable; + } + + + protected NativeWindow createOffscreenWindow(GLCapabilities capabilities, GLCapabilitiesChooser chooser, int width, int height) { + validate(); + NullWindow nw = null; + X11Lib.XLockDisplay(sharedScreen.getDevice().getHandle()); + try{ + nw = new NullWindow(X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capabilities, chooser, sharedScreen)); + }finally{ + X11Lib.XUnlockDisplay(sharedScreen.getDevice().getHandle()); + } + if(nw != null) { + nw.setSize(width, height); + } + return nw; + } + + public GLContext createExternalGLContext() { + validate(); + return X11ExternalGLXContext.create(this, null); + } + + public boolean canCreateExternalGLDrawable(AbstractGraphicsDevice device) { + validate(); + return canCreateGLPbuffer(device); + } + + public GLDrawable createExternalGLDrawable() { + validate(); + return X11ExternalGLXDrawable.create(this, null); + } + + public void loadGLULibrary() { + validate(); + X11Lib.dlopen("/usr/lib/libGLU.so"); + } + + public long dynamicLookupFunction(String glFuncName) { + long res = 0; + res = GLX.glXGetProcAddressARB(glFuncName); + if (res == 0) { + // GLU routines aren't known to the OpenGL function lookup + res = X11Lib.dlsym(glFuncName); + } + return res; + } + + public boolean canCreateContextOnJava2DSurface(AbstractGraphicsDevice device) { + validate(); + return false; + } + + public GLContext createContextOnJava2DSurface(Object graphics, GLContext shareWith) + throws GLException { + throw new GLException("Unimplemented on this platform"); + } + + //---------------------------------------------------------------------- + // Gamma-related functionality + // + + private boolean gotGammaRampLength; + private int gammaRampLength; + protected synchronized int getGammaRampLength() { + if (gotGammaRampLength) { + return gammaRampLength; + } + + long display = sharedScreen.getDevice().getHandle(); + + X11Lib.XLockDisplay(display); + try { + int[] size = new int[1]; + boolean res = X11Lib.XF86VidModeGetGammaRampSize(display, + X11Lib.DefaultScreen(display), + size, 0); + if (!res) { + return 0; + } + gotGammaRampLength = true; + gammaRampLength = size[0]; + return gammaRampLength; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected boolean setGammaRamp(float[] ramp) { + int len = ramp.length; + short[] rampData = new short[len]; + for (int i = 0; i < len; i++) { + rampData[i] = (short) (ramp[i] * 65535); + } + + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + boolean res = X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), + rampData.length, + rampData, 0, + rampData, 0, + rampData, 0); + return res; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected Buffer getGammaRamp() { + int size = getGammaRampLength(); + ShortBuffer rampData = ShortBuffer.wrap(new short[3 * size]); + rampData.position(0); + rampData.limit(size); + ShortBuffer redRampData = rampData.slice(); + rampData.position(size); + rampData.limit(2 * size); + ShortBuffer greenRampData = rampData.slice(); + rampData.position(2 * size); + rampData.limit(3 * size); + ShortBuffer blueRampData = rampData.slice(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + boolean res = X11Lib.XF86VidModeGetGammaRamp(display, + X11Lib.DefaultScreen(display), + size, + redRampData, + greenRampData, + blueRampData); + if (!res) { + return null; + } + return rampData; + } finally { + X11Lib.XUnlockDisplay(display); + } + } + + protected void resetGammaRamp(Buffer originalGammaRamp) { + if (originalGammaRamp == null) + return; // getGammaRamp failed originally + ShortBuffer rampData = (ShortBuffer) originalGammaRamp; + int capacity = rampData.capacity(); + if ((capacity % 3) != 0) { + throw new IllegalArgumentException("Must not be the original gamma ramp"); + } + int size = capacity / 3; + rampData.position(0); + rampData.limit(size); + ShortBuffer redRampData = rampData.slice(); + rampData.position(size); + rampData.limit(2 * size); + ShortBuffer greenRampData = rampData.slice(); + rampData.position(2 * size); + rampData.limit(3 * size); + ShortBuffer blueRampData = rampData.slice(); + long display = sharedScreen.getDevice().getHandle(); + X11Lib.XLockDisplay(display); + try { + X11Lib.XF86VidModeSetGammaRamp(display, + X11Lib.DefaultScreen(display), + size, + redRampData, + greenRampData, + blueRampData); + } finally { + X11Lib.XUnlockDisplay(display); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java new file mode 100644 index 000000000..35daf0ae0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public static final int MAX_ATTRIBS = 128; + private long fbConfig; + private int fbConfigID; + private GLCapabilitiesChooser chooser; + + public X11GLXGraphicsConfiguration(X11GraphicsScreen screen, + GLCapabilities capsChosen, GLCapabilities capsRequested, GLCapabilitiesChooser chooser, + XVisualInfo info, long fbcfg, int fbcfgID) { + super(screen, capsChosen, capsRequested, info); + this.chooser=chooser; + fbConfig = fbcfg; + fbConfigID = fbcfgID; + } + + public static X11GLXGraphicsConfiguration create(GLProfile glp, X11GraphicsScreen x11Screen, int fbcfgID) { + long display = x11Screen.getDevice().getHandle(); + if(0==display) { + throw new GLException("Display null of "+x11Screen); + } + int screen = x11Screen.getIndex(); + long fbcfg = glXFBConfigID2FBConfig(display, screen, fbcfgID); + if(0==fbcfg) { + throw new GLException("FBConfig null of "+toHexString(fbcfgID)); + } + if(null==glp) { + glp = GLProfile.getDefault(); + } + GLCapabilities caps = GLXFBConfig2GLCapabilities(glp, display, fbcfg, true, true, true, GLXUtil.isMultisampleAvailable(display)); + if(null==caps) { + throw new GLException("GLCapabilities null of "+toHexString(fbcfg)); + } + XVisualInfo xvi = GLX.glXGetVisualFromFBConfigCopied(display, fbcfg); + if(null==xvi) { + throw new GLException("XVisualInfo null of "+toHexString(fbcfg)); + } + return new X11GLXGraphicsConfiguration(x11Screen, caps, caps, new DefaultGLCapabilitiesChooser(), xvi, fbcfg, fbcfgID); + } + + public Object clone() { + return super.clone(); + } + + public long getFBConfig() { return fbConfig; } + public int getFBConfigID() { return fbConfigID; } + + protected void updateGraphicsConfiguration() { + X11GLXGraphicsConfiguration newConfig = (X11GLXGraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(getScreen().getDevice()).chooseGraphicsConfiguration(getRequestedCapabilities(), + chooser, + getScreen()); + if(null!=newConfig) { + // FIXME: setScreen( ... ); + setXVisualInfo(newConfig.getXVisualInfo()); + setChosenCapabilities(newConfig.getChosenCapabilities()); + fbConfig = newConfig.getFBConfig(); + fbConfigID = newConfig.getFBConfigID(); + if(DEBUG) { + System.err.println("!!! updateGraphicsConfiguration: "+this); + } + } + } + + private static int nonZeroOrDontCare(int value) { + return value != 0 ? value : (int)GLX.GLX_DONT_CARE ; + } + + public static int[] GLCapabilities2AttribList(GLCapabilities caps, + boolean forFBAttr, + boolean isMultisampleAvailable, + long display, + int screen) + { + int colorDepth = (caps.getRedBits() + + caps.getGreenBits() + + caps.getBlueBits()); + if (colorDepth < 15) { + throw new GLException("Bit depths < 15 (i.e., non-true-color) not supported"); + } + int[] res = new int[MAX_ATTRIBS]; + int idx = 0; + + if (forFBAttr) { + res[idx++] = GLX.GLX_DRAWABLE_TYPE; + res[idx++] = caps.isOnscreen() ? ( GLX.GLX_WINDOW_BIT ) : ( caps.isPBuffer() ? GLX.GLX_PBUFFER_BIT : GLX.GLX_PIXMAP_BIT ) ; + } + + if (forFBAttr) { + res[idx++] = GLX.GLX_RENDER_TYPE; + res[idx++] = GLX.GLX_RGBA_BIT; + } else { + res[idx++] = GLX.GLX_RGBA; + } + + // FIXME: Still a bug is Mesa: PBUFFER && GLX_STEREO==GL_FALSE ? + if (forFBAttr) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + res[idx++] = caps.getDoubleBuffered()?GL.GL_TRUE:GL.GL_FALSE; + res[idx++] = GLX.GLX_STEREO; + res[idx++] = caps.getStereo()?GL.GL_TRUE:GL.GL_FALSE; + res[idx++] = GLX.GLX_TRANSPARENT_TYPE; + res[idx++] = caps.isBackgroundOpaque()?GLX.GLX_NONE:GLX.GLX_TRANSPARENT_RGB; + if(!caps.isBackgroundOpaque()) { + res[idx++] = GLX.GLX_TRANSPARENT_RED_VALUE; + res[idx++] = caps.getTransparentRedValue()>=0?caps.getTransparentRedValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_GREEN_VALUE; + res[idx++] = caps.getTransparentGreenValue()>=0?caps.getTransparentGreenValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_BLUE_VALUE; + res[idx++] = caps.getTransparentBlueValue()>=0?caps.getTransparentBlueValue():(int)GLX.GLX_DONT_CARE; + res[idx++] = GLX.GLX_TRANSPARENT_ALPHA_VALUE; + res[idx++] = caps.getTransparentAlphaValue()>=0?caps.getTransparentAlphaValue():(int)GLX.GLX_DONT_CARE; + } + } else { + if (caps.getDoubleBuffered()) { + res[idx++] = GLX.GLX_DOUBLEBUFFER; + } + if (caps.getStereo()) { + res[idx++] = GLX.GLX_STEREO; + } + } + + res[idx++] = GLX.GLX_RED_SIZE; + res[idx++] = caps.getRedBits(); + res[idx++] = GLX.GLX_GREEN_SIZE; + res[idx++] = caps.getGreenBits(); + res[idx++] = GLX.GLX_BLUE_SIZE; + res[idx++] = caps.getBlueBits(); + res[idx++] = GLX.GLX_ALPHA_SIZE; + res[idx++] = caps.getAlphaBits(); + res[idx++] = GLX.GLX_DEPTH_SIZE; + res[idx++] = caps.getDepthBits(); + if (caps.getStencilBits() > 0) { + res[idx++] = GLX.GLX_STENCIL_SIZE; + res[idx++] = caps.getStencilBits(); + } + if (caps.getAccumRedBits() > 0 || + caps.getAccumGreenBits() > 0 || + caps.getAccumBlueBits() > 0 || + caps.getAccumAlphaBits() > 0) { + res[idx++] = GLX.GLX_ACCUM_RED_SIZE; + res[idx++] = caps.getAccumRedBits(); + res[idx++] = GLX.GLX_ACCUM_GREEN_SIZE; + res[idx++] = caps.getAccumGreenBits(); + res[idx++] = GLX.GLX_ACCUM_BLUE_SIZE; + res[idx++] = caps.getAccumBlueBits(); + res[idx++] = GLX.GLX_ACCUM_ALPHA_SIZE; + res[idx++] = caps.getAccumAlphaBits(); + } + if (isMultisampleAvailable && caps.getSampleBuffers()) { + res[idx++] = GLX.GLX_SAMPLE_BUFFERS; + res[idx++] = GL.GL_TRUE; + res[idx++] = GLX.GLX_SAMPLES; + res[idx++] = caps.getNumSamples(); + } + if (caps.isPBuffer()) { + if (caps.getPbufferFloatingPointBuffers()) { + String glXExtensions = GLX.glXQueryExtensionsString(display, screen); + if (glXExtensions == null || + glXExtensions.indexOf("GLX_NV_float_buffer") < 0) { + throw new GLException("Floating-point pbuffers on X11 currently require NVidia hardware: "+glXExtensions); + } + res[idx++] = GLXExt.GLX_FLOAT_COMPONENTS_NV; + res[idx++] = GL.GL_TRUE; + } + } + res[idx++] = 0; + return res; + } + + // FBConfig + + public static boolean GLXFBConfigValid(long display, long fbcfg) { + int[] tmp = new int[1]; + if(GLX.GLX_BAD_ATTRIBUTE == GLX.glXGetFBConfigAttrib(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0)) { + return false; + } + return true; + } + + public static boolean GLXFBConfigDrawableTypeVerify(int val, boolean onscreen, boolean usePBuffer) { + boolean res; + + if ( onscreen ) { + res = ( 0 != (val & GLX.GLX_WINDOW_BIT) ) ; + } else { + if ( usePBuffer ) { + res = ( 0 != (val & GLX.GLX_PBUFFER_BIT) ) ; + } else { + res = ( 0 != (val & GLX.GLX_PIXMAP_BIT) ) ; + } + } + + return res; + } + + public static GLCapabilities GLXFBConfig2GLCapabilities(GLProfile glp, long display, long fbcfg, + boolean relaxed, boolean onscreen, boolean usePBuffer, boolean isMultisampleEnabled) { + int[] tmp = new int[1]; + int val; + val = glXGetFBConfig(display, fbcfg, GLX.GLX_RENDER_TYPE, tmp, 0); + if (val != GLX.GLX_RGBA_BIT) { + if(DEBUG) { + System.err.println("FBConfig ("+toHexString(fbcfg)+") does not support RGBA: "+toHexString(val)); + } + return null; + } + GLCapabilities res = new GLCapabilities(glp); + + val = glXGetFBConfig(display, fbcfg, GLX.GLX_DRAWABLE_TYPE, tmp, 0); + if(GLXFBConfigDrawableTypeVerify(val, onscreen, usePBuffer)) { + res.setOnscreen(onscreen); + res.setPBuffer(usePBuffer); + } else if(relaxed) { + res.setOnscreen( 0 != (val & GLX.GLX_WINDOW_BIT) ); + res.setPBuffer ( 0 != (val & GLX.GLX_PBUFFER_BIT) ); + } else { + if(DEBUG) { + System.err.println("FBConfig ("+toHexString(fbcfg)+") GLX_DRAWABLE_TYPE does not match: req(onscrn "+onscreen+", pbuffer "+usePBuffer+"), got(onscreen "+( 0 != (val & GLX.GLX_WINDOW_BIT) )+", pbuffer "+( 0 != (val & GLX.GLX_PBUFFER_BIT) )+", pixmap "+( 0 != (val & GLX.GLX_PIXMAP_BIT) )+")"); + } + return null; + } + res.setDoubleBuffered(glXGetFBConfig(display, fbcfg, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetFBConfig(display, fbcfg, GLX.GLX_STEREO, tmp, 0) != 0); + res.setHardwareAccelerated(glXGetFBConfig(display, fbcfg, GLX.GLX_CONFIG_CAVEAT, tmp, 0) != GLX.GLX_SLOW_CONFIG); + res.setDepthBits (glXGetFBConfig(display, fbcfg, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetFBConfig(display, fbcfg, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetFBConfig(display, fbcfg, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetFBConfig(display, fbcfg, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + if (isMultisampleEnabled) { + res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); + } + res.setBackgroundOpaque(glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_TYPE, tmp, 0) == GLX.GLX_NONE); + if(!res.isBackgroundOpaque()) { + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_RED_VALUE, tmp, 0); + res.setTransparentRedValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_GREEN_VALUE, tmp, 0); + res.setTransparentGreenValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_BLUE_VALUE, tmp, 0); + res.setTransparentBlueValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + + glXGetFBConfig(display, fbcfg, GLX.GLX_TRANSPARENT_ALPHA_VALUE, tmp, 0); + res.setTransparentAlphaValue(tmp[0]==GLX.GLX_DONT_CARE?-1:tmp[0]); + } + try { + res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); + } catch (Exception e) {} + return res; + } + + private static String glXGetFBConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + default: return "Unknown error code " + err; + } + } + + public static int glXGetFBConfig(long display, long cfg, int attrib, int[] tmp, int tmp_offset) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetFBConfigAttrib(display, cfg, attrib, tmp, tmp_offset); + if (res != 0) { + throw new GLException("glXGetFBConfig("+toHexString(attrib)+") failed: error code " + glXGetFBConfigErrorCode(res)); + } + return tmp[tmp_offset]; + } + + public static int glXFBConfig2FBConfigID(long display, long cfg) { + int[] tmpID = new int[1]; + return glXGetFBConfig(display, cfg, GLX.GLX_FBCONFIG_ID, tmpID, 0); + } + + public static long glXFBConfigID2FBConfig(long display, int screen, int id) { + int[] attribs = new int[] { GLX.GLX_FBCONFIG_ID, id, 0 }; + int[] count = { -1 }; + PointerBuffer fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + return 0; + } + return fbcfgsL.get(0); + } + + // Visual Info + + public static XVisualInfo XVisualID2XVisualInfo(long display, long visualID) { + XVisualInfo res = null; + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try{ + int[] count = new int[1]; + XVisualInfo template = XVisualInfo.create(); + template.setVisualid(visualID); + XVisualInfo[] infos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualIDMask, template, count, 0); + if (infos == null || infos.length == 0) { + return null; + } + res = XVisualInfo.create(infos[0]); + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + if (DEBUG) { + System.err.println("!!! Fetched XVisualInfo for visual ID " + toHexString(visualID)); + System.err.println("!!! Resulting XVisualInfo: visualid = " + toHexString(res.getVisualid())); + } + return res; + } + + public static GLCapabilities XVisualInfo2GLCapabilities(GLProfile glp, long display, XVisualInfo info, boolean onscreen, boolean usePBuffer, boolean isMultisampleEnabled) { + int[] tmp = new int[1]; + int val = glXGetConfig(display, info, GLX.GLX_USE_GL, tmp, 0); + if (val == 0) { + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support OpenGL"); + } + return null; + } + val = glXGetConfig(display, info, GLX.GLX_RGBA, tmp, 0); + if (val == 0) { + if(DEBUG) { + System.err.println("Visual ("+toHexString(info.getVisualid())+") does not support RGBA"); + } + return null; + } + GLCapabilities res = new GLCapabilities(glp); + res.setOnscreen (onscreen); + res.setPBuffer (usePBuffer); + res.setDoubleBuffered(glXGetConfig(display, info, GLX.GLX_DOUBLEBUFFER, tmp, 0) != 0); + res.setStereo (glXGetConfig(display, info, GLX.GLX_STEREO, tmp, 0) != 0); + // Note: use of hardware acceleration is determined by + // glXCreateContext, not by the XVisualInfo. Optimistically claim + // that all GLCapabilities have the capability to be hardware + // accelerated. + res.setHardwareAccelerated(true); + res.setDepthBits (glXGetConfig(display, info, GLX.GLX_DEPTH_SIZE, tmp, 0)); + res.setStencilBits (glXGetConfig(display, info, GLX.GLX_STENCIL_SIZE, tmp, 0)); + res.setRedBits (glXGetConfig(display, info, GLX.GLX_RED_SIZE, tmp, 0)); + res.setGreenBits (glXGetConfig(display, info, GLX.GLX_GREEN_SIZE, tmp, 0)); + res.setBlueBits (glXGetConfig(display, info, GLX.GLX_BLUE_SIZE, tmp, 0)); + res.setAlphaBits (glXGetConfig(display, info, GLX.GLX_ALPHA_SIZE, tmp, 0)); + res.setAccumRedBits (glXGetConfig(display, info, GLX.GLX_ACCUM_RED_SIZE, tmp, 0)); + res.setAccumGreenBits(glXGetConfig(display, info, GLX.GLX_ACCUM_GREEN_SIZE, tmp, 0)); + res.setAccumBlueBits (glXGetConfig(display, info, GLX.GLX_ACCUM_BLUE_SIZE, tmp, 0)); + res.setAccumAlphaBits(glXGetConfig(display, info, GLX.GLX_ACCUM_ALPHA_SIZE, tmp, 0)); + if (isMultisampleEnabled) { + res.setSampleBuffers(glXGetConfig(display, info, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); + res.setNumSamples (glXGetConfig(display, info, GLX.GLX_SAMPLES, tmp, 0)); + } + return res; + } + + private static String glXGetConfigErrorCode(int err) { + switch (err) { + case GLX.GLX_NO_EXTENSION: return "GLX_NO_EXTENSION"; + case GLX.GLX_BAD_SCREEN: return "GLX_BAD_SCREEN"; + case GLX.GLX_BAD_ATTRIBUTE: return "GLX_BAD_ATTRIBUTE"; + case GLX.GLX_BAD_VISUAL: return "GLX_BAD_VISUAL"; + default: return "Unknown error code " + err; + } + } + + public static int glXGetConfig(long display, XVisualInfo info, int attrib, int[] tmp, int tmp_offset) { + if (display == 0) { + throw new GLException("No display connection"); + } + int res = GLX.glXGetConfig(display, info, attrib, tmp, tmp_offset); + if (res != 0) { + throw new GLException("glXGetConfig("+toHexString(attrib)+") failed: error code " + glXGetConfigErrorCode(res)); + } + return tmp[tmp_offset]; + } + + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + + public String toString() { + return "X11GLXGraphicsConfiguration["+getScreen()+", visualID " + toHexString(getVisualID()) + ", fbConfigID " + toHexString(fbConfigID) + + ",\n\trequested " + getRequestedCapabilities()+ + ",\n\tchosen " + getChosenCapabilities()+ + "]"; + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java new file mode 100644 index 000000000..e65fb5e90 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import com.jogamp.common.nio.PointerBuffer; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import com.jogamp.nativewindow.impl.x11.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + + +/** Subclass of GraphicsConfigurationFactory used when non-AWT tookits + are used on X11 platforms. Toolkits will likely need to delegate + to this one to change the accepted and returned types of the + GraphicsDevice and GraphicsConfiguration abstractions. */ + +public class X11GLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public X11GLXGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.x11.X11GraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + return chooseGraphicsConfigurationStatic(capabilities, chooser, absScreen); + } + + /** + protected static X11GLXGraphicsConfiguration createDefaultGraphicsConfigurationFBConfig(AbstractGraphicsScreen absScreen, boolean onscreen, boolean usePBuffer) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + if (!(absScreen instanceof X11GraphicsScreen)) { + throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here"); + } + X11GraphicsScreen x11Screen = (X11GraphicsScreen)absScreen; + + GLProfile glProfile = GLProfile.getDefault(); + GLCapabilities caps=null; + XVisualInfo xvis=null; + long fbcfg = 0; + int fbid = -1; + + // Utilizing FBConfig + // + GLCapabilities capsFB = null; + long display = x11Screen.getDevice().getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + X11Lib.XLockDisplay(display); + try { + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + + long visID = X11Lib.DefaultVisualID(display, x11Screen.getIndex()); + xvis = X11GLXGraphicsConfiguration.XVisualID2XVisualInfo(display, visID); + caps = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, xvis, onscreen, usePBuffer, isMultisampleAvailable); + + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(caps, true, isMultisampleAvailable, display, screen); + int[] count = { -1 }; + PointerBuffer fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + throw new Exception("Could not fetch FBConfig for "+caps); + } + fbcfg = fbcfgsL.get(0); + capsFB = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfg, true, onscreen, usePBuffer, isMultisampleAvailable); + + fbid = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfg); + + xvis = GLX.glXGetVisualFromFBConfigCopied(display, fbcfg); + if (xvis==null) { + throw new GLException("Error: Choosen FBConfig has no visual"); + } + } catch (Throwable t) { + } finally { + X11Lib.XUnlockDisplay(display); + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + return new X11GLXGraphicsConfiguration(x11Screen, (null!=capsFB)?capsFB:caps, caps, null, xvis, fbcfg, fbid); + } */ + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationStatic(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + if (absScreen == null) { + throw new IllegalArgumentException("AbstractGraphicsScreen is null"); + } + if (!(absScreen instanceof X11GraphicsScreen)) { + throw new IllegalArgumentException("Only X11GraphicsScreen are allowed here"); + } + X11GraphicsScreen x11Screen = (X11GraphicsScreen)absScreen; + + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects"); + } + + if (capabilities == null) { + capabilities = new GLCapabilities(null); + } + + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = ((GLCapabilities)capabilities).isPBuffer(); + + GLCapabilities caps2 = (GLCapabilities) capabilities.clone(); + if(!caps2.isOnscreen()) { + // OFFSCREEN !DOUBLE_BUFFER // FIXME DBLBUFOFFSCRN + caps2.setDoubleBuffered(false); + } + + X11GLXGraphicsConfiguration res; + res = chooseGraphicsConfigurationFBConfig((GLCapabilities) caps2, + (GLCapabilitiesChooser) chooser, + x11Screen); + if(null==res) { + if(usePBuffer) { + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig for "+caps2); + } + res = chooseGraphicsConfigurationXVisual((GLCapabilities) caps2, + (GLCapabilitiesChooser) chooser, + x11Screen); + } + if(null==res) { + throw new GLException("Error: Couldn't create X11GLXGraphicsConfiguration based on FBConfig and XVisual for "+caps2); + } + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationStatic("+x11Screen+","+caps2+"): "+res); + } + return res; + } + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationFBConfig(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + X11GraphicsScreen x11Screen) { + long recommendedFBConfig = 0; + int recommendedIndex = -1; + GLCapabilities[] caps = null; + PointerBuffer fbcfgsL = null; + int chosen=-1; + int retFBID=-1; + XVisualInfo retXVisualInfo = null; + GLProfile glProfile = capabilities.getGLProfile(); + boolean onscreen = capabilities.isOnscreen(); + boolean usePBuffer = capabilities.isPBuffer(); + + // Utilizing FBConfig + // + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + X11Lib.XLockDisplay(display); + try{ + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, true, isMultisampleAvailable, display, screen); + int[] count = { -1 }; + + // determine the recommended FBConfig .. + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, attribs, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXChooseFBConfig ("+x11Screen+","+capabilities+"): "+fbcfgsL+", "+count[0]); + } + } else if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(0) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed - GLX FBConfig invalid: ("+x11Screen+","+capabilities+"): "+fbcfgsL+", fbcfg: "+toHexString(fbcfgsL.get(0))); + } + } else { + recommendedFBConfig = fbcfgsL.get(0); + } + + // get all, glXChooseFBConfig(.. attribs==null ..) == glXGetFBConfig(..) + fbcfgsL = GLX.glXChooseFBConfigCopied(display, screen, null, 0, count, 0); + if (fbcfgsL == null || fbcfgsL.limit()<1) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetFBConfig ("+x11Screen+"): "+fbcfgsL+", "+count[0]); + } + return null; + } + + // make GLCapabilities and seek the recommendedIndex + caps = new GLCapabilities[fbcfgsL.limit()]; + for (int i = 0; i < fbcfgsL.limit(); i++) { + if( !X11GLXGraphicsConfiguration.GLXFBConfigValid( display, fbcfgsL.get(i) ) ) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: FBConfig invalid: ("+x11Screen+","+capabilities+"): fbcfg: "+toHexString(fbcfgsL.get(i))); + } + } else { + caps[i] = X11GLXGraphicsConfiguration.GLXFBConfig2GLCapabilities(glProfile, display, fbcfgsL.get(i), + false, onscreen, usePBuffer, isMultisampleAvailable); + if(caps[i]!=null && recommendedFBConfig==fbcfgsL.get(i)) { + recommendedIndex=i; + if (DEBUG) { + System.err.println("!!! glXChooseFBConfig recommended "+i+", "+caps[i]); + } + } + } + } + + if(null==chooser) { + chosen = recommendedIndex; // may still be -1 in case nothing was recommended (-1) + } + + if (chosen < 0) { + if(null==chooser) { + // nothing recommended .. so use our default implementation + chooser = new DefaultGLCapabilitiesChooser(); + } + try { + chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + chosen = -1; + } + } + if (chosen < 0) { + // keep on going .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. unable to choose config, using first"); + } + // seek first available one .. + for(chosen = 0; chosen < caps.length && caps[chosen]==null; chosen++) ; + if(chosen==caps.length) { + // give up .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig Failed .. nothing available, bail out"); + } + return null; + } + } else if (chosen >= caps.length) { + if(DEBUG) { + System.err.println("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ", got "+chosen+")"); + } + return null; + } + + retFBID = X11GLXGraphicsConfiguration.glXFBConfig2FBConfigID(display, fbcfgsL.get(chosen)); + + retXVisualInfo = GLX.glXGetVisualFromFBConfigCopied(display, fbcfgsL.get(chosen)); + if (retXVisualInfo==null) { + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationFBConfig: Failed glXGetVisualFromFBConfig ("+x11Screen+", "+fbcfgsL.get(chosen) +" (Continue: "+(false==caps[chosen].isOnscreen())+"):\n\t"+caps[chosen]); + } + if(caps[chosen].isOnscreen()) { + // Onscreen drawables shall have a XVisual .. + return null; + } + } + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + + return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capabilities, chooser, retXVisualInfo, fbcfgsL.get(chosen), retFBID); + } + + protected static X11GLXGraphicsConfiguration chooseGraphicsConfigurationXVisual(GLCapabilities capabilities, + GLCapabilitiesChooser chooser, + X11GraphicsScreen x11Screen) { + if (chooser == null) { + chooser = new DefaultGLCapabilitiesChooser(); + } + + // Until we have a rock-solid visual selection algorithm written + // in pure Java, we're going to provide the underlying window + // system's selection to the chooser as a hint + + GLProfile glProfile = capabilities.getGLProfile(); + boolean onscreen = capabilities.isOnscreen(); + GLCapabilities[] caps = null; + int recommendedIndex = -1; + XVisualInfo retXVisualInfo = null; + int chosen=-1; + + AbstractGraphicsDevice absDevice = x11Screen.getDevice(); + long display = absDevice.getHandle(); + + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + X11Lib.XLockDisplay(display); + try{ + int screen = x11Screen.getIndex(); + boolean isMultisampleAvailable = GLXUtil.isMultisampleAvailable(display); + int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capabilities, false, isMultisampleAvailable, display, screen); + XVisualInfo[] infos = null; + + XVisualInfo recommendedVis = GLX.glXChooseVisualCopied(display, screen, attribs, 0); + if (DEBUG) { + System.err.print("!!! glXChooseVisual recommended "); + if (recommendedVis == null) { + System.err.println("null visual"); + } else { + System.err.println("visual id " + toHexString(recommendedVis.getVisualid())); + } + } + int[] count = new int[1]; + XVisualInfo template = XVisualInfo.create(); + template.setScreen(screen); + infos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualScreenMask, template, count, 0); + if (infos == null || infos.length<1) { + throw new GLException("Error while enumerating available XVisualInfos"); + } + caps = new GLCapabilities[infos.length]; + for (int i = 0; i < infos.length; i++) { + caps[i] = X11GLXGraphicsConfiguration.XVisualInfo2GLCapabilities(glProfile, display, infos[i], onscreen, false, isMultisampleAvailable); + // Attempt to find the visual chosen by glXChooseVisual + if (recommendedVis != null && recommendedVis.getVisualid() == infos[i].getVisualid()) { + recommendedIndex = i; + } + } + try { + chosen = chooser.chooseCapabilities(capabilities, caps, recommendedIndex); + } catch (NativeWindowException e) { + if(DEBUG) { + e.printStackTrace(); + } + chosen = -1; + } + if (chosen < 0) { + // keep on going .. + if(DEBUG) { + System.err.println("X11GLXGraphicsConfiguration.chooseGraphicsConfigurationXVisual Failed .. unable to choose config, using first"); + } + chosen = 0; // default .. + } else if (chosen >= caps.length) { + throw new GLException("GLCapabilitiesChooser specified invalid index (expected 0.." + (caps.length - 1) + ")"); + } + if (infos[chosen] == null) { + throw new GLException("GLCapabilitiesChooser chose an invalid visual for "+caps[chosen]); + } + retXVisualInfo = XVisualInfo.create(infos[chosen]); + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + return new X11GLXGraphicsConfiguration(x11Screen, caps[chosen], capabilities, chooser, retXVisualInfo, 0, -1); + } + + public static String toHexString(int val) { + return "0x"+Integer.toHexString(val); + } + + public static String toHexString(long val) { + return "0x"+Long.toHexString(val); + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java new file mode 100644 index 000000000..bea953ee9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXContext.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OffscreenGLXContext extends X11GLXContext { + private X11OffscreenGLXDrawable drawable; + + public X11OffscreenGLXContext(X11OffscreenGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public int getOffscreenContextPixelDataType() { + GL gl = getGL(); + return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; + } + + public int getOffscreenContextReadBuffer() { + GLCapabilities caps = (GLCapabilities)drawable.getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if (caps.getDoubleBuffered()) { + return GL.GL_BACK; + } + return GL.GL_FRONT; + } + + public boolean offscreenImageNeedsVerticalFlip() { + // There doesn't seem to be a way to do this in the construction + // of the Pixmap or GLXPixmap + return true; + } + + protected void create() { + createContext(false); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java new file mode 100644 index 000000000..14d07e74f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11OffscreenGLXDrawable extends X11GLXDrawable { + private long pixmap; + + protected X11OffscreenGLXDrawable(GLDrawableFactory factory, NativeWindow target) { + super(factory, target, true); + create(); + } + + protected void setRealizedImpl() { + if(realized) { + create(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new X11OffscreenGLXContext(this, shareWith); + } + + private void create() { + NativeWindow nw = getNativeWindow(); + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration(); + XVisualInfo vis = config.getXVisualInfo(); + int bitsPerPixel = vis.getDepth(); + AbstractGraphicsScreen aScreen = config.getScreen(); + AbstractGraphicsDevice aDevice = aScreen.getDevice(); + long dpy = aDevice.getHandle(); + int screen = aScreen.getIndex(); + + getFactoryImpl().lockToolkit(); + try { + X11Lib.XLockDisplay(dpy); + try{ + + pixmap = X11Lib.XCreatePixmap(dpy, X11Lib.RootWindow(dpy, screen), + component.getWidth(), component.getHeight(), bitsPerPixel); + if (pixmap == 0) { + throw new GLException("XCreatePixmap failed"); + } + long drawable = GLX.glXCreateGLXPixmap(dpy, vis, pixmap); + if (drawable == 0) { + X11Lib.XFreePixmap(dpy, pixmap); + pixmap = 0; + throw new GLException("glXCreateGLXPixmap failed"); + } + ((SurfaceChangeable)nw).setSurfaceHandle(drawable); + if (DEBUG) { + System.err.println("Created pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(dpy)); + } + }finally{ + X11Lib.XUnlockDisplay(dpy); + } + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + public void destroy() { + if (pixmap == 0) return; + + NativeWindow nw = getNativeWindow(); + long display = nw.getDisplayHandle(); + + getFactoryImpl().lockToolkit(); + try { + X11Lib.XLockDisplay(display); + try{ + long drawable = nw.getSurfaceHandle(); + if (DEBUG) { + System.err.println("Destroying pixmap " + toHexString(pixmap) + + ", GLXPixmap " + toHexString(drawable) + + ", display " + toHexString(display)); + } + + // Must destroy pixmap and GLXPixmap + + if (DEBUG) { + long cur = GLX.glXGetCurrentContext(); + if (cur != 0) { + System.err.println("WARNING: found context " + toHexString(cur) + " current during pixmap destruction"); + } + } + + // FIXME: workaround for crashes on NVidia hardware when + // destroying pixmap (no context is current at the point of the + // crash, at least from the point of view of + // glXGetCurrentContext) + GLX.glXMakeCurrent(display, 0, 0); + + GLX.glXDestroyGLXPixmap(display, drawable); + X11Lib.XFreePixmap(display, pixmap); + drawable = 0; + pixmap = 0; + ((SurfaceChangeable)nw).setSurfaceHandle(0); + + }finally{ + X11Lib.XUnlockDisplay(display); + } + } finally { + getFactoryImpl().unlockToolkit(); + display = 0; + } + } + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java new file mode 100644 index 000000000..c89a5efd5 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXContext.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import java.util.*; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OnscreenGLXContext extends X11GLXContext { + // This indicates whether the context we have created is indirect + // and therefore requires the toolkit to be locked around all GL + // calls rather than just all GLX calls + protected boolean isIndirect; + + public X11OnscreenGLXContext(X11OnscreenGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + } + + public boolean isOptimizable() { + return super.isOptimizable() && !isIndirect; + } + + protected void create() { + createContext(true); + isIndirect = !GLX.glXIsDirect(drawable.getNativeWindow().getDisplayHandle(), context); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java new file mode 100644 index 000000000..43468b858 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OnscreenGLXDrawable.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.nativewindow.*; +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11OnscreenGLXDrawable extends X11GLXDrawable { + protected X11OnscreenGLXDrawable(GLDrawableFactory factory, NativeWindow component) { + super(factory, component, false); + } + + public GLContext createContext(GLContext shareWith) { + return new X11OnscreenGLXContext(this, shareWith); + } + + public int getWidth() { + return component.getWidth(); + } + + public int getHeight() { + return component.getHeight(); + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java new file mode 100644 index 000000000..1b70adf6b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXContext.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.*; + +public class X11PbufferGLXContext extends X11GLXContext { + private X11PbufferGLXDrawable drawable; + + public X11PbufferGLXContext(X11PbufferGLXDrawable drawable, + GLContext shareWith) { + super(drawable, shareWith); + this.drawable = drawable; + } + + public void bindPbufferToTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + public void releasePbufferFromTexture() { + // FIXME: figure out how to implement this + throw new GLException("Not yet implemented"); + } + + + public int getFloatingPointMode() { + return drawable.getFloatingPointMode(); + } + + protected void create() { + createContext(true); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java new file mode 100644 index 000000000..50b32b9ec --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.impl.x11.glx; + +import javax.media.opengl.*; +import javax.media.nativewindow.*; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.impl.x11.glx.*; +import com.jogamp.nativewindow.impl.x11.*; + +public class X11PbufferGLXDrawable extends X11GLXDrawable { + protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeWindow target) { + /* GLCapabilities caps, + GLCapabilitiesChooser chooser, + int width, int height */ + super(factory, target, true); + + if (DEBUG) { + System.out.println("Pbuffer config: " + getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration()); + } + + createPbuffer(); + + if (DEBUG) { + System.err.println("Created pbuffer " + this); + } + } + + protected void setRealizedImpl() { + if(realized) { + createPbuffer(); + } else { + destroy(); + } + } + + public GLContext createContext(GLContext shareWith) { + return new X11PbufferGLXContext(this, shareWith); + } + + public void destroy() { + getFactoryImpl().lockToolkit(); + try { + NativeWindow nw = getNativeWindow(); + if (nw.getSurfaceHandle() != 0) { + GLX.glXDestroyPbuffer(nw.getDisplayHandle(), nw.getSurfaceHandle()); + } + ((SurfaceChangeable)nw).setSurfaceHandle(0); + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + private void createPbuffer() { + getFactoryImpl().lockToolkit(); + try { + X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeWindow().getGraphicsConfiguration().getNativeGraphicsConfiguration(); + AbstractGraphicsScreen aScreen = config.getScreen(); + AbstractGraphicsDevice aDevice = aScreen.getDevice(); + long display = aDevice.getHandle(); + int screen = aScreen.getIndex(); + + if (display==0) { + throw new GLException("Null display"); + } + + NativeWindow nw = getNativeWindow(); + + GLCapabilities capabilities = (GLCapabilities)config.getChosenCapabilities(); + + if (capabilities.getPbufferRenderToTexture()) { + throw new GLException("Render-to-texture pbuffers not supported yet on X11"); + } + + if (capabilities.getPbufferRenderToTextureRectangle()) { + throw new GLException("Render-to-texture-rectangle pbuffers not supported yet on X11"); + } + + // Create the p-buffer. + int niattribs = 0; + int[] iattributes = new int[5]; + + iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH; + iattributes[niattribs++] = nw.getWidth(); + iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT; + iattributes[niattribs++] = nw.getHeight(); + iattributes[niattribs++] = 0; + + long pbuffer = GLX.glXCreatePbuffer(display, config.getFBConfig(), iattributes, 0); + if (pbuffer == 0) { + // FIXME: query X error code for detail error message + throw new GLException("pbuffer creation error: glXCreatePbuffer() failed"); + } + + // Set up instance variables + ((SurfaceChangeable)nw).setSurfaceHandle(pbuffer); + + // Determine the actual width and height we were able to create. + int[] tmp = new int[1]; + GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_WIDTH, tmp, 0); + int width = tmp[0]; + GLX.glXQueryDrawable(display, pbuffer, GLX.GLX_HEIGHT, tmp, 0); + int height = tmp[0]; + ((SurfaceChangeable)nw).setSize(width, height); + } finally { + getFactoryImpl().unlockToolkit(); + } + } + + public int getFloatingPointMode() { + // Floating-point pbuffers currently require NVidia hardware on X11 + return GLPbuffer.NV_FLOAT; + } + + protected void swapBuffersImpl() { + if(DEBUG) { + System.err.println("unhandled swapBuffersImpl() called for: "+this); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java new file mode 100644 index 000000000..dc6c60664 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.impl.x11.glx.awt; + +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import javax.media.nativewindow.*; +import javax.media.nativewindow.x11.*; +import javax.media.nativewindow.awt.*; +import javax.media.opengl.*; +import javax.media.opengl.awt.*; + +import com.jogamp.opengl.impl.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.x11.*; +import com.jogamp.nativewindow.impl.x11.*; +import com.jogamp.opengl.impl.x11.*; +import com.jogamp.opengl.impl.x11.glx.*; + +public class X11AWTGLXGraphicsConfigurationFactory extends GraphicsConfigurationFactory { + protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); + + public X11AWTGLXGraphicsConfigurationFactory() { + GraphicsConfigurationFactory.registerFactory(javax.media.nativewindow.awt.AWTGraphicsDevice.class, this); + } + + public AbstractGraphicsConfiguration chooseGraphicsConfiguration(Capabilities capabilities, + CapabilitiesChooser chooser, + AbstractGraphicsScreen absScreen) { + GraphicsDevice device = null; + if (absScreen != null && + !(absScreen instanceof AWTGraphicsScreen)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only AWTGraphicsScreen objects"); + } + + if(null==absScreen) { + absScreen = AWTGraphicsScreen.createScreenDevice(-1); + } + AWTGraphicsScreen awtScreen = (AWTGraphicsScreen) absScreen; + device = ((AWTGraphicsDevice)awtScreen.getDevice()).getGraphicsDevice(); + + if (capabilities != null && + !(capabilities instanceof GLCapabilities)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilities objects"); + } + + if (chooser != null && + !(chooser instanceof GLCapabilitiesChooser)) { + throw new IllegalArgumentException("This GraphicsConfigurationFactory accepts only GLCapabilitiesChooser objects"); + } + + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: got "+absScreen); + } + + GraphicsConfiguration gc; + X11GraphicsConfiguration x11Config; + + // Need the lock here, since it could be an AWT owned display connection + NativeWindowFactory.getDefaultFactory().getToolkitLock().lock(); + try { + long displayHandle = X11SunJDKReflection.graphicsDeviceGetDisplay(device); + if(0==displayHandle) { + displayHandle = X11Util.createThreadLocalDefaultDisplay(); + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: using a thread local X11 display"); + } + } else { + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: using AWT X11 display 0x"+Long.toHexString(displayHandle)); + } + } + ((AWTGraphicsDevice)awtScreen.getDevice()).setHandle(displayHandle); + X11GraphicsDevice x11Device = new X11GraphicsDevice(displayHandle); + + X11GraphicsScreen x11Screen = new X11GraphicsScreen(x11Device, awtScreen.getIndex()); + if(DEBUG) { + System.err.println("X11AWTGLXGraphicsConfigurationFactory: made "+x11Screen); + } + + gc = device.getDefaultConfiguration(); + AWTGraphicsConfiguration.setupCapabilitiesRGBABits(capabilities, gc); + if(DEBUG) { + System.err.println("AWT Colormodel compatible: "+capabilities); + } + + x11Config = (X11GraphicsConfiguration) + GraphicsConfigurationFactory.getFactory(x11Device).chooseGraphicsConfiguration(capabilities, + chooser, + x11Screen); + if (x11Config == null) { + throw new GLException("Unable to choose a GraphicsConfiguration: "+capabilities+",\n\t"+chooser+"\n\t"+x11Screen); + } + + long visualID = x11Config.getVisualID(); + // Now figure out which GraphicsConfiguration corresponds to this + // visual by matching the visual ID + GraphicsConfiguration[] configs = device.getConfigurations(); + for (int i = 0; i < configs.length; i++) { + GraphicsConfiguration config = configs[i]; + if (config != null) { + if (X11SunJDKReflection.graphicsConfigurationGetVisualID(config) == visualID) { + return new AWTGraphicsConfiguration(awtScreen, x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), + config, x11Config); + } + } + } + } finally { + NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock(); + } + // Either we weren't able to reflectively introspect on the + // X11GraphicsConfig or something went wrong in the steps above; + // Let's take the default configuration as used on Windows and MacOSX then .. + if(DEBUG) { + System.err.println("!!! Using default configuration"); + } + return new AWTGraphicsConfiguration(awtScreen, x11Config.getChosenCapabilities(), x11Config.getRequestedCapabilities(), gc, x11Config); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java new file mode 100644 index 000000000..d8e1cf080 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/AWTAnimatorImpl.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.util; + +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Rectangle; +import java.util.*; +import javax.swing.*; + +import javax.media.opengl.*; + +/** Abstraction to factor out AWT dependencies from the Animator's + implementation in a way that still allows the FPSAnimator to pick + up this behavior if desired. */ + +class AWTAnimatorImpl extends AnimatorImpl { + // For efficient rendering of Swing components, in particular when + // they overlap one another + private List lightweights = new ArrayList(); + private Map repaintManagers = new IdentityHashMap(); + private Map dirtyRegions = new IdentityHashMap(); + + public void display(Animator animator, + boolean ignoreExceptions, + boolean printExceptions) { + Iterator iter = animator.drawableIterator(); + while (iter.hasNext()) { + GLAutoDrawable drawable = (GLAutoDrawable) iter.next(); + if (drawable instanceof JComponent) { + // Lightweight components need a more efficient drawing + // scheme than simply forcing repainting of each one in + // turn since drawing one can force another one to be + // drawn in turn + lightweights.add(drawable); + } else { + try { + drawable.display(); + } catch (RuntimeException e) { + if (ignoreExceptions) { + if (printExceptions) { + e.printStackTrace(); + } + } else { + throw(e); + } + } + } + } + if (lightweights.size() > 0) { + try { + SwingUtilities.invokeAndWait(drawWithRepaintManagerRunnable); + } catch (Exception e) { + e.printStackTrace(); + } + lightweights.clear(); + } + } + + // Uses RepaintManager APIs to implement more efficient redrawing of + // the Swing widgets we're animating + private Runnable drawWithRepaintManagerRunnable = new Runnable() { + public void run() { + for (Iterator iter = lightweights.iterator(); iter.hasNext(); ) { + JComponent comp = (JComponent) iter.next(); + RepaintManager rm = RepaintManager.currentManager(comp); + rm.markCompletelyDirty(comp); + repaintManagers.put(rm, rm); + + // RepaintManagers don't currently optimize the case of + // overlapping sibling components. If we have two + // JInternalFrames in a JDesktopPane, the redraw of the + // bottom one will cause the top one to be redrawn as + // well. The top one will then be redrawn separately. In + // order to optimize this case we need to compute the union + // of all of the dirty regions on a particular JComponent if + // optimized drawing isn't enabled for it. + + // Walk up the hierarchy trying to find a non-optimizable + // ancestor + Rectangle visible = comp.getVisibleRect(); + int x = visible.x; + int y = visible.y; + while (comp != null) { + x += comp.getX(); + y += comp.getY(); + Component c = comp.getParent(); + if ((c == null) || (!(c instanceof JComponent))) { + comp = null; + } else { + comp = (JComponent) c; + if (!comp.isOptimizedDrawingEnabled()) { + rm = RepaintManager.currentManager(comp); + repaintManagers.put(rm, rm); + // Need to dirty this region + Rectangle dirty = (Rectangle) dirtyRegions.get(comp); + if (dirty == null) { + dirty = new Rectangle(x, y, visible.width, visible.height); + dirtyRegions.put(comp, dirty); + } else { + // Compute union with already dirty region + // Note we could compute multiple non-overlapping + // regions: might want to do that in the future + // (prob. need more complex algorithm -- dynamic + // programming?) + dirty.add(new Rectangle(x, y, visible.width, visible.height)); + } + } + } + } + } + + // Dirty any needed regions on non-optimizable components + for (Iterator iter = dirtyRegions.keySet().iterator(); iter.hasNext(); ) { + JComponent comp = (JComponent) iter.next(); + Rectangle rect = (Rectangle) dirtyRegions.get(comp); + RepaintManager rm = RepaintManager.currentManager(comp); + rm.addDirtyRegion(comp, rect.x, rect.y, rect.width, rect.height); + } + + // Draw all dirty regions + for (Iterator iter = repaintManagers.keySet().iterator(); iter.hasNext(); ) { + ((RepaintManager) iter.next()).paintDirtyRegions(); + } + dirtyRegions.clear(); + repaintManagers.clear(); + } + }; + + public boolean skipWaitForStop(Thread thread) { + return ((Thread.currentThread() == thread) || EventQueue.isDispatchThread()); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/Animator.java b/src/jogl/classes/com/jogamp/opengl/util/Animator.java new file mode 100755 index 000000000..30be0bd90 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/Animator.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util; + +import java.util.*; + +import javax.media.opengl.*; + +import com.jogamp.opengl.impl.Debug; + +/** <P> An Animator can be attached to one or more {@link + GLAutoDrawable}s to drive their display() methods in a loop. </P> + + <P> The Animator class creates a background thread in which the + calls to <code>display()</code> are performed. After each drawable + has been redrawn, a brief pause is performed to avoid swamping the + CPU, unless {@link #setRunAsFastAsPossible} has been called. </P> +*/ + +public class Animator { + protected static final boolean DEBUG = Debug.debug("Animator"); + + private volatile ArrayList/*<GLAutoDrawable>*/ drawables = new ArrayList(); + private AnimatorImpl impl; + private Runnable runnable; + private boolean runAsFastAsPossible; + protected ThreadGroup threadGroup; + protected Thread thread; + protected volatile boolean shouldStop; + protected boolean ignoreExceptions; + protected boolean printExceptions; + + /** Creates a new, empty Animator. */ + public Animator(ThreadGroup tg) { + + if(GLProfile.isAWTJOGLAvailable()) { + try { + impl = (AnimatorImpl) Class.forName("com.jogamp.opengl.util.awt.AWTAnimatorImpl").newInstance(); + } catch (Exception e) { } + } + if(null==impl) { + impl = new AnimatorImpl(); + } + threadGroup = tg; + + if(DEBUG) { + System.out.println("Animator created, ThreadGroup: "+threadGroup); + } + } + + public Animator() { + this((ThreadGroup)null); + } + + /** Creates a new Animator for a particular drawable. */ + public Animator(GLAutoDrawable drawable) { + this((ThreadGroup)null); + add(drawable); + } + + /** Creates a new Animator for a particular drawable. */ + public Animator(ThreadGroup tg, GLAutoDrawable drawable) { + this(tg); + add(drawable); + } + + /** Adds a drawable to the list managed by this Animator. */ + public synchronized void add(GLAutoDrawable drawable) { + ArrayList newList = (ArrayList) drawables.clone(); + newList.add(drawable); + drawables = newList; + notifyAll(); + } + + /** Removes a drawable from the list managed by this Animator. */ + public synchronized void remove(GLAutoDrawable drawable) { + ArrayList newList = (ArrayList) drawables.clone(); + newList.remove(drawable); + drawables = newList; + } + + /** Returns an iterator over the drawables managed by this + Animator. */ + public Iterator/*<GLAutoDrawable>*/ drawableIterator() { + return drawables.iterator(); + } + + /** Sets a flag causing this Animator to ignore exceptions produced + while redrawing the drawables. By default this flag is set to + false, causing any exception thrown to halt the Animator. */ + public void setIgnoreExceptions(boolean ignoreExceptions) { + this.ignoreExceptions = ignoreExceptions; + } + + /** Sets a flag indicating that when exceptions are being ignored by + this Animator (see {@link #setIgnoreExceptions}), to print the + exceptions' stack traces for diagnostic information. Defaults to + false. */ + public void setPrintExceptions(boolean printExceptions) { + this.printExceptions = printExceptions; + } + + /** Sets a flag in this Animator indicating that it is to run as + fast as possible. By default there is a brief pause in the + animation loop which prevents the CPU from getting swamped. + This method may not have an effect on subclasses. */ + public final void setRunAsFastAsPossible(boolean runFast) { + runAsFastAsPossible = runFast; + } + + /** Called every frame to cause redrawing of all of the + GLAutoDrawables this Animator manages. Subclasses should call + this to get the most optimized painting behavior for the set of + components this Animator manages, in particular when multiple + lightweight widgets are continually being redrawn. */ + protected void display() { + impl.display(this, ignoreExceptions, printExceptions); + } + + class MainLoop implements Runnable { + public void run() { + try { + if(DEBUG) { + System.out.println("Animator started: "+Thread.currentThread()); + } + while (!shouldStop) { + // Don't consume CPU unless there is work to be done + if (drawables.size() == 0) { + synchronized (Animator.this) { + while (drawables.size() == 0 && !shouldStop) { + try { + Animator.this.wait(); + } catch (InterruptedException e) { + } + } + } + } + display(); + if (!runAsFastAsPossible) { + // Avoid swamping the CPU + Thread.yield(); + } + } + if(DEBUG) { + System.out.println("Animator stopped: "+Thread.currentThread()); + } + } finally { + shouldStop = false; + synchronized (Animator.this) { + thread = null; + Animator.this.notify(); + } + } + } + } + + /** Starts this animator. */ + public synchronized void start() { + if (thread != null) { + throw new GLException("Already started"); + } + if (runnable == null) { + runnable = new MainLoop(); + } + if(null==threadGroup) { + thread = new Thread(runnable); + } else { + thread = new Thread(threadGroup, runnable); + } + thread.start(); + } + + /** Indicates whether this animator is currently running. This + should only be used as a heuristic to applications because in + some circumstances the Animator may be in the process of + shutting down and this method will still return true. */ + public synchronized boolean isAnimating() { + return (thread != null); + } + + /** Stops this animator. In most situations this method blocks until + completion, except when called from the animation thread itself + or in some cases from an implementation-internal thread like the + AWT event queue thread. */ + public synchronized void stop() { + shouldStop = true; + notifyAll(); + + // It's hard to tell whether the thread which calls stop() has + // dependencies on the Animator's internal thread. Currently we + // use a couple of heuristics to determine whether we should do + // the blocking wait(). + if (impl.skipWaitForStop(thread)) { + return; + } + + while (shouldStop && thread != null) { + try { + wait(); + } catch (InterruptedException ie) { + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java b/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java new file mode 100644 index 000000000..50b91b729 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/AnimatorImpl.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.opengl.util; + +import java.util.*; +import javax.media.opengl.*; + +/** Abstraction to factor out AWT dependencies from the Animator's + implementation in a way that still allows the FPSAnimator to pick + up this behavior if desired. */ + +class AnimatorImpl { + public void display(Animator animator, + boolean ignoreExceptions, + boolean printExceptions) { + Iterator iter = animator.drawableIterator(); + while (iter.hasNext()) { + GLAutoDrawable drawable = (GLAutoDrawable) iter.next(); + try { + drawable.display(); + } catch (RuntimeException e) { + if (ignoreExceptions) { + if (printExceptions) { + e.printStackTrace(); + } + } else { + throw(e); + } + } + } + } + + public boolean skipWaitForStop(Thread thread) { + return (Thread.currentThread() == thread); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java new file mode 100755 index 000000000..4920ed5f5 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; + +public class FBObject { + private int width, height, attr; + private int fb, fbo_tex, depth_rb, stencil_rb, vStatus; + private int texInternalFormat, texDataFormat, texDataType; + + public static final int ATTR_DEPTH = 1 << 0; + public static final int ATTR_STENCIL = 1 << 1; + + public FBObject(int width, int height, int attributes) { + this.width = width; + this.height = height; + this.attr = attributes; + } + + + public boolean validateStatus(GL gl) { + vStatus = getStatus(gl, fb); + switch(vStatus) { + case GL.GL_FRAMEBUFFER_COMPLETE: + return true; + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: + case 0: + default: + return false; + } + } + + public static int getStatus(GL gl, int fb) { + if(!gl.glIsFramebuffer(fb)) { + return -1; + } + return gl.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER); + //return gl.glCheckFramebufferStatus(fb); + } + + public String getStatusString() { + return getStatusString(vStatus); + } + + public static String getStatusString(int fbStatus) { + switch(fbStatus) { + case -1: + return "NOT A FBO"; + case GL.GL_FRAMEBUFFER_COMPLETE: + return "OK"; + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return("GL FBO: incomplete,incomplete attachment\n"); + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + return("GL FBO: Unsupported framebuffer format"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return("GL FBO: incomplete,missing attachment"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return("GL FBO: incomplete,attached images must have same dimensions"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + return("GL FBO: incomplete,attached images must have same format"); + /* + case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + return("GL FBO: incomplete,missing draw buffer"); + case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + return("GL FBO: incomplete,missing read buffer"); + case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: + return("GL FBO: incomplete, duplicate attachment"); + */ + case 0: + return("GL FBO: incomplete, implementation fault"); + default: + return("GL FBO: incomplete, implementation ERROR"); + } + } + + public void init(GL gl) { + int textureInternalFormat, textureDataFormat, textureDataType; + + if(gl.isGL2()) { + textureInternalFormat=GL.GL_RGBA8; + textureDataFormat=GL2.GL_BGRA; + textureDataType=GL2.GL_UNSIGNED_INT_8_8_8_8_REV; + } else if(gl.isGLES()) { + textureInternalFormat=GL.GL_RGBA; + textureDataFormat=GL.GL_RGBA; + textureDataType=GL.GL_UNSIGNED_BYTE; + } else { + textureInternalFormat=GL.GL_RGB; + textureDataFormat=GL.GL_RGB; + textureDataType=GL.GL_UNSIGNED_BYTE; + } + init(gl, textureInternalFormat, textureDataFormat, textureDataType); + } + + public void init(GL gl, int textureInternalFormat, int textureDataFormat, int textureDataType) { + texInternalFormat=textureInternalFormat; + texDataFormat=textureDataFormat; + texDataType=textureDataType; + + // generate fbo .. + int name[] = new int[1]; + + gl.glGenFramebuffers(1, name, 0); + fb = name[0]; + System.out.println("fb: "+fb); + + gl.glGenTextures(1, name, 0); + fbo_tex = name[0]; + System.out.println("fbo_tex: "+fbo_tex); + + if(0!=(attr&ATTR_DEPTH)) { + gl.glGenRenderbuffers(1, name, 0); + depth_rb = name[0]; + System.out.println("depth_rb: "+depth_rb); + } else { + depth_rb = 0; + } + if(0!=(attr&ATTR_STENCIL)) { + gl.glGenRenderbuffers(1, name, 0); + stencil_rb = name[0]; + System.out.println("stencil_rb: "+stencil_rb); + } else { + stencil_rb = 0; + } + + // bind fbo .. + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); + + gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex); + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, texInternalFormat, width, height, 0, + texDataFormat, texDataType, null); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + //gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP); + //gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP); + + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0, + GL.GL_TEXTURE_2D, fbo_tex, 0); + + if(depth_rb!=0) { + // Initialize the depth buffer: + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, + GL.GL_DEPTH_COMPONENT16, width, height); + // Set up the depth buffer attachment: + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_DEPTH_ATTACHMENT, + GL.GL_RENDERBUFFER, depth_rb); + } + + if(stencil_rb!=0) { + // Initialize the stencil buffer: + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, + GL.GL_STENCIL_INDEX8, width, height); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_STENCIL_ATTACHMENT, + GL.GL_RENDERBUFFER, stencil_rb); + } + + // Check the FBO for completeness + if(validateStatus(gl)) { + System.out.println("Framebuffer " + fb + " is complete"); + } else { + System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString()); + } + + unbind(gl); + } + + public void destroy(GL gl) { + unbind(gl); + + int name[] = new int[1]; + + if(0!=stencil_rb) { + name[0] = stencil_rb; + gl.glDeleteRenderbuffers(1, name, 0); + stencil_rb = 0; + } + if(0!=depth_rb) { + name[0] = depth_rb; + gl.glDeleteRenderbuffers(1, name, 0); + depth_rb=0; + } + if(0!=fbo_tex) { + name[0] = fbo_tex; + gl.glDeleteTextures(1, name, 0); + fbo_tex = 0; + } + if(0!=fb) { + name[0] = fb; + gl.glDeleteFramebuffers(1, name, 0); + fb = 0; + } + } + + public void bind(GL gl) { + gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex); + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); + } + + public void unbind(GL gl) { + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); + } + + public void use(GL gl) { + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex); // to use it .. + } + + public int getFBName() { + return fb; + } + public int getTextureName() { + return fbo_tex; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java new file mode 100755 index 000000000..75c4cdff7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/FPSAnimator.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util; + +import java.util.*; +import javax.media.opengl.*; + +/** An Animator subclass which attempts to achieve a target + frames-per-second rate to avoid using all CPU time. The target FPS + is only an estimate and is not guaranteed. */ + +public class FPSAnimator extends Animator { + private Timer timer; + private int fps; + private boolean scheduleAtFixedRate; + + /** Creates an FPSAnimator with a given target frames-per-second + value. Equivalent to <code>FPSAnimator(null, fps)</code>. */ + public FPSAnimator(int fps) { + this(null, fps); + } + + /** Creates an FPSAnimator with a given target frames-per-second + value and a flag indicating whether to use fixed-rate + scheduling. Equivalent to <code>FPSAnimator(null, fps, + scheduleAtFixedRate)</code>. */ + public FPSAnimator(int fps, boolean scheduleAtFixedRate) { + this(null, fps, scheduleAtFixedRate); + } + + /** Creates an FPSAnimator with a given target frames-per-second + value and an initial drawable to animate. Equivalent to + <code>FPSAnimator(null, fps, false)</code>. */ + public FPSAnimator(GLAutoDrawable drawable, int fps) { + this(drawable, fps, false); + } + + /** Creates an FPSAnimator with a given target frames-per-second + value, an initial drawable to animate, and a flag indicating + whether to use fixed-rate scheduling. */ + public FPSAnimator(GLAutoDrawable drawable, int fps, boolean scheduleAtFixedRate) { + this.fps = fps; + if (drawable != null) { + add(drawable); + } + this.scheduleAtFixedRate = scheduleAtFixedRate; + } + + /** Starts this FPSAnimator. */ + public synchronized void start() { + if (timer != null) { + throw new GLException("Already started"); + } + timer = new Timer(); + long delay = (long) (1000.0f / (float) fps); + TimerTask task = new TimerTask() { + public void run() { + display(); + } + }; + if (scheduleAtFixedRate) { + timer.scheduleAtFixedRate(task, 0, delay); + } else { + timer.schedule(task, 0, delay); + } + } + + /** Indicates whether this FPSAnimator is currently running. This + should only be used as a heuristic to applications because in + some circumstances the FPSAnimator may be in the process of + shutting down and this method will still return true. */ + public synchronized boolean isAnimating() { + return (timer != null); + } + + /** Stops this FPSAnimator. Due to the implementation of the + FPSAnimator it is not guaranteed that the FPSAnimator will be + completely stopped by the time this method returns. */ + public synchronized void stop() { + if (timer == null) { + throw new GLException("Already stopped"); + } + timer.cancel(); + timer = null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/FileUtil.java b/src/jogl/classes/com/jogamp/opengl/util/FileUtil.java new file mode 100755 index 000000000..6ad0da825 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/FileUtil.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util; + +import java.io.*; + +/** Utilities for dealing with files. */ + +public class FileUtil { + private FileUtil() {} + + /** + * Returns the lowercase suffix of the given file name (the text + * after the last '.' in the file name). Returns null if the file + * name has no suffix. Only operates on the given file name; + * performs no I/O operations. + * + * @param file name of the file + * @return lowercase suffix of the file name + * @throws NullPointerException if file is null + */ + + public static String getFileSuffix(File file) { + return getFileSuffix(file.getName()); + } + + /** + * Returns the lowercase suffix of the given file name (the text + * after the last '.' in the file name). Returns null if the file + * name has no suffix. Only operates on the given file name; + * performs no I/O operations. + * + * @param filename name of the file + * @return lowercase suffix of the file name + * @throws NullPointerException if filename is null + */ + public static String getFileSuffix(String filename) { + int lastDot = filename.lastIndexOf('.'); + if (lastDot < 0) { + return null; + } + return toLowerCase(filename.substring(lastDot + 1)); + } + + private static String toLowerCase(String arg) { + if (arg == null) { + return null; + } + + return arg.toLowerCase(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java b/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java new file mode 100644 index 000000000..6412db5ef --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/FixedPoint.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.util; + +public class FixedPoint { + public static final int toFixed(int value) { + if (value < -32768) value = -32768; + if (value > 32767) value = 32767; + return value * 65536; + } + + public static final int toFixed(float value) { + if (value < -32768) value = -32768; + if (value > 32767) value = 32767; + return (int)(value * 65536.0f); + } + + public static final float toFloat(int value) { + return (float)value/65536.0f; + } + + public static final int mult(int x1, int x2) { + return (int) ( ((long)x1*(long)x2)/65536 ); + } + + public static final int div(int x1, int x2) { + return (int) ( (((long)x1)<<16)/x2 ); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java new file mode 100644 index 000000000..1141f6624 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -0,0 +1,354 @@ + +package com.jogamp.opengl.util; + +import com.jogamp.common.nio.Buffers; +import java.security.*; + +import javax.media.opengl.*; + +import com.jogamp.opengl.util.glsl.*; + +import com.jogamp.opengl.impl.SystemUtil; + +import java.nio.*; + +public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayDataEditable { + + /** + * The OpenGL ES emulation on the PC probably has a buggy VBO implementation, + * where we have to 'refresh' the VertexPointer or VertexAttribArray after each + * BindBuffer ! + * + * This should not be necessary on proper native implementations. + */ + public static final boolean hasVBOBug = AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return SystemUtil.getenv("JOGL_VBO_BUG"); + } + }) != null; + + /** + * @param index The GL array index + * @param name The optional custom name for the GL array index, maybe null. + * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'. + * This name might be used as the shader attribute name. + * @param comps The array component number + * @param dataType The array index GL data type + * @param normalized Wheather the data shall be normalized + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataClient createFixed(GL gl, int index, String name, int comps, int dataType, boolean normalized, + int initialSize) + throws GLException + { + gl.getGLProfile().isValidArrayDataType(index, comps, dataType, false, true); + GLArrayDataClient adc = new GLArrayDataClient(); + GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc); + adc.init(name, index, comps, dataType, normalized, 0, null, initialSize, false, glArrayHandler, 0, 0); + return adc; + } + + public static GLArrayDataClient createFixed(GL gl, int index, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer) + throws GLException + { + gl.getGLProfile().isValidArrayDataType(index, comps, dataType, false, true); + GLArrayDataClient adc = new GLArrayDataClient(); + GLArrayHandler glArrayHandler = new GLFixedArrayHandler(adc); + adc.init(name, index, comps, dataType, normalized, stride, buffer, comps*comps, false, glArrayHandler, 0, 0); + return adc; + } + + public static GLArrayDataClient createGLSL(GL gl, String name, int comps, int dataType, boolean normalized, + int initialSize) + throws GLException + { + if(!gl.hasGLSL()) { + throw new GLException("GLArrayDataClient.GLSL not supported: "+gl); + } + gl.getGLProfile().isValidArrayDataType(-1, comps, dataType, true, true); + + GLArrayDataClient adc = new GLArrayDataClient(); + GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc); + adc.init(name, -1, comps, dataType, normalized, 0, null, initialSize, true, glArrayHandler, 0, 0); + return adc; + } + + public static GLArrayDataClient createGLSL(GL gl, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer) + throws GLException + { + if(!gl.hasGLSL()) { + throw new GLException("GLArrayDataClient.GLSL not supported: "+gl); + } + gl.getGLProfile().isValidArrayDataType(-1, comps, dataType, true, true); + + GLArrayDataClient adc = new GLArrayDataClient(); + GLArrayHandler glArrayHandler = new GLSLArrayHandler(adc); + adc.init(name, -1, comps, dataType, normalized, stride, buffer, comps*comps, true, glArrayHandler, 0, 0); + return adc; + } + + // + // Data read access + // + + public final boolean isBufferWritten() { return bufferWritten; } + + public final boolean sealed() { return sealed; } + + public int getBufferUsage() { return -1; } + + // + // Data and GL state modification .. + // + + public final void setBufferWritten(boolean written) { bufferWritten=written; } + + public void destroy(GL gl) { + reset(gl); + buffer=null; + } + + public void reset(GL gl) { + enableBuffer(gl, false); + reset(); + } + + public void seal(GL gl, boolean seal) + { + seal(seal); + if(sealedGL==seal) return; + sealedGL = seal; + if(seal) { + init_vbo(gl); + + enableBuffer(gl, true); + } else { + enableBuffer(gl, false); + } + } + + public void enableBuffer(GL gl, boolean enable) { + if(enableBufferAlways && enable) { + bufferEnabled = false; + } + if( bufferEnabled != enable && components>0 ) { + if(enable) { + checkSeal(true); + if(null!=buffer) { + buffer.rewind(); + } + } + glArrayHandler.enableBuffer(gl, enable); + bufferEnabled = enable; + } + } + + public void setEnableAlways(boolean always) { + enableBufferAlways = always; + } + + // + // Data modification .. + // + + public void reset() { + if(buffer!=null) { + buffer.clear(); + } + this.sealed=false; + this.bufferEnabled=false; + this.bufferWritten=false; + } + + public void seal(boolean seal) + { + if(sealed==seal) return; + sealed = seal; + if(seal) { + bufferWritten=false; + if (null!=buffer) { + buffer.flip(); + } + } else { + if (null!=buffer) { + buffer.position(buffer.limit()); + buffer.limit(buffer.capacity()); + } + } + } + + + public void rewind() { + if(buffer!=null) { + buffer.rewind(); + } + } + + public void padding(int done) { + if ( buffer==null || sealed ) return; + while(done<strideL) { + Buffers.putb(buffer, (byte)0); + done++; + } + } + + /** + * Generic buffer relative put method. + * + * This class buffer Class must match the arguments buffer class. + * The arguments remaining elements must be a multiple of this arrays element stride. + */ + public void put(Buffer v) { + if ( buffer==null || sealed ) return; + if(0!=(v.remaining() % strideL)) { + throw new GLException("Buffer length ("+v.remaining()+") is not a multiple of component-stride:\n\t"+this); + } + growBufferIfNecessary(v.remaining()); + Buffers.put(buffer, v); + } + + public void putb(byte v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + Buffers.putb(buffer, v); + } + + public void puts(short v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + Buffers.puts(buffer, v); + } + + public void puti(int v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + Buffers.puti(buffer, v); + } + + public void putx(int v) { + puti(v); + } + + public void putf(float v) { + if ( buffer==null || sealed ) return; + growBufferIfNecessary(1); + Buffers.putf(buffer, v); + } + + public String toString() { + return "GLArrayDataClient["+name+ + ", index "+index+ + ", location "+location+ + ", isVertexAttribute "+isVertexAttribute+ + ", dataType "+dataType+ + ", bufferClazz "+clazz+ + ", elements "+getElementNumber()+ + ", components "+components+ + ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ + ", initialSize "+initialSize+ + ", sealed "+sealed+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+ + ", buffer "+buffer+ + "]"; + } + + // non public matters + + protected final boolean growBufferIfNecessary(int spare) { + if(buffer==null || buffer.remaining()<spare) { + growBuffer(initialSize); + return true; + } + return false; + } + + protected final void growBuffer(int additional) { + if(sealed || 0==additional || 0==components) return; + + // add the stride delta + additional += (additional/components)*(strideL-components); + + if(components>0) { + int osize = (buffer!=null)?buffer.capacity():0; + if(clazz==ByteBuffer.class) { + ByteBuffer newBBuffer = Buffers.newDirectByteBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newBBuffer.put((ByteBuffer)buffer); + } + buffer = newBBuffer; + } else if(clazz==ShortBuffer.class) { + ShortBuffer newSBuffer = Buffers.newDirectShortBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newSBuffer.put((ShortBuffer)buffer); + } + buffer = newSBuffer; + } else if(clazz==IntBuffer.class) { + IntBuffer newIBuffer = Buffers.newDirectIntBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newIBuffer.put((IntBuffer)buffer); + } + buffer = newIBuffer; + } else if(clazz==FloatBuffer.class) { + FloatBuffer newFBuffer = Buffers.newDirectFloatBuffer( (osize+additional) * components ); + if(buffer!=null) { + buffer.flip(); + newFBuffer.put((FloatBuffer)buffer); + } + buffer = newFBuffer; + } else { + throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); + } + } + } + + protected final void checkSeal(boolean test) throws GLException { + if(sealed!=test) { + if(test) { + throw new GLException("Not Sealed yet, seal first:\n\t"+this); + } else { + throw new GLException("Already Sealed, can't modify VBO:\n\t"+this); + } + } + } + + protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data, + int initialSize, boolean isVertexAttribute, GLArrayHandler handler, + int vboName, long bufferOffset) + throws GLException + { + super.init(name, index, comps, dataType, normalized, stride, data, isVertexAttribute, + vboName, bufferOffset); + + this.initialSize = initialSize; + this.glArrayHandler = handler; + this.sealed=false; + this.sealedGL=false; + this.bufferEnabled=false; + this.enableBufferAlways=false; + this.bufferWritten=false; + if(null==buffer) { + growBuffer(initialSize); + } + } + + protected void init_vbo(GL gl) {} + + protected GLArrayDataClient() { } + + protected boolean sealed, sealedGL; + protected boolean bufferEnabled; + protected boolean bufferWritten; + protected boolean enableBufferAlways; + + protected int initialSize; + + protected GLArrayHandler glArrayHandler; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java new file mode 100644 index 000000000..0f8ed27be --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataEditable.java @@ -0,0 +1,110 @@ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; + +import java.nio.*; + +/** + * + * The total number of bytes hold by the referenced buffer is: + * getComponentSize()* getComponentNumber() * getElementNumber() + * + */ +public interface GLArrayDataEditable extends GLArrayData { + + public boolean sealed(); + + /** + * The VBO buffer usage, if it's an VBO, otherwise -1 + */ + public int getBufferUsage(); + + /** + * Is the buffer written to the GPU ? + */ + public boolean isBufferWritten(); + + /** + * Marks the buffer written to the GPU + */ + public void setBufferWritten(boolean written); + + // + // Data and GL state modification .. + // + + public void destroy(GL gl); + + public void reset(GL gl); + + /** + * If seal is true, it + * disable write operations to the buffer. + * Calls flip, ie limit:=position and position:=0. + * Also enables the buffer for OpenGL, and passes the data. + * + * If seal is false, it + * enable write operations continuing + * at the buffer position, where you left off at seal(true), + * ie position:=limit and limit:=capacity. + * Also disables the buffer for OpenGL. + * + * @see #seal(boolean) + */ + public void seal(GL gl, boolean seal); + + /** + * Enables/disables the buffer, which implies + * the client state, binding the VBO + * and transfering the data if not done yet. + * + * The above will only be executed, + * if the buffer is disabled, + * or 'setEnableAlways' was called with 'true'. + * + * @see #setEnableAlways(boolean) + */ + public void enableBuffer(GL gl, boolean enable); + + /** + * Affects the behavior of 'enableBuffer'. + * + * The default is 'false' + * + * This is usefull when you mix up + * GLArrayData usage with conventional GL array calls. + * + * @see #enableBuffer(GL, boolean) + */ + public void setEnableAlways(boolean always); + + // + // Data modification .. + // + + public void reset(); + + /** + * If seal is true, it + * disable write operations to the buffer. + * Calls flip, ie limit:=position and position:=0. + * + * If seal is false, it + * enable write operations continuing + * at the buffer position, where you left off at seal(true), + * ie position:=limit and limit:=capacity. + * + */ + public void seal(boolean seal); + + public void rewind(); + public void padding(int done); + public void put(Buffer v); + public void putb(byte v); + public void puts(short v); + public void puti(int v); + public void putx(int v); + public void putf(float v); +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java new file mode 100644 index 000000000..c061e212a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java @@ -0,0 +1,209 @@ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; +import java.nio.*; + +import com.jogamp.opengl.util.glsl.*; + +public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataEditable { + + // + // lifetime matters + // + + /** + * Create a VBOBuffer object, using a predefined fixed function array index + * and starting with a given Buffer object incl it's stride + * + * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. + * On profile ES2 the fixed function emulation will transform these calls to + * EnableVertexAttribArray and VertexAttribPointer calls, + * and a predefined vertex attribute variable name will be choosen. + * + * @param index The GL array index + * @param name The optional custom name for the GL array index, maybe null. + * If null, the default name mapping will be used, see 'getPredefinedArrayIndexName(int)'. + * This name might be used as the shader attribute name. + * @param comps The array component number + * @param dataType The array index GL data type + * @param normalized Wheather the data shall be normalized + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createFixed(GL gl, int index, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, int vboBufferUsage) + throws GLException + { + gl.getGLProfile().isValidArrayDataType(index, comps, dataType, false, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); + ads.init(gl, name, index, comps, dataType, normalized, stride, buffer, buffer.limit(), false, glArrayHandler, + 0, 0, vboBufferUsage); + return ads; + } + + /** + * Create a VBOBuffer object, using a predefined fixed function array index + * and starting with a new created Buffer object with initialSize size + * + * On profiles GL2 and ES1 the fixed function pipeline behavior is as expected. + * On profile ES2 the fixed function emulation will transform these calls to + * EnableVertexAttribArray and VertexAttribPointer calls, + * and a predefined vertex attribute variable name will be choosen. + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createFixed(GL gl, int index, String name, int comps, int dataType, boolean normalized, + int initialSize, int vboBufferUsage) + throws GLException + { + gl.getGLProfile().isValidArrayDataType(index, comps, dataType, false, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLFixedArrayHandler(ads); + ads.init(gl, name, index, comps, dataType, normalized, 0, null, initialSize, false, glArrayHandler, + 0, 0, vboBufferUsage); + return ads; + } + + /** + * Create a VBOBuffer object, using a custom GLSL array attribute name + * and starting with a new created Buffer object with initialSize size + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createGLSL(GL gl, String name, int comps, int dataType, boolean normalized, + int initialSize, int vboBufferUsage) + throws GLException + { + if(!gl.hasGLSL()) { + throw new GLException("GLArrayDataServer.GLSL not supported: "+gl); + } + gl.getGLProfile().isValidArrayDataType(-1, comps, dataType, true, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); + ads.init(gl, name, -1, comps, dataType, normalized, 0, null, initialSize, true, glArrayHandler, + 0, 0, vboBufferUsage); + return ads; + } + + /** + * Create a VBOBuffer object, using a custom GLSL array attribute name + * and starting with a given Buffer object incl it's stride + * + * @see javax.media.opengl.GLContext#getPredefinedArrayIndexName(int) + */ + public static GLArrayDataServer createGLSL(GL gl, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, int vboBufferUsage) + throws GLException + { + if(!gl.hasGLSL()) { + throw new GLException("GLArrayDataServer.GLSL not supported: "+gl); + } + gl.getGLProfile().isValidArrayDataType(-1, comps, dataType, true, true); + + GLArrayDataServer ads = new GLArrayDataServer(); + GLArrayHandler glArrayHandler = new GLSLArrayHandler(ads); + ads.init(gl, name, -1, comps, dataType, normalized, stride, buffer, buffer.limit(), true, glArrayHandler, + 0, 0, vboBufferUsage); + return ads; + } + + // + // Data matters GLArrayData + // + + public int getBufferUsage() { return vboBufferUsage; } + + // + // Data and GL state modification .. + // + + public void destroy(GL gl) { + super.destroy(gl); + if(vboName!=0) { + int[] tmp = new int[1]; + tmp[0] = vboName; + gl.glDeleteBuffers(1, tmp, 0); + vboName = 0; + } + } + + // + // data matters + // + + /** + * Convenient way do disable the VBO behavior and + * switch to client side data one + * Only possible if buffer is defined. + */ + public void setVBOUsage(boolean vboUsage) { + checkSeal(false); + super.setVBOUsage(vboUsage); + } + + public String toString() { + return "GLArrayDataServer["+name+ + ", index "+index+ + ", location "+location+ + ", isVertexAttribute "+isVertexAttribute+ + ", dataType "+dataType+ + ", bufferClazz "+clazz+ + ", elements "+getElementNumber()+ + ", components "+components+ + ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ + ", initialSize "+initialSize+ + ", vboBufferUsage "+vboBufferUsage+ + ", vboUsage "+vboUsage+ + ", vboName "+vboName+ + ", sealed "+sealed+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+ + ", buffer "+buffer+ + ", offset "+bufferOffset+ + "]"; + } + + // + // non public matters .. + // + + protected void init(GL gl, String name, int index, int comps, int dataType, boolean normalized, + int stride, Buffer data, int initialSize, boolean isVertexAttribute, + GLArrayHandler glArrayHandler, + int vboName, long bufferOffset, int vboBufferUsage) + throws GLException + { + super.init(name, index, comps, dataType, normalized, stride, data, initialSize, isVertexAttribute, glArrayHandler, + vboName, bufferOffset); + + vboUsage=true; + + if( ! (gl.isGL2ES2() && vboBufferUsage==GL2ES2.GL_STREAM_DRAW) ) { + switch(vboBufferUsage) { + case -1: // nop + case GL.GL_STATIC_DRAW: + case GL.GL_DYNAMIC_DRAW: + break; + default: + throw new GLException("invalid vboBufferUsage: "+vboBufferUsage+":\n\t"+this); + } + } + this.vboBufferUsage=vboBufferUsage; + } + + protected void init_vbo(GL gl) { + if(vboUsage && vboName==0) { + int[] tmp = new int[1]; + gl.glGenBuffers(1, tmp, 0); + vboName = tmp[0]; + } + } + + protected int vboBufferUsage; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java new file mode 100644 index 000000000..2ab77fa1b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -0,0 +1,215 @@ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; + +import com.jogamp.opengl.util.glsl.fixedfunc.impl.*; + +import java.nio.*; + +public class GLArrayDataWrapper implements GLArrayData { + + public static GLArrayDataWrapper createFixed(GL gl, int index, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, + int vboName, long bufferOffset) + throws GLException + { + gl.getGLProfile().isValidArrayDataType(index, comps, dataType, false, true); + GLArrayDataWrapper adc = new GLArrayDataWrapper(); + adc.init(null, index, comps, dataType, normalized, stride, buffer, false, + vboName, bufferOffset); + return adc; + } + + public static GLArrayDataWrapper createGLSL(GL gl, String name, int comps, int dataType, boolean normalized, + int stride, Buffer buffer, + int vboName, long bufferOffset) + throws GLException + { + if(!gl.hasGLSL()) { + throw new GLException("GLArrayDataWrapper.GLSL not supported: "+gl); + } + gl.getGLProfile().isValidArrayDataType(-1, comps, dataType, true, true); + + GLArrayDataWrapper adc = new GLArrayDataWrapper(); + adc.init(name, -1, comps, dataType, normalized, stride, buffer, true, + vboName, bufferOffset); + return adc; + } + + // + // Data read access + // + + public final boolean isVertexAttribute() { return isVertexAttribute; } + + public final int getIndex() { return index; } + + public final int getLocation() { return location; } + + public final void setLocation(int v) { location = v; } + + public final String getName() { return name; } + + public final long getOffset() { return vboUsage?bufferOffset:-1; } + + public final int getVBOName() { return vboUsage?vboName:-1; } + + public final boolean isVBO() { return vboUsage; } + + public final Buffer getBuffer() { return buffer; } + + public final int getComponentNumber() { return components; } + + public final int getComponentType() { return dataType; } + + public final int getComponentSize() { + if(clazz==ByteBuffer.class) { + return GLBuffers.SIZEOF_BYTE; + } + if(clazz==ShortBuffer.class) { + return GLBuffers.SIZEOF_SHORT; + } + if(clazz==IntBuffer.class) { + return GLBuffers.SIZEOF_INT; + } + if(clazz==FloatBuffer.class) { + return GLBuffers.SIZEOF_FLOAT; + } + throw new GLException("Given Buffer Class not supported: "+clazz+":\n\t"+this); + } + + public final int getElementNumber() { + if(null==buffer) return 0; + return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ; + } + + public final boolean getNormalized() { return normalized; } + + public final int getStride() { return stride; } + + public final Class getBufferClass() { return clazz; } + + public void destroy(GL gl) { + this.buffer = null; + this.components = 0; + this.stride=0; + this.strideB=0; + this.strideL=0; + this.vboName=0; + this.vboUsage=false; + this.bufferOffset=0; + } + + public String toString() { + return "GLArrayDataWrapper["+name+ + ", index "+index+ + ", location "+location+ + ", isVertexAttribute "+isVertexAttribute+ + ", dataType "+dataType+ + ", bufferClazz "+clazz+ + ", elements "+getElementNumber()+ + ", components "+components+ + ", stride "+stride+"u "+strideB+"b "+strideL+"c"+ + ", buffer "+buffer+ + ", offset "+bufferOffset+ + ", vboUsage "+vboUsage+ + ", vboName "+vboName+ + "]"; + } + + public static final Class getBufferClass(int dataType) { + switch(dataType) { + case GL.GL_BYTE: + case GL.GL_UNSIGNED_BYTE: + return ByteBuffer.class; + case GL.GL_SHORT: + case GL.GL_UNSIGNED_SHORT: + return ShortBuffer.class; + case GL2ES1.GL_FIXED: + return IntBuffer.class; + case GL.GL_FLOAT: + return FloatBuffer.class; + default: + throw new GLException("Given OpenGL data type not supported: "+dataType); + } + } + + public void setName(String newName) { + location = -1; + name = newName; + } + + public void setVBOUsage(boolean vboUsage) { + this.vboUsage=vboUsage; + } + + public void setVBOName(int vboName) { + this.vboName=vboName; + setVBOUsage(vboName>0); + } + + protected void init(String name, int index, int comps, int dataType, boolean normalized, int stride, Buffer data, + boolean isVertexAttribute, + int vboName, long bufferOffset) + throws GLException + { + this.isVertexAttribute = isVertexAttribute; + this.index = index; + this.location = -1; + // We can't have any dependence on the FixedFuncUtil class here for build bootstrapping reasons + this.name = (null==name)?FixedFuncPipeline.getPredefinedArrayIndexName(index):name; + if(null==this.name) { + throw new GLException("Not a valid GL array index: "+index); + } + this.dataType = dataType; + this.clazz = getBufferClass(dataType); + switch(dataType) { + case GL.GL_BYTE: + case GL.GL_UNSIGNED_BYTE: + case GL.GL_SHORT: + case GL.GL_UNSIGNED_SHORT: + case GL2ES1.GL_FIXED: + this.normalized = normalized; + break; + default: + this.normalized = false; + } + + int bpc = getComponentSize(); + if(0<stride && stride<comps*bpc) { + throw new GLException("stride ("+stride+") lower than component bytes, "+comps+" * "+bpc); + } + if(0<stride && stride%bpc!=0) { + throw new GLException("stride ("+stride+") not a multiple of bpc "+bpc); + } + this.buffer = data; + this.components = comps; + this.stride=stride; + this.strideB=(0==stride)?comps*bpc:stride; + this.strideL=(0==stride)?comps:strideB/bpc; + this.vboName=vboName; + this.vboUsage=vboName>0; + this.bufferOffset=bufferOffset; + } + + protected GLArrayDataWrapper() { } + + protected int index; + protected int location; + protected String name; + protected int components; + protected int dataType; + protected boolean normalized; + protected int stride; // user given stride + protected int strideB; // stride in bytes + protected int strideL; // stride in logical components + protected Class clazz; + protected Buffer buffer; + protected boolean isVertexAttribute; + + protected long bufferOffset; + protected int vboName; + protected boolean vboUsage; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java new file mode 100644 index 000000000..bfabb5b01 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayHandler.java @@ -0,0 +1,11 @@ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; + +public interface GLArrayHandler { + + public void enableBuffer(GL gl, boolean enable); + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java new file mode 100755 index 000000000..efe3a7675 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ +package com.jogamp.opengl.util; + +import com.jogamp.common.nio.Buffers; +import javax.media.opengl.GL; +import javax.media.opengl.GL2; +import javax.media.opengl.GL2ES2; + +import java.nio.*; + +/** + * Utility routines for dealing with direct buffers. + * @author Kenneth Russel + * @author Michael Bien + */ +public class GLBuffers extends Buffers { + + public static final int sizeOfGLType(int glType) { + switch (glType) { + case GL.GL_UNSIGNED_BYTE: + return SIZEOF_BYTE; + case GL.GL_BYTE: + return SIZEOF_BYTE; + case GL.GL_UNSIGNED_SHORT: + return SIZEOF_SHORT; + case GL.GL_SHORT: + return SIZEOF_SHORT; + case GL.GL_FLOAT: + return SIZEOF_FLOAT; + case GL.GL_FIXED: + return SIZEOF_INT; + case GL2ES2.GL_INT: + return SIZEOF_INT; + case GL2ES2.GL_UNSIGNED_INT: + return SIZEOF_INT; + case GL2.GL_DOUBLE: + return SIZEOF_DOUBLE; + } + return -1; + } + + public static final Buffer newDirectGLBuffer(int glType, int numElements) { + switch (glType) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + return newDirectByteBuffer(numElements); + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + return newDirectShortBuffer(numElements); + case GL.GL_FLOAT: + return newDirectFloatBuffer(numElements); + case GL.GL_FIXED: + case GL2ES2.GL_INT: + case GL2ES2.GL_UNSIGNED_INT: + return newDirectIntBuffer(numElements); + case GL2.GL_DOUBLE: + return newDirectDoubleBuffer(numElements); + } + return null; + } + + public static final Buffer sliceGLBuffer(ByteBuffer parent, int bytePos, int byteLen, int glType) { + if (parent == null || byteLen == 0) { + return null; + } + parent.position(bytePos); + parent.limit(bytePos + byteLen); + + switch (glType) { + case GL.GL_UNSIGNED_BYTE: + case GL.GL_BYTE: + return parent.slice(); + case GL.GL_UNSIGNED_SHORT: + case GL.GL_SHORT: + return parent.asShortBuffer(); + case GL.GL_FLOAT: + return parent.asFloatBuffer(); + case GL.GL_FIXED: + case GL2ES2.GL_INT: + case GL2ES2.GL_UNSIGNED_INT: + return parent.asIntBuffer(); + case GL2.GL_DOUBLE: + return parent.asDoubleBuffer(); + } + return null; + } + + //---------------------------------------------------------------------- + // Conversion routines + // + public final static float[] getFloatArray(double[] source) { + int i = source.length; + float[] dest = new float[i--]; + while (i >= 0) { + dest[i] = (float) source[i]; + i--; + } + return dest; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLFixedArrayHandler.java b/src/jogl/classes/com/jogamp/opengl/util/GLFixedArrayHandler.java new file mode 100644 index 000000000..f0f5ea896 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/GLFixedArrayHandler.java @@ -0,0 +1,65 @@ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; +import com.jogamp.opengl.util.*; +import java.nio.*; + +public class GLFixedArrayHandler implements GLArrayHandler { + private GLArrayDataEditable ad; + + public GLFixedArrayHandler(GLArrayDataEditable ad) { + this.ad = ad; + } + + protected final void passArrayPointer(GLPointerFunc gl) { + switch(ad.getIndex()) { + case GLPointerFunc.GL_VERTEX_ARRAY: + gl.glVertexPointer(ad); + break; + case GLPointerFunc.GL_NORMAL_ARRAY: + gl.glNormalPointer(ad); + break; + case GLPointerFunc.GL_COLOR_ARRAY: + gl.glColorPointer(ad); + break; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + gl.glTexCoordPointer(ad); + break; + default: + throw new GLException("invalid glArrayIndex: "+ad.getIndex()+":\n\t"+ad); + } + } + + public void enableBuffer(GL gl, boolean enable) { + GLPointerFunc glp = gl.getGL2ES1(); + if(enable) { + glp.glEnableClientState(ad.getIndex()); + + Buffer buffer = ad.getBuffer(); + + if(ad.isVBO()) { + // always bind and refresh the VBO mgr, + // in case more than one gl*Pointer objects are in use + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, ad.getVBOName()); + if(!ad.isBufferWritten()) { + if(null!=buffer) { + gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * ad.getComponentSize(), buffer, ad.getBufferUsage()); + } + ad.setBufferWritten(true); + } + passArrayPointer(glp); + } else if(null!=buffer) { + passArrayPointer(glp); + ad.setBufferWritten(true); + } + } else { + if(ad.isVBO()) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + glp.glDisableClientState(ad.getIndex()); + } + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/Gamma.java b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java new file mode 100755 index 000000000..672325cf3 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/Gamma.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.*; + +/** Provides control over the primary display's gamma, brightness and + contrast controls via the hardware gamma ramp tables. Not + supported on all platforms or graphics hardware. <P> + + Thanks to the LWJGL project for illustrating how to access gamma + control on the various platforms. +*/ + +public class Gamma { + private Gamma() {} + + /** + * Sets the gamma, brightness, and contrast of the current main + * display. This functionality is not available on all platforms and + * graphics hardware. Returns true if the settings were successfully + * changed, false if not. This method may return false for some + * values of the incoming arguments even on hardware which does + * support the underlying functionality. <P> + * + * If this method returns true, the display settings will + * automatically be reset to their original values upon JVM exit + * (assuming the JVM does not crash); if the user wishes to change + * the display settings back to normal ahead of time, use {@link + * #resetDisplayGamma resetDisplayGamma}(). It is recommended to + * call {@link #resetDisplayGamma resetDisplayGamma} before calling + * e.g. <code>System.exit()</code> from the application rather than + * rely on the shutdown hook functionality due to inevitable race + * conditions and unspecified behavior during JVM teardown. <P> + * + * This method may be called multiple times during the application's + * execution, but calling {@link #resetDisplayGamma + * resetDisplayGamma} will only reset the settings to the values + * before the first call to this method. <P> + * + * @param gamma The gamma value, typically > 1.0 (default values + * vary, but typically roughly 1.0) + * @param brightness The brightness value between -1.0 and 1.0, + * inclusive (default values vary, but typically 0) + * @param contrast The contrast, greater than 0.0 (default values + * vary, but typically 1) + * @return true if gamma settings were successfully changed, false + * if not + * @throws IllegalArgumentException if any of the parameters were + * out-of-bounds + */ + public static boolean setDisplayGamma(GL gl, float gamma, float brightness, float contrast) throws IllegalArgumentException { + return GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).setDisplayGamma(gamma, brightness, contrast); + } + + /** + * Resets the gamma, brightness and contrast values for the primary + * display to their original values before {@link #setDisplayGamma + * setDisplayGamma} was called the first time. {@link + * #setDisplayGamma setDisplayGamma} must be called before calling + * this method or an unspecified exception will be thrown. While it + * is not explicitly required that this method be called before + * exiting, calling it is recommended because of the inevitable + * unspecified behavior during JVM teardown. + */ + public static void resetDisplayGamma(GL gl) { + GLDrawableFactoryImpl.getFactoryImpl(gl.getContext().getGLDrawable().getGLProfile()).resetDisplayGamma(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java new file mode 100644 index 000000000..04b994198 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -0,0 +1,974 @@ + +package com.jogamp.opengl.util; + +import com.jogamp.common.util.*; +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; +import java.nio.*; +import java.util.Iterator; +import java.util.ArrayList; + +public class ImmModeSink { + + public static final boolean DEBUG_BEGIN_END = false; + public static final boolean DEBUG_DRAW = false; + + // public static final int GL_QUADS = 0x0007; // Needs data manipulation + public static final int GL_QUAD_STRIP = 0x0008; + public static final int GL_POLYGON = 0x0009; + + /** + * Uses a GL2ES1, or ES2 fixed function emulation immediate mode sink + */ + public static ImmModeSink createFixed(GL gl, int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType) { + return new ImmModeSink(gl, glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, false); + } + + /** + * Uses a GL2ES2 GLSL shader immediate mode sink. + * To issue the draw() command, + * a ShaderState must be current, using ShaderState.glUseProgram(). + * + * @see #draw(GL, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrent() + */ + public static ImmModeSink createGLSL(GL gl, int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType) { + return new ImmModeSink(gl, glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, true); + } + + public static boolean usesVBO() { return vboUsage; } + + public static void setVBOUsage(boolean v) { vboUsage = v; } + + public void destroy(GL gl) { + destroyList(gl); + + vboSet.destroy(gl); + } + + public void reset() { + reset(null); + } + + public void reset(GL gl) { + destroyList(gl); + vboSet.reset(gl); + } + + public String toString() { + StringBuffer sb = new StringBuffer("ImmModeSink["); + sb.append(",\n\tVBO list: "+vboSetList.size()+" ["); + for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) { + sb.append("\n\t"); + sb.append( (VBOSet)i.next() ); + } + if(vboSetList.size()>0) { + sb.append("\n\t],\nVBO current: NOP]"); + } else { + sb.append("\n\t],\nVBO current: \n"); + sb.append(vboSet); + sb.append("\n]"); + } + return sb.toString(); + } + + public void draw(GL gl, boolean disableBufferAfterDraw) { + if(DEBUG_DRAW) { + Exception e = new Exception("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); + e.printStackTrace(); + } + int n=0; + for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) { + ((VBOSet)i.next()).draw(gl, null, disableBufferAfterDraw, n); + } + } + + public void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw) { + if(DEBUG_DRAW) { + Exception e = new Exception("ImmModeSink.draw(disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); + e.printStackTrace(); + } + int n=0; + for(Iterator i=vboSetList.iterator(); i.hasNext() ; n++) { + ((VBOSet)i.next()).draw(gl, indices, disableBufferAfterDraw, n); + } + } + + public void glBegin(int mode) { + if(DEBUG_BEGIN_END) { + Exception e = new Exception("ImmModeSink.glBegin("+vboSet.mode+"):\n\t"+this); + e.printStackTrace(); + } + vboSet.modeOrig = mode; + switch(mode) { + // Needs data manipulation .. + //case GL_QUADS: + // mode=GL.GL_LINES; + // break; + case GL_QUAD_STRIP: + mode=GL.GL_TRIANGLE_STRIP; + break; + case GL_POLYGON: + mode=GL.GL_LINES; + break; + } + vboSet.mode = mode; + vboSet.checkSeal(false); + } + + public final void glEnd(GL gl) { + glEnd(gl, null, true); + } + + public void glEnd(GL gl, boolean immediateDraw) { + glEnd(gl, null, immediateDraw); + } + + public final void glEnd(GL gl, Buffer indices) { + glEnd(gl, indices, true); + } + + private void glEnd(GL gl, Buffer indices, boolean immediateDraw) { + if(DEBUG_BEGIN_END) { + Exception e = new Exception("ImmModeSink START glEnd(immediate: "+immediateDraw+"):\n\t"+this); + e.printStackTrace(); + } + if(immediateDraw) { + vboSet.seal(gl, true); + vboSet.draw(gl, indices, true, -1); + reset(gl); + } else { + vboSet.seal(gl, true); + vboSet.enableBuffer(gl, false); + vboSetList.add(vboSet); + vboSet = vboSet.regenerate(); + } + } + + public void glVertexv(Buffer v) { + vboSet.glVertexv(v); + } + public void glNormalv(Buffer v) { + vboSet.glNormalv(v); + } + public void glColorv(Buffer v) { + vboSet.glColorv(v); + } + public void glTexCoordv(Buffer v) { + vboSet.glTexCoordv(v); + } + + public final void glVertex2f(float x, float y) { + vboSet.glVertex2f(x,y); + } + + public final void glVertex3f(float x, float y, float z) { + vboSet.glVertex3f(x,y,z); + } + + public final void glNormal3f(float x, float y, float z) { + vboSet.glNormal3f(x,y,z); + } + + public final void glColor3f(float x, float y, float z) { + vboSet.glColor3f(x,y,z); + } + + public final void glColor4f(float x, float y, float z, float a) { + vboSet.glColor4f(x,y,z, a); + } + + public final void glTexCoord2f(float x, float y) { + vboSet.glTexCoord2f(x,y); + } + + public final void glTexCoord3f(float x, float y, float z) { + vboSet.glTexCoord3f(x,y,z); + } + + public final void glVertex2s(short x, short y) { + vboSet.glVertex2s(x,y); + } + + public final void glVertex3s(short x, short y, short z) { + vboSet.glVertex3s(x,y,z); + } + + public final void glNormal3s(short x, short y, short z) { + vboSet.glNormal3s(x,y,z); + } + + public final void glColor3s(short x, short y, short z) { + vboSet.glColor3s(x,y,z); + } + + public final void glColor4s(short x, short y, short z, short a) { + vboSet.glColor4s(x,y,z,a); + } + + public final void glTexCoord2s(short x, short y) { + vboSet.glTexCoord2s(x,y); + } + + public final void glTexCoord3s(short x, short y, short z) { + vboSet.glTexCoord3s(x,y,z); + } + + public final void glVertex2b(byte x, byte y) { + vboSet.glVertex2b(x,y); + } + + public final void glVertex3b(byte x, byte y, byte z) { + vboSet.glVertex3b(x,y,z); + } + + public final void glNormal3b(byte x, byte y, byte z) { + vboSet.glNormal3b(x,y,z); + } + + public final void glColor3b(byte x, byte y, byte z) { + vboSet.glColor3b(x,y,z); + } + + public final void glColor4b(byte x, byte y, byte z, byte a) { + vboSet.glColor4b(x,y,z,a); + } + + public final void glTexCoord2b(byte x, byte y) { + vboSet.glTexCoord2b(x,y); + } + + public final void glTexCoord3b(byte x, byte y, byte z) { + vboSet.glTexCoord3b(x,y,z); + } + + protected ImmModeSink(GL gl, int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, boolean useGLSL) { + if(useGLSL && !gl.hasGLSL()) { + throw new GLException("ImmModeSink GLSL usage not supported: "+gl); + } + vboSet = new VBOSet(gl, glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + this.vboSetList = new ArrayList(); + } + + private void destroyList(GL gl) { + for(Iterator i=vboSetList.iterator(); i.hasNext() ; ) { + ((VBOSet)i.next()).destroy(gl); + } + vboSetList.clear(); + } + + private VBOSet vboSet; + private ArrayList vboSetList; + private static boolean vboUsage = true; + + protected static class VBOSet { + protected VBOSet (GL gl, int glBufferUsage, int initialSize, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, boolean useGLSL) { + this.gl=gl; + this.glBufferUsage=glBufferUsage; + this.initialSize=initialSize; + this.vDataType=vDataType; + this.vComps=vComps; + this.cDataType=cDataType; + this.cComps=cComps; + this.nDataType=nDataType; + this.nComps=nComps; + this.tDataType=tDataType; + this.tComps=tComps; + this.useGLSL=useGLSL; + + allocateBuffer(initialSize); + rewind(); + + this.sealed=false; + this.sealedGL=false; + this.mode = -1; + this.modeOrig = -1; + this.bufferEnabled=false; + this.bufferWritten=false; + } + + protected final VBOSet regenerate() { + return new VBOSet(gl, glBufferUsage, initialSize, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL); + } + + protected void checkSeal(boolean test) throws GLException { + if(mode<0) { + throw new GLException("No mode set yet, call glBegin(mode) first:\n\t"+this); + } + if(sealed!=test) { + if(test) { + throw new GLException("Not Sealed yet, call glEnd() first:\n\t"+this); + } else { + throw new GLException("Already Sealed, can't modify VBO after glEnd():\n\t"+this); + } + } + } + + protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i) + { + if(DEBUG_DRAW) { + Exception e = new Exception("ImmModeSink.draw["+i+"](disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); + e.printStackTrace(); + } + enableBuffer(gl, true); + + if (buffer!=null) { + GL2ES1 glf = gl.getGL2ES1(); + + if(null==indices) { + glf.glDrawArrays(mode, 0, count); + } else { + Class clazz = indices.getClass(); + int type=-1; + if(ReflectionUtil.instanceOf(clazz, ByteBuffer.class.getName())) { + type = GL.GL_UNSIGNED_BYTE; + } else if(ReflectionUtil.instanceOf(clazz, ShortBuffer.class.getName())) { + type = GL.GL_UNSIGNED_SHORT; + } + if(0>type) { + throw new GLException("Given Buffer Class not supported: "+clazz+", should be ubyte or ushort:\n\t"+this); + } + glf.glDrawElements(mode, indices.remaining(), type, indices); + // GL2: gl.glDrawRangeElements(mode, 0, indices.remaining()-1, indices.remaining(), type, indices); + } + } + + if(disableBufferAfterDraw) { + enableBuffer(gl, false); + } + } + + public void glVertexv(Buffer v) { + checkSeal(false); + GLBuffers.put(vertexArray, v); + } + public void glNormalv(Buffer v) { + checkSeal(false); + GLBuffers.put(normalArray, v); + } + public void glColorv(Buffer v) { + checkSeal(false); + GLBuffers.put(colorArray, v); + } + public void glTexCoordv(Buffer v) { + checkSeal(false); + GLBuffers.put(textCoordArray, v); + } + + public void glVertex2b(byte x, byte y) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 2); + if(vComps>0) + GLBuffers.putb(vertexArray, x); + if(vComps>1) + GLBuffers.putb(vertexArray, y); + padding(VERTEX, vComps-2); + } + public void glVertex3b(byte x, byte y, byte z) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 3); + if(vComps>0) + GLBuffers.putb(vertexArray, x); + if(vComps>1) + GLBuffers.putb(vertexArray, y); + if(vComps>2) + GLBuffers.putb(vertexArray, z); + padding(VERTEX, vComps-3); + } + public void glVertex2s(short x, short y) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 2); + if(vComps>0) + GLBuffers.puts(vertexArray, x); + if(vComps>1) + GLBuffers.puts(vertexArray, y); + padding(VERTEX, vComps-2); + } + public void glVertex3s(short x, short y, short z) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 3); + if(vComps>0) + GLBuffers.puts(vertexArray, x); + if(vComps>1) + GLBuffers.puts(vertexArray, y); + if(vComps>2) + GLBuffers.puts(vertexArray, z); + padding(VERTEX, vComps-3); + } + public void glVertex2f(float x, float y) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 2); + if(vComps>0) + GLBuffers.putf(vertexArray, x); + if(vComps>1) + GLBuffers.putf(vertexArray, y); + padding(VERTEX, vComps-2); + } + public void glVertex3f(float x, float y, float z) { + checkSeal(false); + growBufferIfNecessary(VERTEX, 3); + if(vComps>0) + GLBuffers.putf(vertexArray, x); + if(vComps>1) + GLBuffers.putf(vertexArray, y); + if(vComps>2) + GLBuffers.putf(vertexArray, z); + padding(VERTEX, vComps-3); + } + + public void glNormal3b(byte x, byte y, byte z) { + checkSeal(false); + growBufferIfNecessary(NORMAL, 3); + if(nComps>0) + GLBuffers.putb(normalArray, x); + if(nComps>1) + GLBuffers.putb(normalArray, y); + if(nComps>2) + GLBuffers.putb(normalArray, z); + padding(NORMAL, nComps-3); + } + public void glNormal3s(short x, short y, short z) { + checkSeal(false); + growBufferIfNecessary(NORMAL, 3); + if(nComps>0) + GLBuffers.puts(normalArray, x); + if(nComps>1) + GLBuffers.puts(normalArray, y); + if(nComps>2) + GLBuffers.puts(normalArray, z); + padding(NORMAL, nComps-3); + } + public void glNormal3f(float x, float y, float z) { + checkSeal(false); + growBufferIfNecessary(NORMAL, 3); + if(nComps>0) + GLBuffers.putf(normalArray, x); + if(nComps>1) + GLBuffers.putf(normalArray, y); + if(nComps>2) + GLBuffers.putf(normalArray, z); + padding(NORMAL, nComps-3); + } + + public void glColor3b(byte r, byte g, byte b) { + checkSeal(false); + growBufferIfNecessary(COLOR, 3); + if(cComps>0) + GLBuffers.putb(colorArray, r); + if(cComps>1) + GLBuffers.putb(colorArray, g); + if(cComps>2) + GLBuffers.putb(colorArray, b); + padding(COLOR, cComps-3); + } + public void glColor4b(byte r, byte g, byte b, byte a) { + checkSeal(false); + growBufferIfNecessary(COLOR, 4); + if(cComps>0) + GLBuffers.putb(colorArray, r); + if(cComps>1) + GLBuffers.putb(colorArray, g); + if(cComps>2) + GLBuffers.putb(colorArray, b); + if(cComps>3) + GLBuffers.putb(colorArray, a); + padding(COLOR, cComps-4); + } + public void glColor3s(short r, short g, short b) { + checkSeal(false); + growBufferIfNecessary(COLOR, 3); + if(cComps>0) + GLBuffers.puts(colorArray, r); + if(cComps>1) + GLBuffers.puts(colorArray, g); + if(cComps>2) + GLBuffers.puts(colorArray, b); + padding(COLOR, cComps-3); + } + public void glColor4s(short r, short g, short b, short a) { + checkSeal(false); + growBufferIfNecessary(COLOR, 4); + if(cComps>0) + GLBuffers.puts(colorArray, r); + if(cComps>1) + GLBuffers.puts(colorArray, g); + if(cComps>2) + GLBuffers.puts(colorArray, b); + if(cComps>3) + GLBuffers.puts(colorArray, a); + padding(COLOR, cComps-4); + } + public void glColor3f(float r, float g, float b) { + checkSeal(false); + growBufferIfNecessary(COLOR, 3); + if(cComps>0) + GLBuffers.putf(colorArray, r); + if(cComps>1) + GLBuffers.putf(colorArray, g); + if(cComps>2) + GLBuffers.putf(colorArray, b); + padding(COLOR, cComps-3); + } + public void glColor4f(float r, float g, float b, float a) { + checkSeal(false); + growBufferIfNecessary(COLOR, 4); + if(cComps>0) + GLBuffers.putf(colorArray, r); + if(cComps>1) + GLBuffers.putf(colorArray, g); + if(cComps>2) + GLBuffers.putf(colorArray, b); + if(cComps>3) + GLBuffers.putf(colorArray, a); + padding(COLOR, cComps-4); + } + + public void glTexCoord2b(byte x, byte y) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 2); + if(tComps>0) + GLBuffers.putb(textCoordArray, x); + if(tComps>1) + GLBuffers.putb(textCoordArray, y); + padding(TEXTCOORD, tComps-2); + } + public void glTexCoord3b(byte x, byte y, byte z) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 3); + if(tComps>0) + GLBuffers.putb(textCoordArray, x); + if(tComps>1) + GLBuffers.putb(textCoordArray, y); + if(tComps>2) + GLBuffers.putb(textCoordArray, z); + padding(TEXTCOORD, tComps-3); + } + public void glTexCoord2s(short x, short y) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 2); + if(tComps>0) + GLBuffers.puts(textCoordArray, x); + if(tComps>1) + GLBuffers.puts(textCoordArray, y); + padding(TEXTCOORD, tComps-2); + } + public void glTexCoord3s(short x, short y, short z) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 3); + if(tComps>0) + GLBuffers.puts(textCoordArray, x); + if(tComps>1) + GLBuffers.puts(textCoordArray, y); + if(tComps>2) + GLBuffers.puts(textCoordArray, z); + padding(TEXTCOORD, tComps-3); + } + public void glTexCoord2f(float x, float y) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 2); + if(tComps>0) + GLBuffers.putf(textCoordArray, x); + if(tComps>1) + GLBuffers.putf(textCoordArray, y); + padding(TEXTCOORD, tComps-2); + } + public void glTexCoord3f(float x, float y, float z) { + checkSeal(false); + growBufferIfNecessary(TEXTCOORD, 3); + if(tComps>0) + GLBuffers.putf(textCoordArray, x); + if(tComps>1) + GLBuffers.putf(textCoordArray, y); + if(tComps>2) + GLBuffers.putf(textCoordArray, z); + padding(TEXTCOORD, tComps-3); + } + + public void rewind() { + if(null!=vertexArray) { + vertexArray.rewind(); + } + if(null!=colorArray) { + colorArray.rewind(); + } + if(null!=normalArray) { + normalArray.rewind(); + } + if(null!=textCoordArray) { + textCoordArray.rewind(); + } + } + + public void destroy(GL gl) { + reset(gl); + + vertexArray=null; colorArray=null; normalArray=null; textCoordArray=null; + vArrayData=null; cArrayData=null; nArrayData=null; tArrayData=null; + buffer=null; + bSize=0; count=0; + } + + public void reset(GL gl) { + enableBuffer(gl, false); + reset(); + } + + public void reset() { + if(buffer!=null) { + buffer.clear(); + } + rewind(); + + this.mode = -1; + this.modeOrig = -1; + this.sealed=false; + this.bufferEnabled=false; + this.bufferWritten=false; + } + + public void seal(GL glObj, boolean seal) + { + seal(seal); + if(sealedGL==seal) return; + sealedGL = seal; + GL gl = glObj.getGL(); + if(seal) { + if(vboUsage && vboName==0) { + int[] tmp = new int[1]; + gl.glGenBuffers(1, tmp, 0); + vboName = tmp[0]; + } + if(null!=vArrayData) + vArrayData.setVBOName(vboName); + if(null!=cArrayData) + cArrayData.setVBOName(vboName); + if(null!=nArrayData) + nArrayData.setVBOName(vboName); + if(null!=tArrayData) + tArrayData.setVBOName(vboName); + enableBuffer(gl, true); + } else { + enableBuffer(gl, false); + } + } + + public void seal(boolean seal) + { + if(sealed==seal) return; + sealed = seal; + if(seal) { + bufferWritten=false; + } + } + + public void enableBuffer(GL gl, boolean enable) { + /* if(enableBufferAlways && enable) { + bufferEnabled = false; + } */ + if( bufferEnabled != enable && count>0 ) { + if(enable) { + checkSeal(true); + } + if(useGLSL) { + enableBufferGLSL(gl, enable); + } else { + enableBufferFixed(gl, enable); + } + bufferEnabled = enable; + } + } + + public void enableBufferFixed(GL gl, boolean enable) { + GL2ES1 glf = gl.getGL2ES1(); + + if(enable) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + + if(!bufferWritten) { + gl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); + bufferWritten=true; + } + + if(vComps>0) { + glf.glEnableClientState(glf.GL_VERTEX_ARRAY); + glf.glVertexPointer(vArrayData); + } + if(cComps>0) { + glf.glEnableClientState(glf.GL_COLOR_ARRAY); + glf.glColorPointer(cArrayData); + } + if(nComps>0) { + glf.glEnableClientState(glf.GL_NORMAL_ARRAY); + glf.glNormalPointer(nArrayData); + } + if(tComps>0) { + glf.glEnableClientState(glf.GL_TEXTURE_COORD_ARRAY); + glf.glTexCoordPointer(tArrayData); + } + + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } else { + if(vComps>0) { + glf.glDisableClientState(glf.GL_VERTEX_ARRAY); + } + if(cComps>0) { + glf.glDisableClientState(glf.GL_COLOR_ARRAY); + } + if(nComps>0) { + glf.glDisableClientState(glf.GL_NORMAL_ARRAY); + } + if(tComps>0) { + glf.glDisableClientState(glf.GL_TEXTURE_COORD_ARRAY); + } + } + } + + public void enableBufferGLSL(GL gl, boolean enable) { + GL2ES2 glsl = gl.getGL2ES2(); + com.jogamp.opengl.util.glsl.ShaderState st = com.jogamp.opengl.util.glsl.ShaderState.getCurrent(); + if(null==st) { + throw new GLException("No ShaderState current"); + } + + if(enable) { + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + + if(!bufferWritten) { + glsl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit(), buffer, GL.GL_STATIC_DRAW); + bufferWritten=true; + } + + if(vComps>0) { + st.glEnableVertexAttribArray(glsl, vArrayData.getName()); + st.glVertexAttribPointer(glsl, vArrayData); + } + if(cComps>0) { + st.glEnableVertexAttribArray(glsl, cArrayData.getName()); + st.glVertexAttribPointer(glsl, cArrayData); + } + if(nComps>0) { + st.glEnableVertexAttribArray(glsl, nArrayData.getName()); + st.glVertexAttribPointer(glsl, nArrayData); + } + if(tComps>0) { + st.glEnableVertexAttribArray(glsl, tArrayData.getName()); + st.glVertexAttribPointer(glsl, tArrayData); + } + + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } else { + if(vComps>0) { + st.glDisableVertexAttribArray(glsl, vArrayData.getName()); + } + if(cComps>0) { + st.glDisableVertexAttribArray(glsl, cArrayData.getName()); + } + if(nComps>0) { + st.glDisableVertexAttribArray(glsl, nArrayData.getName()); + } + if(tComps>0) { + st.glDisableVertexAttribArray(glsl, tArrayData.getName()); + } + } + } + + public String toString() { + return "VBOSet[mode "+mode+ + ", modeOrig "+modeOrig+ + ", sealed "+sealed+ + ", bufferEnabled "+bufferEnabled+ + ", bufferWritten "+bufferWritten+ + ",\n\t"+vArrayData+ + ",\n\t"+cArrayData+ + ",\n\t"+nArrayData+ + ",\n\t"+tArrayData+ + "]"; + } + + // non public matters + + protected void allocateBuffer(int elements) { + int vWidth = vComps * GLBuffers.sizeOfGLType(vDataType); + int cWidth = cComps * GLBuffers.sizeOfGLType(cDataType); + int nWidth = nComps * GLBuffers.sizeOfGLType(nDataType); + int tWidth = tComps * GLBuffers.sizeOfGLType(tDataType); + + count = elements; + bSize = count * ( vWidth + cWidth + nWidth + tWidth ) ; + + buffer = GLBuffers.newDirectByteBuffer(bSize); + + int pos = 0; + int size= count * vWidth ; + if(size>0) { + vertexArray = GLBuffers.sliceGLBuffer(buffer, pos, size, vDataType); + } else { + vertexArray = null; + } + vOffset = pos; + pos+=size; + + size= count * cWidth ; + if(size>0) { + colorArray = GLBuffers.sliceGLBuffer(buffer, pos, size, cDataType); + } else { + colorArray = null; + } + cOffset = pos; + pos+=size; + + size= count * nWidth ; + if(size>0) { + normalArray = GLBuffers.sliceGLBuffer(buffer, pos, size, nDataType); + } else { + normalArray = null; + } + nOffset = pos; + pos+=size; + + size= count * tWidth ; + if(size>0) { + textCoordArray = GLBuffers.sliceGLBuffer(buffer, pos, size, tDataType); + } else { + textCoordArray = null; + } + tOffset = pos; + pos+=size; + + buffer.position(pos); + buffer.flip(); + + if(vComps>0) { + vArrayData = GLArrayDataWrapper.createFixed(gl, GLPointerFunc.GL_VERTEX_ARRAY, vComps, vDataType, false, + 0, vertexArray, 0, vOffset); + } else { + vArrayData = null; + } + if(cComps>0) { + cArrayData = GLArrayDataWrapper.createFixed(gl, GLPointerFunc.GL_COLOR_ARRAY, cComps, cDataType, false, + 0, colorArray, 0, cOffset); + } else { + cArrayData = null; + } + if(nComps>0) { + nArrayData = GLArrayDataWrapper.createFixed(gl, GLPointerFunc.GL_NORMAL_ARRAY, nComps, nDataType, false, + 0, normalArray, 0, nOffset); + } else { + nArrayData = null; + } + if(tComps>0) { + tArrayData = GLArrayDataWrapper.createFixed(gl, GLPointerFunc.GL_TEXTURE_COORD_ARRAY, tComps, tDataType, false, + 0, textCoordArray, 0, tOffset); + } else { + tArrayData = null; + } + + } + + protected final boolean growBufferIfNecessary(int type, int spare) { + if(buffer==null || count < spare) { + growBuffer(type, initialSize); + return true; + } + return false; + } + + protected final void growBuffer(int type, int additional) { + if(sealed || 0==additional) return; + + // save olde values .. + Buffer _vertexArray=vertexArray, _colorArray=colorArray, _normalArray=normalArray, _textCoordArray=textCoordArray; + ByteBuffer _buffer = buffer; + + allocateBuffer(count+additional); + + if(null!=_vertexArray) { + _vertexArray.flip(); + GLBuffers.put(vertexArray, _vertexArray); + } + if(null!=_colorArray) { + _colorArray.flip(); + GLBuffers.put(colorArray, _colorArray); + } + if(null!=_normalArray) { + _normalArray.flip(); + GLBuffers.put(normalArray, _normalArray); + } + if(null!=_textCoordArray) { + _textCoordArray.flip(); + GLBuffers.put(textCoordArray, _textCoordArray); + } + } + + protected void padding(int type, int fill) { + if ( sealed ) return; + + Buffer dest = null; + + switch (type) { + case VERTEX: + dest = vertexArray; + break; + case COLOR: + dest = colorArray; + break; + case NORMAL: + dest = normalArray; + break; + case TEXTCOORD: + dest = textCoordArray; + break; + } + + if ( null==dest ) return; + + while((fill--)>0) { + GLBuffers.putb(dest, (byte)0); + } + } + + protected int mode, modeOrig; + protected int glBufferUsage, initialSize; + + protected ByteBuffer buffer; + protected int bSize, count, vboName; + + public static final int VERTEX = 0; + public static final int COLOR = 1; + public static final int NORMAL = 2; + public static final int TEXTCOORD = 3; + + protected int vOffset, cOffset, nOffset, tOffset; + protected int vComps, cComps, nComps, tComps; + protected int vDataType, cDataType, nDataType, tDataType; + protected Buffer vertexArray, colorArray, normalArray, textCoordArray; + protected GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData; + + protected boolean sealed, sealedGL, useGLSL; + protected boolean bufferEnabled, bufferWritten; + protected GL gl; + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/Locator.java b/src/jogl/classes/com/jogamp/opengl/util/Locator.java new file mode 100644 index 000000000..c524c0888 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/Locator.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.util; + +import java.util.*; +import java.nio.*; +import java.io.*; +import java.net.*; + +/** Utilities for dealing with resources. */ + +public class Locator { + private Locator() {} + + /** + * Locates the resource using 'getResource(String path, ClassLoader cl)', + * with this context ClassLoader and the path as is, + * as well with the context's package name path plus the path. + * + * @see #getResource(String, ClassLoader) + */ + public static URL getResource(Class context, String path) { + ClassLoader contextCL = (null!=context)?context.getClassLoader():null; + URL url = getResource(path, contextCL); + if (url == null && null!=context) { + // Try again by scoping the path within the class's package + String className = context.getName().replace('.', '/'); + int lastSlash = className.lastIndexOf('/'); + if (lastSlash >= 0) { + String tmpPath = className.substring(0, lastSlash + 1) + path; + url = getResource(tmpPath, contextCL); + } + } + return url; + } + + /** + * Locates the resource using the ClassLoader's facility, + * the absolute URL and absolute file. + * + * @see ClassLoader#getResource(String) + * @see ClassLoader#getSystemResource(String) + * @see URL#URL(String) + * @see File#File(String) + */ + public static URL getResource(String path, ClassLoader cl) { + URL url = null; + if (cl != null) { + url = cl.getResource(path); + } else { + url = ClassLoader.getSystemResource(path); + } + if(!urlExists(url)) { + url = null; + try { + url = new URL(path); + } catch (MalformedURLException e) { } + } + if(!urlExists(url)) { + url = null; + try { + File file = new File(path); + if(file.exists()) { + url = file.toURL(); + } + } catch (MalformedURLException e) {} + } + return url; + } + + /** + * Generates a path for the 'relativeFile' relative to the 'absoluteFileLocation' + */ + public static String getRelativeOf(String absoluteFileLocation, String relativeFile) { + File file = new File(absoluteFileLocation); + file = file.getParentFile(); + while (file != null && relativeFile.startsWith("../")) { + file = file.getParentFile(); + relativeFile = relativeFile.substring(3); + } + if (file != null) { + String res = new File(file, relativeFile).getPath(); + // Handle things on Windows + return res.replace('\\', '/'); + } else { + return relativeFile; + } + } + + /** + * Returns true, if the url exists, + * trying to open a connection. + */ + public static boolean urlExists(URL url) { + boolean v = false; + if(null!=url) { + try { + URLConnection uc = url.openConnection(); + v = true; + } catch (IOException ioe) { } + } + return v; + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java new file mode 100755 index 000000000..47de8ce0a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/PMVMatrix.java @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.util; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.impl.ProjectFloat; + +import java.nio.*; +import java.util.ArrayList; +import java.util.List; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +public class PMVMatrix implements GLMatrixFunc { + + public PMVMatrix() { + projectFloat = new ProjectFloat(); + + matrixIdent = Buffers.newDirectFloatBuffer(1*16); + projectFloat.gluMakeIdentityf(matrixIdent); + matrixIdent.rewind(); + + // T Texture + // P Projection + // Mv ModelView + // Mvi Modelview-Inverse + // Mvit Modelview-Inverse-Transpose + // Pmv P * Mv + matrixTPMvMvitPmv = Buffers.newDirectFloatBuffer(6*16); // grouping T + P + Mv + Mvi + Mvit + Pmv + matrixPMvMvitPmv = slice(matrixTPMvMvitPmv, 1*16, 5*16); // grouping P + Mv + Mvi + Mvit + Pmv + matrixT = slice(matrixTPMvMvitPmv, 0*16, 1*16); // T + matrixPMvMvit = slice(matrixTPMvMvitPmv, 1*16, 4*16); // grouping P + Mv + Mvi + Mvit + matrixPMvMvi = slice(matrixTPMvMvitPmv, 1*16, 3*16); // grouping P + Mv + Mvi + matrixPMv = slice(matrixTPMvMvitPmv, 1*16, 2*16); // grouping P + Mv + matrixP = slice(matrixTPMvMvitPmv, 1*16, 1*16); // P + matrixMv = slice(matrixTPMvMvitPmv, 2*16, 1*16); // Mv + matrixMvi = slice(matrixTPMvMvitPmv, 3*16, 1*16); // Mvi + matrixMvit = slice(matrixTPMvMvitPmv, 4*16, 1*16); // Mvit + matrixPmv = slice(matrixTPMvMvitPmv, 5*16, 1*16); // Pmv + matrixTPMvMvitPmv.rewind(); + + matrixMvit3 = Buffers.newDirectFloatBuffer(3*3); + + localBuf = Buffers.newDirectFloatBuffer(6*16); + + matrixMult=slice(localBuf, 0*16, 16); + + matrixTrans=slice(localBuf, 1*16, 16); + projectFloat.gluMakeIdentityf(matrixTrans); + + matrixRot=slice(localBuf, 2*16, 16); + projectFloat.gluMakeIdentityf(matrixRot); + + matrixScale=slice(localBuf, 3*16, 16); + projectFloat.gluMakeIdentityf(matrixScale); + + matrixOrtho=slice(localBuf, 4*16, 16); + projectFloat.gluMakeIdentityf(matrixOrtho); + + matrixFrustum=slice(localBuf, 5*16, 16); + projectFloat.gluMakeZero(matrixFrustum); + + vec3f=new float[3]; + + matrixPStack = new ArrayList(); + matrixMvStack= new ArrayList(); + + // default values and mode + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glMatrixMode(GL.GL_TEXTURE); + glLoadIdentity(); + setDirty(); + } + + public void destroy() { + if(null!=projectFloat) { + projectFloat.destroy(); projectFloat=null; + } + + if(null!=matrixIdent) { + matrixIdent.clear(); matrixIdent=null; + } + if(null!=matrixTPMvMvitPmv) { + matrixTPMvMvitPmv.clear(); matrixTPMvMvitPmv=null; + } + if(null!=matrixMvit3) { + matrixMvit3.clear(); matrixMvit3=null; + } + if(null!=localBuf) { + localBuf.clear(); localBuf=null; + } + + if(null!=matrixPStack) { + matrixPStack.clear(); matrixPStack=null; + } + vec3f=null; + if(null!=matrixMvStack) { + matrixMvStack.clear(); matrixMvStack=null; + } + if(null!=matrixPStack) { + matrixPStack.clear(); matrixPStack=null; + } + if(null!=matrixTStack) { + matrixTStack.clear(); matrixTStack=null; + } + + matrixTPMvMvitPmv=null; matrixPMvMvit=null; matrixPMvMvitPmv=null; matrixPMvMvi=null; matrixPMv=null; + matrixP=null; matrixT=null; matrixMv=null; matrixMvi=null; matrixMvit=null; matrixPmv=null; + matrixMult=null; matrixTrans=null; matrixRot=null; matrixScale=null; matrixOrtho=null; matrixFrustum=null; + } + + private static FloatBuffer slice(FloatBuffer buf, int pos, int len) { + buf.position(pos); + buf.limit(pos + len); + return buf.slice(); + } + + public static final boolean isMatrixModeName(final int matrixModeName) { + switch(matrixModeName) { + case GL_MODELVIEW_MATRIX: + case GL_PROJECTION_MATRIX: + case GL_TEXTURE_MATRIX: + return true; + } + return false; + } + + public static final int matrixModeName2MatrixGetName(final int matrixModeName) { + switch(matrixModeName) { + case GL_MODELVIEW: + return GL_MODELVIEW_MATRIX; + case GL_PROJECTION: + return GL_PROJECTION_MATRIX; + case GL.GL_TEXTURE: + return GL_TEXTURE_MATRIX; + default: + throw new GLException("unsupported matrixName: "+matrixModeName); + } + } + + public static final boolean isMatrixGetName(final int matrixGetName) { + switch(matrixGetName) { + case GL_MATRIX_MODE: + case GL_MODELVIEW_MATRIX: + case GL_PROJECTION_MATRIX: + case GL_TEXTURE_MATRIX: + return true; + } + return false; + } + + public static final int matrixGetName2MatrixModeName(final int matrixGetName) { + switch(matrixGetName) { + case GL_MODELVIEW_MATRIX: + return GL_MODELVIEW; + case GL_PROJECTION_MATRIX: + return GL_PROJECTION; + case GL_TEXTURE_MATRIX: + return GL.GL_TEXTURE; + default: + throw new GLException("unsupported matrixGetName: "+matrixGetName); + } + } + + public void setDirty() { + modified = DIRTY_MODELVIEW | DIRTY_PROJECTION | DIRTY_TEXTURE ; + matrixMode = GL_MODELVIEW; + } + + public int getDirtyBits() { + return modified; + } + + public boolean isDirty(final int matrixName) { + boolean res; + switch(matrixName) { + case GL_MODELVIEW: + res = (modified&DIRTY_MODELVIEW)!=0 ; + break; + case GL_PROJECTION: + res = (modified&DIRTY_PROJECTION)!=0 ; + break; + case GL.GL_TEXTURE: + res = (modified&DIRTY_TEXTURE)!=0 ; + break; + default: + throw new GLException("unsupported matrixName: "+matrixName); + } + return res; + } + + public boolean isDirty() { + return modified!=0; + } + + public boolean update() { + // if(0==modified) return false; + + // int res = modified; + int res = DIRTY_MODELVIEW | DIRTY_PROJECTION ; + if( (res&DIRTY_MODELVIEW)!=0 ) { + setMviMvit(); + } + if( (res&DIRTY_MODELVIEW)!=0 || (res&DIRTY_PROJECTION)!=0 ) { + glMultMatrixf(matrixP, matrixMv, matrixPmv); + } + modified=0; + return res!=0; + } + + public final int glGetMatrixMode() { + return matrixMode; + } + + public final FloatBuffer glGetTMatrixf() { + return matrixT; + } + + public final FloatBuffer glGetPMatrixf() { + return matrixP; + } + + public final FloatBuffer glGetMvMatrixf() { + return matrixMv; + } + + public final FloatBuffer glGetPMvMvitPmvMatrixf() { + return matrixPMvMvitPmv; + } + + public final FloatBuffer glGetPMvMvitMatrixf() { + return matrixPMvMvit; + } + + public final FloatBuffer glGetPMvMviMatrixf() { + return matrixPMvMvi; + } + + public final FloatBuffer glGetPMvMatrixf() { + return matrixPMv; + } + + public final FloatBuffer glGetMviMatrixf() { + return matrixMvi; + } + + public final FloatBuffer glGetPmvMatrixf() { + return matrixPmv; + } + + public final FloatBuffer glGetNormalMatrixf() { + return matrixMvit3; + } + + /* + * @return the current matrix + */ + public final FloatBuffer glGetMatrixf() { + return glGetMatrixf(matrixMode); + } + + /** + * @param matrixName GL_MODELVIEW, GL_PROJECTION or GL.GL_TEXTURE + * @return the given matrix + */ + public final FloatBuffer glGetMatrixf(final int matrixName) { + if(matrixName==GL_MODELVIEW) { + return matrixMv; + } else if(matrixName==GL_PROJECTION) { + return matrixP; + } else if(matrixName==GL.GL_TEXTURE) { + return matrixT; + } else { + throw new GLException("unsupported matrixName: "+matrixName); + } + } + + public final void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) { + float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear; + float bottom=-1.0f*top; + float left=aspect*bottom; + float right=aspect*top; + glFrustumf(left, right, bottom, top, zNear, zFar); + } + + public static final void glMultMatrixf(final FloatBuffer a, final FloatBuffer b, FloatBuffer p) { + for (int i = 0; i < 4; i++) { + final float ai0=a.get(i+0*4), ai1=a.get(i+1*4), ai2=a.get(i+2*4), ai3=a.get(i+3*4); + p.put(i+0*4 , ai0 * b.get(0+0*4) + ai1 * b.get(1+0*4) + ai2 * b.get(2+0*4) + ai3 * b.get(3+0*4) ); + p.put(i+1*4 , ai0 * b.get(0+1*4) + ai1 * b.get(1+1*4) + ai2 * b.get(2+1*4) + ai3 * b.get(3+1*4) ); + p.put(i+2*4 , ai0 * b.get(0+2*4) + ai1 * b.get(1+2*4) + ai2 * b.get(2+2*4) + ai3 * b.get(3+2*4) ); + p.put(i+3*4 , ai0 * b.get(0+3*4) + ai1 * b.get(1+3*4) + ai2 * b.get(2+3*4) + ai3 * b.get(3+3*4) ); + } + } + public static final void glMultMatrixf(final FloatBuffer a, final float[] b, int b_off, FloatBuffer p) { + for (int i = 0; i < 4; i++) { + final float ai0=a.get(i+0*4), ai1=a.get(i+1*4), ai2=a.get(i+2*4), ai3=a.get(i+3*4); + p.put(i+0*4 , ai0 * b[b_off+0+0*4] + ai1 * b[b_off+1+0*4] + ai2 * b[b_off+2+0*4] + ai3 * b[b_off+3+0*4] ); + p.put(i+1*4 , ai0 * b[b_off+0+1*4] + ai1 * b[b_off+1+1*4] + ai2 * b[b_off+2+1*4] + ai3 * b[b_off+3+1*4] ); + p.put(i+2*4 , ai0 * b[b_off+0+2*4] + ai1 * b[b_off+1+2*4] + ai2 * b[b_off+2+2*4] + ai3 * b[b_off+3+2*4] ); + p.put(i+3*4 , ai0 * b[b_off+0+3*4] + ai1 * b[b_off+1+3*4] + ai2 * b[b_off+2+3*4] + ai3 * b[b_off+3+3*4] ); + } + } + + // + // MatrixIf + // + + public void glMatrixMode(final int matrixName) { + switch(matrixName) { + case GL_MODELVIEW: + case GL_PROJECTION: + case GL.GL_TEXTURE: + break; + default: + throw new GLException("unsupported matrixName: "+matrixName); + } + matrixMode = matrixName; + } + + public void glGetFloatv(int matrixGetName, FloatBuffer params) { + int pos = params.position(); + if(matrixGetName==GL_MATRIX_MODE) { + params.put((float)matrixMode); + } else { + FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName)); + params.put(matrix); + matrix.rewind(); + } + params.position(pos); + } + public void glGetFloatv(int matrixGetName, float[] params, int params_offset) { + if(matrixGetName==GL_MATRIX_MODE) { + params[params_offset]=(float)matrixMode; + } else { + FloatBuffer matrix = glGetMatrixf(matrixGetName2MatrixModeName(matrixGetName)); + matrix.get(params, params_offset, 16); + matrix.rewind(); + } + } + public void glGetIntegerv(int pname, IntBuffer params) { + int pos = params.position(); + if(pname==GL_MATRIX_MODE) { + params.put(matrixMode); + } else { + throw new GLException("unsupported pname: "+pname); + } + params.position(pos); + } + public void glGetIntegerv(int pname, int[] params, int params_offset) { + if(pname==GL_MATRIX_MODE) { + params[params_offset]=matrixMode; + } else { + throw new GLException("unsupported pname: "+pname); + } + } + + public final void glLoadMatrixf(final float[] values, final int offset) { + int len = values.length-offset; + if(matrixMode==GL_MODELVIEW) { + matrixMv.clear(); + matrixMv.put(values, offset, len); + matrixMv.rewind(); + modified |= DIRTY_MODELVIEW ; + } else if(matrixMode==GL_PROJECTION) { + matrixP.clear(); + matrixP.put(values, offset, len); + matrixP.rewind(); + modified |= DIRTY_PROJECTION ; + } else if(matrixMode==GL.GL_TEXTURE) { + matrixT.clear(); + matrixT.put(values, offset, len); + matrixT.rewind(); + modified |= DIRTY_TEXTURE ; + } + } + + public final void glLoadMatrixf(java.nio.FloatBuffer m) { + int spos = m.position(); + if(matrixMode==GL_MODELVIEW) { + matrixMv.clear(); + matrixMv.put(m); + matrixMv.rewind(); + modified |= DIRTY_MODELVIEW ; + } else if(matrixMode==GL_PROJECTION) { + matrixP.clear(); + matrixP.put(m); + matrixP.rewind(); + modified |= DIRTY_PROJECTION ; + } else if(matrixMode==GL.GL_TEXTURE) { + matrixT.clear(); + matrixT.put(m); + matrixT.rewind(); + modified |= DIRTY_TEXTURE ; + } + m.position(spos); + } + + public final void glPopMatrix() { + float[] stackEntry=null; + if(matrixMode==GL_MODELVIEW) { + stackEntry = (float[])matrixMvStack.remove(0); + } else if(matrixMode==GL_PROJECTION) { + stackEntry = (float[])matrixPStack.remove(0); + } else if(matrixMode==GL.GL_TEXTURE) { + stackEntry = (float[])matrixTStack.remove(0); + } + glLoadMatrixf(stackEntry, 0); + } + + public final void glPushMatrix() { + float[] stackEntry = new float[1*16]; + if(matrixMode==GL_MODELVIEW) { + matrixMv.get(stackEntry); + matrixMv.rewind(); + matrixMvStack.add(0, stackEntry); + } else if(matrixMode==GL_PROJECTION) { + matrixP.get(stackEntry); + matrixP.rewind(); + matrixPStack.add(0, stackEntry); + } else if(matrixMode==GL.GL_TEXTURE) { + matrixT.get(stackEntry); + matrixT.rewind(); + matrixTStack.add(0, stackEntry); + } + } + + public final void glLoadIdentity() { + if(matrixMode==GL_MODELVIEW) { + matrixMv.clear(); + matrixMv.put(matrixIdent); + matrixMv.rewind(); + matrixIdent.rewind(); + modified |= DIRTY_MODELVIEW ; + } else if(matrixMode==GL_PROJECTION) { + matrixP.clear(); + matrixP.put(matrixIdent); + matrixP.rewind(); + matrixIdent.rewind(); + modified |= DIRTY_PROJECTION ; + } else if(matrixMode==GL.GL_TEXTURE) { + matrixT.clear(); + matrixT.put(matrixIdent); + matrixT.rewind(); + matrixIdent.rewind(); + modified |= DIRTY_TEXTURE ; + } + } + + public final void glMultMatrixf(final FloatBuffer m) { + if(matrixMode==GL_MODELVIEW) { + glMultMatrixf(matrixMv, m, matrixMult); + matrixMv.clear(); + matrixMv.put(matrixMult); + matrixMv.rewind(); + modified |= DIRTY_MODELVIEW ; + } else if(matrixMode==GL_PROJECTION) { + glMultMatrixf(matrixP, m, matrixMult); + matrixP.clear(); + matrixP.put(matrixMult); + matrixP.rewind(); + modified |= DIRTY_PROJECTION ; + } else if(matrixMode==GL.GL_TEXTURE) { + glMultMatrixf(matrixT, m, matrixMult); + matrixT.clear(); + matrixT.put(matrixMult); + matrixT.rewind(); + modified |= DIRTY_TEXTURE ; + } + matrixMult.rewind(); + } + + public void glMultMatrixf(float[] m, int m_offset) { + if(matrixMode==GL_MODELVIEW) { + glMultMatrixf(matrixMv, m, m_offset, matrixMult); + matrixMv.clear(); + matrixMv.put(matrixMult); + matrixMv.rewind(); + modified |= DIRTY_MODELVIEW ; + } else if(matrixMode==GL_PROJECTION) { + glMultMatrixf(matrixP, m, m_offset, matrixMult); + matrixP.clear(); + matrixP.put(matrixMult); + matrixP.rewind(); + modified |= DIRTY_PROJECTION ; + } else if(matrixMode==GL.GL_TEXTURE) { + glMultMatrixf(matrixT, m, m_offset, matrixMult); + matrixT.clear(); + matrixT.put(matrixMult); + matrixT.rewind(); + modified |= DIRTY_TEXTURE ; + } + matrixMult.rewind(); + } + + public final void glTranslatef(final float x, final float y, final float z) { + // Translation matrix: + // 1 0 0 x + // 0 1 0 y + // 0 0 1 z + // 0 0 0 1 + matrixTrans.put(0+4*3, x); + matrixTrans.put(1+4*3, y); + matrixTrans.put(2+4*3, z); + glMultMatrixf(matrixTrans); + } + + public final void glRotatef(final float angdeg, float x, float y, float z) { + float angrad = angdeg * (float) Math.PI / 180; + float c = (float)Math.cos(angrad); + float ic= 1.0f - c; + float s = (float)Math.sin(angrad); + + vec3f[0]=x; vec3f[1]=y; vec3f[2]=z; + projectFloat.normalize(vec3f); + x = vec3f[0]; y = vec3f[1]; z = vec3f[2]; + + // Rotation matrix: + // xx(1−c)+c xy(1−c)+zs xz(1−c)-ys 0 + // xy(1−c)-zs yy(1−c)+c yz(1−c)+xs 0 + // xz(1−c)+ys yz(1−c)-xs zz(1−c)+c 0 + // 0 0 0 1 + float xy = x*y; + float xz = x*z; + float xs = x*s; + float ys = y*s; + float yz = y*z; + float zs = z*s; + matrixRot.put(0*4+0, x*x*ic+c); + matrixRot.put(0*4+1, xy*ic+zs); + matrixRot.put(0*4+2, xz*ic-ys); + + matrixRot.put(1*4+0, xy*ic-zs); + matrixRot.put(1*4+1, y*y*ic+c); + matrixRot.put(1*4+2, yz*ic+xs); + + matrixRot.put(2*4+0, xz*ic+ys); + matrixRot.put(2*4+1, yz*ic-xs); + matrixRot.put(2*4+2, z*z*ic+c); + + glMultMatrixf(matrixRot); + } + + public final void glScalef(final float x, final float y, final float z) { + // Scale matrix: + // x 0 0 0 + // 0 y 0 0 + // 0 0 z 0 + // 0 0 0 1 + matrixScale.put(0+4*0, x); + matrixScale.put(1+4*1, y); + matrixScale.put(2+4*2, z); + + glMultMatrixf(matrixScale); + } + + public final void glOrthof(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { + // Ortho matrix: + // 2/dx 0 0 tx + // 0 2/dy 0 ty + // 0 0 2/dz tz + // 0 0 0 1 + float dx=right-left; + float dy=top-bottom; + float dz=zFar-zNear; + float tx=-1.0f*(right+left)/dx; + float ty=-1.0f*(top+bottom)/dy; + float tz=-1.0f*(zFar+zNear)/dz; + + matrixOrtho.put(0+4*0, 2.0f/dx); + matrixOrtho.put(1+4*1, 2.0f/dy); + matrixOrtho.put(2+4*2, -2.0f/dz); + matrixOrtho.put(0+4*3, tx); + matrixOrtho.put(1+4*3, ty); + matrixOrtho.put(2+4*3, tz); + + glMultMatrixf(matrixOrtho); + } + + public final void glFrustumf(final float left, final float right, final float bottom, final float top, final float zNear, final float zFar) { + if(zNear<=0.0f||zFar<0.0f) { + throw new GLException("GL_INVALID_VALUE: zNear and zFar must be positive, and zNear>0"); + } + if(left==right || top==bottom) { + throw new GLException("GL_INVALID_VALUE: top,bottom and left,right must not be equal"); + } + // Frustum matrix: + // 2*zNear/dx 0 A 0 + // 0 2*zNear/dy B 0 + // 0 0 C D + // 0 0 −1 0 + float zNear2 = 2.0f*zNear; + float dx=right-left; + float dy=top-bottom; + float dz=zFar-zNear; + float A=(right+left)/dx; + float B=(top+bottom)/dy; + float C=-1.0f*(zFar+zNear)/dz; + float D=-2.0f*(zFar*zNear)/dz; + + matrixFrustum.put(0+4*0, zNear2/dx); + matrixFrustum.put(1+4*1, zNear2/dy); + matrixFrustum.put(2+4*2, C); + + matrixFrustum.put(0+4*2, A); + matrixFrustum.put(1+4*2, B); + + matrixFrustum.put(2+4*3, D); + matrixFrustum.put(3+4*2, -1.0f); + + glMultMatrixf(matrixFrustum); + } + + // + // private + // + + private final void setMviMvit() { + if(!projectFloat.gluInvertMatrixf(matrixMv, matrixMvi)) { + throw new GLException("Invalid source Mv matrix, can't compute inverse"); + } + + // transpose matrix + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + matrixMvit.put(j+i*4, matrixMvi.get(i+j*4)); + } + } + + // fetch 3x3 + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + matrixMvit3.put(i+j*3, matrixMvit.get(i+j*4)); + } + } + } + + protected FloatBuffer matrixIdent; + protected FloatBuffer matrixTPMvMvitPmv, matrixPMvMvit, matrixPMvMvitPmv, matrixPMvMvi, matrixPMv, matrixP, matrixT, matrixMv, matrixMvi, matrixMvit, matrixPmv; + protected FloatBuffer matrixMvit3; + protected FloatBuffer localBuf, matrixMult, matrixTrans, matrixRot, matrixScale, matrixOrtho, matrixFrustum; + protected float[] vec3f; + protected List/*FloatBuffer*/ matrixTStack, matrixPStack, matrixMvStack; + protected int matrixMode = GL_MODELVIEW; + protected int modified = 0; + protected ProjectFloat projectFloat; + + public static final int DIRTY_MODELVIEW = 1 << 0; + public static final int DIRTY_PROJECTION = 1 << 1; + public static final int DIRTY_TEXTURE = 1 << 2; +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/StreamUtil.java b/src/jogl/classes/com/jogamp/opengl/util/StreamUtil.java new file mode 100755 index 000000000..4cf8cb1f0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/StreamUtil.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util; + +import java.io.*; +import java.nio.*; + +/** Utilities for dealing with streams. */ + +public class StreamUtil { + private StreamUtil() {} + + public static byte[] readAll2Array(InputStream stream) throws IOException { + BytesRead bytesRead = readAllImpl(stream); + byte[] data = bytesRead.data; + if (bytesRead.payloadLen != data.length) { + data = new byte[bytesRead.payloadLen]; + System.arraycopy(bytesRead.data, 0, data, 0, bytesRead.payloadLen); + } + return data; + } + + public static ByteBuffer readAll2Buffer(InputStream stream) throws IOException { + BytesRead bytesRead = readAllImpl(stream); + return GLBuffers.newDirectByteBuffer(bytesRead.data, 0, bytesRead.payloadLen); + } + + private static BytesRead readAllImpl(InputStream stream) throws IOException { + // FIXME: Shall we do this here ? + if( !(stream instanceof BufferedInputStream) ) { + stream = new BufferedInputStream(stream); + } + int avail = stream.available(); + byte[] data = new byte[avail]; + int numRead = 0; + int pos = 0; + do { + if (pos + avail > data.length) { + byte[] newData = new byte[pos + avail]; + System.arraycopy(data, 0, newData, 0, pos); + data = newData; + } + numRead = stream.read(data, pos, avail); + if (numRead >= 0) { + pos += numRead; + } + avail = stream.available(); + } while (avail > 0 && numRead >= 0); + + return new BytesRead(pos, data); + } + + private static class BytesRead { + BytesRead(int payloadLen, byte[] data) { + this.payloadLen=payloadLen; + this.data=data; + } + int payloadLen; + byte[] data; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java b/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java new file mode 100755 index 000000000..b949f0e39 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/TGAWriter.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; + +/** + * Utility class which helps take fast screenshots of OpenGL rendering + * results into Targa-format files. Used by the {@link com.jogamp.opengl.util.awt.Screenshot} + * class; can also be used in conjunction with the {@link com.jogamp.opengl.util.gl2.TileRenderer} class. + */ +public class TGAWriter { + + private static final int TARGA_HEADER_SIZE = 18; + + private FileChannel ch; + private ByteBuffer buf; + + /** Constructor for the TGAWriter. */ + public TGAWriter() { + } + + /** + * Opens the specified Targa file for writing, overwriting any + * existing file, and sets up the header of the file expecting the + * data to be filled in before closing it. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether the alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws IOException if an I/O error occurred while writing the + * file + */ + public void open(File file, + int width, + int height, + boolean alpha) throws IOException { + RandomAccessFile out = new RandomAccessFile(file, "rw"); + ch = out.getChannel(); + int pixelSize = (alpha ? 32 : 24); + int numChannels = (alpha ? 4 : 3); + + int fileLength = TARGA_HEADER_SIZE + width * height * numChannels; + out.setLength(fileLength); + MappedByteBuffer image = ch.map(FileChannel.MapMode.READ_WRITE, 0, fileLength); + + // write the TARGA header + image.put(0, (byte) 0).put(1, (byte) 0); + image.put(2, (byte) 2); // uncompressed type + image.put(12, (byte) (width & 0xFF)); // width + image.put(13, (byte) (width >> 8)); // width + image.put(14, (byte) (height & 0xFF)); // height + image.put(15, (byte) (height >> 8)); // height + image.put(16, (byte) pixelSize); // pixel size + + // go to image data position + image.position(TARGA_HEADER_SIZE); + // jogl needs a sliced buffer + buf = image.slice(); + } + + /** + * Returns the ByteBuffer corresponding to the data for the image. + * This must be filled in with data in either BGR or BGRA format + * depending on whether an alpha channel was specified during + * open(). + */ + public ByteBuffer getImageData() { + return buf; + } + + public void close() throws IOException { + // close the file channel + ch.close(); + buf = null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java b/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java new file mode 100755 index 000000000..a3139b16a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/ImageUtil.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.awt; + +import java.awt.*; +import java.awt.image.*; + +/** Utilities for dealing with images. */ + +public class ImageUtil { + private ImageUtil() {} + + /** Flips the supplied BufferedImage vertically. This is often a + necessary conversion step to display a Java2D image correctly + with OpenGL and vice versa. */ + public static void flipImageVertically(BufferedImage image) { + WritableRaster raster = image.getRaster(); + Object scanline1 = null; + Object scanline2 = null; + + for (int i = 0; i < image.getHeight() / 2; i++) { + scanline1 = raster.getDataElements(0, i, image.getWidth(), 1, scanline1); + scanline2 = raster.getDataElements(0, image.getHeight() - i - 1, image.getWidth(), 1, scanline2); + raster.setDataElements(0, i, image.getWidth(), 1, scanline2); + raster.setDataElements(0, image.getHeight() - i - 1, image.getWidth(), 1, scanline1); + } + } + + /** + * Creates a <code>BufferedImage</code> with a pixel format compatible with the graphics + * environment. The returned image can thus benefit from hardware accelerated operations + * in Java2D API. + * + * @param width The width of the image to be created + * @param height The height of the image to be created + * + * @return A instance of <code>BufferedImage</code> with a type compatible with the graphics card. + */ + public static BufferedImage createCompatibleImage(int width, int height) { + GraphicsConfiguration configuration = + GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + return configuration.createCompatibleImage(width, height); + } + + /** + * Creates a thumbnail from an image. A thumbnail is a scaled down version of the original picture. + * This method will retain the width to height ratio of the original picture and return a new + * instance of <code>BufferedImage</code>. The original picture is not modified. + * + * @param image The original image to sample down + * @param thumbWidth The width of the thumbnail to be created + * + * @throws IllegalArgumentException If thumbWidth is greater than image.getWidth() + * + * @return A thumbnail with the requested width or the original picture if thumbWidth = image.getWidth() + */ + public static BufferedImage createThumbnail(BufferedImage image, int thumbWidth) { + // Thanks to Romain Guy for this utility + if (thumbWidth > image.getWidth()) { + throw new IllegalArgumentException("Thumbnail width must be greater than image width"); + } + + if (thumbWidth == image.getWidth()) { + return image; + } + + float ratio = (float) image.getWidth() / (float) image.getHeight(); + int width = image.getWidth(); + BufferedImage thumb = image; + + do { + width /= 2; + if (width < thumbWidth) { + width = thumbWidth; + } + + BufferedImage temp = createCompatibleImage(width, (int) (width / ratio)); + Graphics2D g2 = temp.createGraphics(); + g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g2.drawImage(thumb, 0, 0, temp.getWidth(), temp.getHeight(), null); + g2.dispose(); + thumb = temp; + } while (width != thumbWidth); + + return thumb; + } + +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java new file mode 100755 index 000000000..1275c9391 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Overlay.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.awt; + +import java.awt.Graphics2D; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.texture.*; + +/** Provides a Java 2D overlay on top of an arbitrary GLDrawable, + making it easier to do things like draw text and images on top of + an OpenGL scene while still maintaining reasonably good + efficiency. */ + +public class Overlay { + private GLDrawable drawable; + private TextureRenderer renderer; + private boolean contentsLost; + + /** Creates a new Java 2D overlay on top of the specified + GLDrawable. */ + public Overlay(GLDrawable drawable) { + this.drawable = drawable; + } + + /** Creates a {@link java.awt.Graphics2D Graphics2D} instance for + rendering into the overlay. The returned object should be + disposed of using the normal {@link java.awt.Graphics#dispose() + Graphics.dispose()} method once it is no longer being used. + + @return a new {@link java.awt.Graphics2D Graphics2D} object for + rendering into the backing store of this renderer + */ + public Graphics2D createGraphics() { + // Validate the size of the renderer against the current size of + // the drawable + validateRenderer(); + return renderer.createGraphics(); + } + + /** Indicates whether the Java 2D contents of the overlay were lost + since the last time {@link #createGraphics} was called. This + method should be called immediately after calling {@link + #createGraphics} to see whether the entire contents of the + overlay need to be redrawn or just the region the application is + interested in updating. + + @return whether the contents of the overlay were lost since the + last render + */ + public boolean contentsLost() { + return contentsLost; + } + + /** Marks the given region of the overlay as dirty. This region, and + any previously set dirty regions, will be automatically + synchronized with the underlying Texture during the next {@link + #draw draw} or {@link #drawAll drawAll} operation, at which + point the dirty region will be cleared. It is not necessary for + an OpenGL context to be current when this method is called. + + @param x the x coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param y the y coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param width the width of the region to update + @param height the height of the region to update + + @throws GLException If an OpenGL context is not current when this method is called */ + public void markDirty(int x, int y, int width, int height) { + renderer.markDirty(x, y, width, height); + } + + /** Draws the entire contents of the overlay on top of the OpenGL + drawable. This is a convenience method which encapsulates all + portions of the rendering process; if this method is used, + {@link #beginRendering}, {@link #endRendering}, etc. should not + be used. This method should be called while the OpenGL context + for the drawable is current, and after your OpenGL scene has + been rendered. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void drawAll() throws GLException { + beginRendering(); + draw(0, 0, drawable.getWidth(), drawable.getHeight()); + endRendering(); + } + + /** Begins the OpenGL rendering process for the overlay. This is + separated out so advanced applications can render independent + pieces of the overlay to different portions of the drawable. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void beginRendering() throws GLException { + renderer.beginOrthoRendering(drawable.getWidth(), drawable.getHeight()); + } + + /** Ends the OpenGL rendering process for the overlay. This is + separated out so advanced applications can render independent + pieces of the overlay to different portions of the drawable. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void endRendering() throws GLException { + renderer.endOrthoRendering(); + } + + /** Draws the specified sub-rectangle of the overlay on top of the + OpenGL drawable. {@link #beginRendering} and {@link + #endRendering} must be used in conjunction with this method to + achieve proper rendering results. This method should be called + while the OpenGL context for the drawable is current, and after + your OpenGL scene has been rendered. + + @param x the lower-left x coordinate (relative to the lower left + of the overlay) of the rectangle to draw + @param y the lower-left y coordinate (relative to the lower left + of the overlay) of the rectangle to draw + @param width the width of the rectangle to draw + @param height the height of the rectangle to draw + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void draw(int x, int y, int width, int height) throws GLException { + draw(x, y, x, y, width, height); + } + + /** Draws the specified sub-rectangle of the overlay at the + specified x and y coordinate on top of the OpenGL drawable. + {@link #beginRendering} and {@link #endRendering} must be used + in conjunction with this method to achieve proper rendering + results. This method should be called while the OpenGL context + for the drawable is current, and after your OpenGL scene has + been rendered. + + @param screenx the on-screen x coordinate at which to draw the rectangle + @param screeny the on-screen y coordinate (relative to lower left) at + which to draw the rectangle + @param overlayx the x coordinate of the pixel in the overlay of + the lower left portion of the rectangle to draw + @param overlayy the y coordinate of the pixel in the overlay + (relative to lower left) of the lower left portion of the + rectangle to draw + @param width the width of the rectangle to draw + @param height the height of the rectangle to draw + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void draw(int screenx, int screeny, + int overlayx, int overlayy, + int width, int height) throws GLException { + renderer.drawOrthoRect(screenx, screeny, + overlayx, overlayy, + width, height); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void validateRenderer() { + if (renderer == null) { + renderer = new TextureRenderer(drawable.getWidth(), + drawable.getHeight(), + true); + contentsLost = true; + } else if (renderer.getWidth() != drawable.getWidth() || + renderer.getHeight() != drawable.getHeight()) { + renderer.setSize(drawable.getWidth(), drawable.getHeight()); + contentsLost = true; + } else { + contentsLost = false; + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java new file mode 100755 index 000000000..7019d720f --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/Screenshot.java @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util.awt; + +import java.awt.image.*; +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import javax.imageio.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; + +import com.jogamp.opengl.util.*; + +/** Utilities for taking screenshots of OpenGL applications. */ + +public class Screenshot { + private Screenshot() {} + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). <p> + * + * No alpha channel is written with this variant. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int width, + int height) throws GLException, IOException { + writeToTargaFile(file, width, height, false); + } + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether the alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int width, + int height, + boolean alpha) throws GLException, IOException { + writeToTargaFile(file, 0, 0, width, height, alpha); + } + + /** + * Takes a fast screenshot of the current OpenGL drawable to a Targa + * file. Requires the OpenGL context for the desired drawable to be + * current. Takes the screenshot from the last assigned read buffer, + * or the OpenGL default read buffer if none has been specified by + * the user (GL_FRONT for single-buffered configurations and GL_BACK + * for double-buffered configurations). This is the fastest + * mechanism for taking a screenshot of an application. Contributed + * by Carsten Weisse of Bytonic Software (http://bytonic.de/). + * + * @param file the file to write containing the screenshot + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the desired screenshot area + * @param height the height of the desired screenshot area + * @param alpha whether the alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * @throws IOException if an I/O error occurred while writing the + * file + */ + public static void writeToTargaFile(File file, + int x, + int y, + int width, + int height, + boolean alpha) throws GLException, IOException { + if (alpha) { + checkExtABGR(); + } + + TGAWriter writer = new TGAWriter(); + writer.open(file, width, height, alpha); + ByteBuffer bgr = writer.getImageData(); + + GL2 gl = GLUgl2.getCurrentGL2(); + + // Set up pixel storage modes + PixelStorageModes psm = new PixelStorageModes(); + psm.save(gl); + + int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR); + + // read the BGR values into the image buffer + gl.glReadPixels(x, y, width, height, readbackType, + GL2.GL_UNSIGNED_BYTE, bgr); + + // Restore pixel storage modes + psm.restore(gl); + + // close the file + writer.close(); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. <P> + * + * No alpha channel is read back with this variant. + * + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int width, + int height) throws GLException { + return readToBufferedImage(width, height, false); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. + * + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether the alpha channel should be read back. If + * true, requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int width, + int height, + boolean alpha) throws GLException { + return readToBufferedImage(0, 0, width, height, alpha); + } + + /** + * Takes a screenshot of the current OpenGL drawable to a + * BufferedImage. Requires the OpenGL context for the desired + * drawable to be current. Takes the screenshot from the last + * assigned read buffer, or the OpenGL default read buffer if none + * has been specified by the user (GL_FRONT for single-buffered + * configurations and GL_BACK for double-buffered configurations). + * Note that the scanlines of the resulting image are flipped + * vertically in order to correctly match the OpenGL contents, which + * takes time and is therefore not as fast as the Targa screenshot + * function. + * + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the desired screenshot area + * @param height the height of the desired screenshot area + * @param alpha whether the alpha channel should be read back. If + * true, requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + */ + public static BufferedImage readToBufferedImage(int x, + int y, + int width, + int height, + boolean alpha) throws GLException { + int bufImgType = (alpha ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR); + int readbackType = (alpha ? GL2.GL_ABGR_EXT : GL2.GL_BGR); + + if (alpha) { + checkExtABGR(); + } + + // Allocate necessary storage + BufferedImage image = new BufferedImage(width, height, bufImgType); + + GL2 gl = GLUgl2.getCurrentGL2(); + + // Set up pixel storage modes + PixelStorageModes psm = new PixelStorageModes(); + psm.save(gl); + + // read the BGR values into the image + gl.glReadPixels(x, y, width, height, readbackType, + GL2.GL_UNSIGNED_BYTE, + ByteBuffer.wrap(((DataBufferByte) image.getRaster().getDataBuffer()).getData())); + + // Restore pixel storage modes + psm.restore(gl); + + // Must flip BufferedImage vertically for correct results + ImageUtil.flipImageVertically(image); + return image; + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * No alpha channel is saved with this variant. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int width, + int height) throws IOException, GLException { + writeToFile(file, width, height, false); + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * Note that some file formats, in particular JPEG, can not handle + * an alpha channel properly. If the "alpha" argument is specified + * as true for such a file format it will be silently ignored. + * + * @param file the file to write containing the screenshot + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether an alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int width, + int height, + boolean alpha) throws IOException, GLException { + writeToFile(file, 0, 0, width, height, alpha); + } + + /** + * Takes a screenshot of the current OpenGL drawable to the + * specified file on disk using the ImageIO package. Requires the + * OpenGL context for the desired drawable to be current. Takes the + * screenshot from the last assigned read buffer, or the OpenGL + * default read buffer if none has been specified by the user + * (GL_FRONT for single-buffered configurations and GL_BACK for + * double-buffered configurations). This is not the fastest + * mechanism for taking a screenshot but may be more convenient than + * others for getting images for consumption by other packages. The + * file format is inferred from the suffix of the given file. <P> + * + * Note that some file formats, in particular JPEG, can not handle + * an alpha channel properly. If the "alpha" argument is specified + * as true for such a file format it will be silently ignored. + * + * @param file the file to write containing the screenshot + * @param x the starting x coordinate of the screenshot, measured from the lower-left + * @param y the starting y coordinate of the screenshot, measured from the lower-left + * @param width the width of the current drawable + * @param height the height of the current drawable + * @param alpha whether an alpha channel should be saved. If true, + * requires GL_EXT_abgr extension to be present. + * + * @throws GLException if an OpenGL context was not current or + * another OpenGL-related error occurred + * + * @throws IOException if an I/O error occurred or if the file could + * not be written to disk due to the requested file format being + * unsupported by ImageIO + */ + public static void writeToFile(File file, + int x, + int y, + int width, + int height, + boolean alpha) throws IOException, GLException { + String fileSuffix = FileUtil.getFileSuffix(file); + if (alpha && (fileSuffix.equals("jpg") || fileSuffix.equals("jpeg"))) { + // JPEGs can't deal properly with alpha channels + alpha = false; + } + + BufferedImage image = readToBufferedImage(x, y, width, height, alpha); + if (!ImageIO.write(image, fileSuffix, file)) { + throw new IOException("Unsupported file format " + fileSuffix); + } + } + + private static int glGetInteger(GL2 gl, int pname, int[] tmp) { + gl.glGetIntegerv(pname, tmp, 0); + return tmp[0]; + } + + private static void checkExtABGR() { + GL2 gl = GLUgl2.getCurrentGL2(); + if (!gl.isExtensionAvailable("GL_EXT_abgr")) { + throw new IllegalArgumentException("Saving alpha channel requires GL_EXT_abgr"); + } + } + + static class PixelStorageModes { + int packAlignment; + int packRowLength; + int packSkipRows; + int packSkipPixels; + int packSwapBytes; + int[] tmp = new int[1]; + + void save(GL2 gl) { + packAlignment = glGetInteger(gl, GL2.GL_PACK_ALIGNMENT, tmp); + packRowLength = glGetInteger(gl, GL2.GL_PACK_ROW_LENGTH, tmp); + packSkipRows = glGetInteger(gl, GL2.GL_PACK_SKIP_ROWS, tmp); + packSkipPixels = glGetInteger(gl, GL2.GL_PACK_SKIP_PIXELS, tmp); + packSwapBytes = glGetInteger(gl, GL2.GL_PACK_SWAP_BYTES, tmp); + + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 0); + } + + void restore(GL2 gl) { + gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, packAlignment); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, packRowLength); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java new file mode 100755 index 000000000..bac9f88ea --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextRenderer.java @@ -0,0 +1,1952 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ +package com.jogamp.opengl.util.awt; + +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.packrect.*; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.awt.*; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; + +// For debugging purposes +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.event.*; +import java.awt.font.*; +import java.awt.geom.*; + +import java.nio.*; + +import java.text.*; + +import java.util.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; +import javax.media.opengl.awt.*; + + +/** Renders bitmapped Java 2D text into an OpenGL window with high + performance, full Unicode support, and a simple API. Performs + appropriate caching of text rendering results in an OpenGL texture + internally to avoid repeated font rasterization. The caching is + completely automatic, does not require any user intervention, and + has no visible controls in the public API. <P> + + Using the {@link TextRenderer TextRenderer} is simple. Add a + "<code>TextRenderer renderer;</code>" field to your {@link + javax.media.opengl.GLEventListener GLEventListener}. In your {@link + javax.media.opengl.GLEventListener#init init} method, add: + + <PRE> + renderer = new TextRenderer(new Font("SansSerif", Font.BOLD, 36)); + </PRE> + + <P> In the {@link javax.media.opengl.GLEventListener#display display} method of your + {@link javax.media.opengl.GLEventListener GLEventListener}, add: + <PRE> + renderer.beginRendering(drawable.getWidth(), drawable.getHeight()); + // optionally set the color + renderer.setColor(1.0f, 0.2f, 0.2f, 0.8f); + renderer.draw("Text to draw", xPosition, yPosition); + // ... more draw commands, color changes, etc. + renderer.endRendering(); + </PRE> + + Unless you are sharing textures and display lists between OpenGL + contexts, you do not need to call the {@link #dispose dispose} + method of the TextRenderer; the OpenGL resources it uses + internally will be cleaned up automatically when the OpenGL + context is destroyed. <P> + + <b>Note</b> that the TextRenderer may cause the vertex and texture + coordinate array buffer bindings to change, or to be unbound. This + is important to note if you are using Vertex Buffer Objects (VBOs) + in your application. <P> + + Internally, the renderer uses a rectangle packing algorithm to + pack both glyphs and full Strings' rendering results (which are + variable size) onto a larger OpenGL texture. The internal backing + store is maintained using a {@link + com.jogamp.opengl.util.awt.TextureRenderer TextureRenderer}. A least + recently used (LRU) algorithm is used to discard previously + rendered strings; the specific algorithm is undefined, but is + currently implemented by flushing unused Strings' rendering + results every few hundred rendering cycles, where a rendering + cycle is defined as a pair of calls to {@link #beginRendering + beginRendering} / {@link #endRendering endRendering}. + + @author John Burkey + @author Kenneth Russell +*/ +public class TextRenderer { + private static final boolean DEBUG = Debug.debug("TextRenderer"); + + // These are occasionally useful for more in-depth debugging + private static final boolean DISABLE_GLYPH_CACHE = false; + private static final boolean DRAW_BBOXES = false; + + static final int kSize = 256; + + // Every certain number of render cycles, flush the strings which + // haven't been used recently + private static final int CYCLES_PER_FLUSH = 100; + + // The amount of vertical dead space on the backing store before we + // force a compaction + private static final float MAX_VERTICAL_FRAGMENTATION = 0.7f; + static final int kQuadsPerBuffer = 100; + static final int kCoordsPerVertVerts = 3; + static final int kCoordsPerVertTex = 2; + static final int kVertsPerQuad = 4; + static final int kTotalBufferSizeVerts = kQuadsPerBuffer * kVertsPerQuad; + static final int kTotalBufferSizeCoordsVerts = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertVerts; + static final int kTotalBufferSizeCoordsTex = kQuadsPerBuffer * kVertsPerQuad * kCoordsPerVertTex; + static final int kTotalBufferSizeBytesVerts = kTotalBufferSizeCoordsVerts * 4; + static final int kTotalBufferSizeBytesTex = kTotalBufferSizeCoordsTex * 4; + static final int kSizeInBytes_OneVertices_VertexData = kCoordsPerVertVerts * 4; + static final int kSizeInBytes_OneVertices_TexData = kCoordsPerVertTex * 4; + private Font font; + private boolean antialiased; + private boolean useFractionalMetrics; + + // Whether we're attempting to use automatic mipmap generation support + private boolean mipmap; + private RectanglePacker packer; + private boolean haveMaxSize; + private RenderDelegate renderDelegate; + private TextureRenderer cachedBackingStore; + private Graphics2D cachedGraphics; + private FontRenderContext cachedFontRenderContext; + private Map /*<String,Rect>*/ stringLocations = new HashMap /*<String,Rect>*/(); + private GlyphProducer mGlyphProducer; + + private int numRenderCycles; + + // Need to keep track of whether we're in a beginRendering() / + // endRendering() cycle so we can re-enter the exact same state if + // we have to reallocate the backing store + private boolean inBeginEndPair; + private boolean isOrthoMode; + private int beginRenderingWidth; + private int beginRenderingHeight; + private boolean beginRenderingDepthTestDisabled; + + // For resetting the color after disposal of the old backing store + private boolean haveCachedColor; + private float cachedR; + private float cachedG; + private float cachedB; + private float cachedA; + private Color cachedColor; + private boolean needToResetColor; + + // For debugging only + private Frame dbgFrame; + + // Debugging purposes only + private boolean debugged; + Pipelined_QuadRenderer mPipelinedQuadRenderer; + + //emzic: added boolean flag + private boolean useVertexArrays = true; + + //emzic: added boolean flag + private boolean isExtensionAvailable_GL_VERSION_1_5; + private boolean checkFor_isExtensionAvailable_GL_VERSION_1_5; + + // Whether GL_LINEAR filtering is enabled for the backing store + private boolean smoothing = true; + + /** Creates a new TextRenderer with the given font, using no + antialiasing or fractional metrics, and the default + RenderDelegate. Equivalent to <code>TextRenderer(font, false, + false)</code>. + + @param font the font to render with + */ + public TextRenderer(Font font) { + this(font, false, false, null, false); + } + + /** Creates a new TextRenderer with the given font, using no + antialiasing or fractional metrics, and the default + RenderDelegate. If <CODE>mipmap</CODE> is true, attempts to use + OpenGL's automatic mipmap generation for better smoothing when + rendering the TextureRenderer's contents at a distance. + Equivalent to <code>TextRenderer(font, false, false)</code>. + + @param font the font to render with + @param mipmap whether to attempt use of automatic mipmap generation + */ + public TextRenderer(Font font, boolean mipmap) { + this(font, false, false, null, mipmap); + } + + /** Creates a new TextRenderer with the given Font, specified font + properties, and default RenderDelegate. The + <code>antialiased</code> and <code>useFractionalMetrics</code> + flags provide control over the same properties at the Java 2D + level. No mipmap support is requested. Equivalent to + <code>TextRenderer(font, antialiased, useFractionalMetrics, + null)</code>. + + @param font the font to render with + @param antialiased whether to use antialiased fonts + @param useFractionalMetrics whether to use fractional font + metrics at the Java 2D level + */ + public TextRenderer(Font font, boolean antialiased, + boolean useFractionalMetrics) { + this(font, antialiased, useFractionalMetrics, null, false); + } + + /** Creates a new TextRenderer with the given Font, specified font + properties, and given RenderDelegate. The + <code>antialiased</code> and <code>useFractionalMetrics</code> + flags provide control over the same properties at the Java 2D + level. The <code>renderDelegate</code> provides more control + over the text rendered. No mipmap support is requested. + + @param font the font to render with + @param antialiased whether to use antialiased fonts + @param useFractionalMetrics whether to use fractional font + metrics at the Java 2D level + @param renderDelegate the render delegate to use to draw the + text's bitmap, or null to use the default one + */ + public TextRenderer(Font font, boolean antialiased, + boolean useFractionalMetrics, RenderDelegate renderDelegate) { + this(font, antialiased, useFractionalMetrics, renderDelegate, false); + } + + /** Creates a new TextRenderer with the given Font, specified font + properties, and given RenderDelegate. The + <code>antialiased</code> and <code>useFractionalMetrics</code> + flags provide control over the same properties at the Java 2D + level. The <code>renderDelegate</code> provides more control + over the text rendered. If <CODE>mipmap</CODE> is true, attempts + to use OpenGL's automatic mipmap generation for better smoothing + when rendering the TextureRenderer's contents at a distance. + + @param font the font to render with + @param antialiased whether to use antialiased fonts + @param useFractionalMetrics whether to use fractional font + metrics at the Java 2D level + @param renderDelegate the render delegate to use to draw the + text's bitmap, or null to use the default one + @param mipmap whether to attempt use of automatic mipmap generation + */ + public TextRenderer(Font font, boolean antialiased, + boolean useFractionalMetrics, RenderDelegate renderDelegate, + boolean mipmap) { + this.font = font; + this.antialiased = antialiased; + this.useFractionalMetrics = useFractionalMetrics; + this.mipmap = mipmap; + + // FIXME: consider adjusting the size based on font size + // (it will already automatically resize if necessary) + packer = new RectanglePacker(new Manager(), kSize, kSize); + + if (renderDelegate == null) { + renderDelegate = new DefaultRenderDelegate(); + } + + this.renderDelegate = renderDelegate; + + mGlyphProducer = new GlyphProducer(font.getNumGlyphs()); + } + + /** Returns the bounding rectangle of the given String, assuming it + was rendered at the origin. See {@link #getBounds(CharSequence) + getBounds(CharSequence)}. */ + public Rectangle2D getBounds(String str) { + return getBounds((CharSequence) str); + } + + /** Returns the bounding rectangle of the given CharSequence, + assuming it was rendered at the origin. The coordinate system of + the returned rectangle is Java 2D's, with increasing Y + coordinates in the downward direction. The relative coordinate + (0, 0) in the returned rectangle corresponds to the baseline of + the leftmost character of the rendered string, in similar + fashion to the results returned by, for example, {@link + java.awt.font.GlyphVector#getVisualBounds}. Most applications + will use only the width and height of the returned Rectangle for + the purposes of centering or justifying the String. It is not + specified which Java 2D bounds ({@link + java.awt.font.GlyphVector#getVisualBounds getVisualBounds}, + {@link java.awt.font.GlyphVector#getPixelBounds getPixelBounds}, + etc.) the returned bounds correspond to, although every effort + is made to ensure an accurate bound. */ + public Rectangle2D getBounds(CharSequence str) { + // FIXME: this should be more optimized and use the glyph cache + Rect r = null; + + if ((r = (Rect) stringLocations.get(str)) != null) { + TextData data = (TextData) r.getUserData(); + + // Reconstitute the Java 2D results based on the cached values + return new Rectangle2D.Double(-data.origin().x, -data.origin().y, + r.w(), r.h()); + } + + // Must return a Rectangle compatible with the layout algorithm -- + // must be idempotent + return normalize(renderDelegate.getBounds(str, font, + getFontRenderContext())); + } + + /** Returns the Font this renderer is using. */ + public Font getFont() { + return font; + } + + /** Returns a FontRenderContext which can be used for external + text-related size computations. This object should be considered + transient and may become invalidated between {@link + #beginRendering beginRendering} / {@link #endRendering + endRendering} pairs. */ + public FontRenderContext getFontRenderContext() { + if (cachedFontRenderContext == null) { + cachedFontRenderContext = getGraphics2D().getFontRenderContext(); + } + + return cachedFontRenderContext; + } + + /** Begins rendering with this {@link TextRenderer TextRenderer} + into the current OpenGL drawable, pushing the projection and + modelview matrices and some state bits and setting up a + two-dimensional orthographic projection with (0, 0) as the + lower-left coordinate and (width, height) as the upper-right + coordinate. Binds and enables the internal OpenGL texture + object, sets the texture environment mode to GL_MODULATE, and + changes the current color to the last color set with this + TextRenderer via {@link #setColor setColor}. This method + disables the depth test and is equivalent to + beginRendering(width, height, true). + + @param width the width of the current on-screen OpenGL drawable + @param height the height of the current on-screen OpenGL drawable + @throws javax.media.opengl.GLException If an OpenGL context is not current when this method is called + */ + public void beginRendering(int width, int height) throws GLException { + beginRendering(width, height, true); + } + + /** Begins rendering with this {@link TextRenderer TextRenderer} + into the current OpenGL drawable, pushing the projection and + modelview matrices and some state bits and setting up a + two-dimensional orthographic projection with (0, 0) as the + lower-left coordinate and (width, height) as the upper-right + coordinate. Binds and enables the internal OpenGL texture + object, sets the texture environment mode to GL_MODULATE, and + changes the current color to the last color set with this + TextRenderer via {@link #setColor setColor}. Disables the depth + test if the disableDepthTest argument is true. + + @param width the width of the current on-screen OpenGL drawable + @param height the height of the current on-screen OpenGL drawable + @param disableDepthTest whether to disable the depth test + @throws GLException If an OpenGL context is not current when this method is called + */ + public void beginRendering(int width, int height, boolean disableDepthTest) + throws GLException { + beginRendering(true, width, height, disableDepthTest); + } + + /** Begins rendering of 2D text in 3D with this {@link TextRenderer + TextRenderer} into the current OpenGL drawable. Assumes the end + user is responsible for setting up the modelview and projection + matrices, and will render text using the {@link #draw3D draw3D} + method. This method pushes some OpenGL state bits, binds and + enables the internal OpenGL texture object, sets the texture + environment mode to GL_MODULATE, and changes the current color + to the last color set with this TextRenderer via {@link + #setColor setColor}. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void begin3DRendering() throws GLException { + beginRendering(false, 0, 0, false); + } + + /** Changes the current color of this TextRenderer to the supplied + one. The default color is opaque white. + + @param color the new color to use for rendering text + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setColor(Color color) throws GLException { + boolean noNeedForFlush = (haveCachedColor && (cachedColor != null) && + color.equals(cachedColor)); + + if (!noNeedForFlush) { + flushGlyphPipeline(); + } + + getBackingStore().setColor(color); + haveCachedColor = true; + cachedColor = color; + } + + /** Changes the current color of this TextRenderer to the supplied + one, where each component ranges from 0.0f - 1.0f. The alpha + component, if used, does not need to be premultiplied into the + color channels as described in the documentation for {@link + com.jogamp.opengl.util.texture.Texture Texture}, although + premultiplied colors are used internally. The default color is + opaque white. + + @param r the red component of the new color + @param g the green component of the new color + @param b the blue component of the new color + @param a the alpha component of the new color, 0.0f = completely + transparent, 1.0f = completely opaque + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setColor(float r, float g, float b, float a) + throws GLException { + boolean noNeedForFlush = (haveCachedColor && (cachedColor == null) && + (r == cachedR) && (g == cachedG) && (b == cachedB) && + (a == cachedA)); + + if (!noNeedForFlush) { + flushGlyphPipeline(); + } + + getBackingStore().setColor(r, g, b, a); + haveCachedColor = true; + cachedR = r; + cachedG = g; + cachedB = b; + cachedA = a; + cachedColor = null; + } + + /** Draws the supplied CharSequence at the desired location using + the renderer's current color. The baseline of the leftmost + character is at position (x, y) specified in OpenGL coordinates, + where the origin is at the lower-left of the drawable and the Y + coordinate increases in the upward direction. + + @param str the string to draw + @param x the x coordinate at which to draw + @param y the y coordinate at which to draw + @throws GLException If an OpenGL context is not current when this method is called + */ + public void draw(CharSequence str, int x, int y) throws GLException { + draw3D(str, x, y, 0, 1); + } + + /** Draws the supplied String at the desired location using the + renderer's current color. See {@link #draw(CharSequence, int, + int) draw(CharSequence, int, int)}. */ + public void draw(String str, int x, int y) throws GLException { + draw3D(str, x, y, 0, 1); + } + + /** Draws the supplied CharSequence at the desired 3D location using + the renderer's current color. The baseline of the leftmost + character is placed at position (x, y, z) in the current + coordinate system. + + @param str the string to draw + @param x the x coordinate at which to draw + @param y the y coordinate at which to draw + @param z the z coordinate at which to draw + @param scaleFactor a uniform scale factor applied to the width and height of the drawn rectangle + @throws GLException If an OpenGL context is not current when this method is called + */ + public void draw3D(CharSequence str, float x, float y, float z, + float scaleFactor) { + internal_draw3D(str, x, y, z, scaleFactor); + } + + /** Draws the supplied String at the desired 3D location using the + renderer's current color. See {@link #draw3D(CharSequence, + float, float, float, float) draw3D(CharSequence, float, float, + float, float)}. */ + public void draw3D(String str, float x, float y, float z, float scaleFactor) { + internal_draw3D(str, x, y, z, scaleFactor); + } + + /** Returns the pixel width of the given character. */ + public float getCharWidth(char inChar) { + return mGlyphProducer.getGlyphPixelWidth(inChar); + } + + /** Causes the TextRenderer to flush any internal caches it may be + maintaining and draw its rendering results to the screen. This + should be called after each call to draw() if you are setting + OpenGL state such as the modelview matrix between calls to + draw(). */ + public void flush() { + flushGlyphPipeline(); + } + + /** Ends a render cycle with this {@link TextRenderer TextRenderer}. + Restores the projection and modelview matrices as well as + several OpenGL state bits. Should be paired with {@link + #beginRendering beginRendering}. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void endRendering() throws GLException { + endRendering(true); + } + + /** Ends a 3D render cycle with this {@link TextRenderer TextRenderer}. + Restores several OpenGL state bits. Should be paired with {@link + #begin3DRendering begin3DRendering}. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void end3DRendering() throws GLException { + endRendering(false); + } + + /** Disposes of all resources this TextRenderer is using. It is not + valid to use the TextRenderer after this method is called. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void dispose() throws GLException { + packer.dispose(); + packer = null; + cachedBackingStore = null; + cachedGraphics = null; + cachedFontRenderContext = null; + + if (dbgFrame != null) { + dbgFrame.dispose(); + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static Rectangle2D preNormalize(Rectangle2D src) { + // Need to round to integer coordinates + // Also give ourselves a little slop around the reported + // bounds of glyphs because it looks like neither the visual + // nor the pixel bounds works perfectly well + int minX = (int) Math.floor(src.getMinX()) - 1; + int minY = (int) Math.floor(src.getMinY()) - 1; + int maxX = (int) Math.ceil(src.getMaxX()) + 1; + int maxY = (int) Math.ceil(src.getMaxY()) + 1; + return new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY); + } + + + private Rectangle2D normalize(Rectangle2D src) { + // Give ourselves a boundary around each entity on the backing + // store in order to prevent bleeding of nearby Strings due to + // the fact that we use linear filtering + + // NOTE that this boundary is quite heuristic and is related + // to how far away in 3D we may view the text -- + // heuristically, 1.5% of the font's height + int boundary = (int) Math.max(1, 0.015 * font.getSize()); + + return new Rectangle2D.Double((int) Math.floor(src.getMinX() - boundary), + (int) Math.floor(src.getMinY() - boundary), + (int) Math.ceil(src.getWidth() + 2 * boundary), + (int) Math.ceil(src.getHeight()) + 2 * boundary); + } + + private TextureRenderer getBackingStore() { + TextureRenderer renderer = (TextureRenderer) packer.getBackingStore(); + + if (renderer != cachedBackingStore) { + // Backing store changed since last time; discard any cached Graphics2D + if (cachedGraphics != null) { + cachedGraphics.dispose(); + cachedGraphics = null; + cachedFontRenderContext = null; + } + + cachedBackingStore = renderer; + } + + return cachedBackingStore; + } + + private Graphics2D getGraphics2D() { + TextureRenderer renderer = getBackingStore(); + + if (cachedGraphics == null) { + cachedGraphics = renderer.createGraphics(); + + // Set up composite, font and rendering hints + cachedGraphics.setComposite(AlphaComposite.Src); + cachedGraphics.setColor(Color.WHITE); + cachedGraphics.setFont(font); + cachedGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + (antialiased ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON + : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)); + cachedGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, + (useFractionalMetrics + ? RenderingHints.VALUE_FRACTIONALMETRICS_ON + : RenderingHints.VALUE_FRACTIONALMETRICS_OFF)); + } + + return cachedGraphics; + } + + private void beginRendering(boolean ortho, int width, int height, + boolean disableDepthTestForOrtho) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + + if (DEBUG && !debugged) { + debug(gl); + } + + inBeginEndPair = true; + isOrthoMode = ortho; + beginRenderingWidth = width; + beginRenderingHeight = height; + beginRenderingDepthTestDisabled = disableDepthTestForOrtho; + + if (ortho) { + getBackingStore().beginOrthoRendering(width, height, + disableDepthTestForOrtho); + } else { + getBackingStore().begin3DRendering(); + } + + // Push client attrib bits used by the pipelined quad renderer + gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS); + + if (!haveMaxSize) { + // Query OpenGL for the maximum texture size and set it in the + // RectanglePacker to keep it from expanding too large + int[] sz = new int[1]; + gl.glGetIntegerv(GL2.GL_MAX_TEXTURE_SIZE, sz, 0); + packer.setMaxSize(sz[0], sz[0]); + haveMaxSize = true; + } + + if (needToResetColor && haveCachedColor) { + if (cachedColor == null) { + getBackingStore().setColor(cachedR, cachedG, cachedB, cachedA); + } else { + getBackingStore().setColor(cachedColor); + } + + needToResetColor = false; + } + + // Disable future attempts to use mipmapping if TextureRenderer + // doesn't support it + if (mipmap && !getBackingStore().isUsingAutoMipmapGeneration()) { + if (DEBUG) { + System.err.println("Disabled mipmapping in TextRenderer"); + } + + mipmap = false; + } + } + + /** + * emzic: here the call to glBindBuffer crashes on certain graphicscard/driver combinations + * this is why the ugly try-catch block has been added, which falls back to the old textrenderer + * + * @param ortho + * @throws GLException + */ + private void endRendering(boolean ortho) throws GLException { + flushGlyphPipeline(); + + inBeginEndPair = false; + + GL2 gl = GLContext.getCurrentGL().getGL2(); + + // Pop client attrib bits used by the pipelined quad renderer + gl.glPopClientAttrib(); + + // The OpenGL spec is unclear about whether this changes the + // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER + // binding + if (is15Available(gl)) { + try { + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); + } catch (Exception e) { + isExtensionAvailable_GL_VERSION_1_5 = false; + } + } + + if (ortho) { + getBackingStore().endOrthoRendering(); + } else { + getBackingStore().end3DRendering(); + } + + if (++numRenderCycles >= CYCLES_PER_FLUSH) { + numRenderCycles = 0; + + if (DEBUG) { + System.err.println("Clearing unused entries in endRendering()"); + } + + clearUnusedEntries(); + } + } + + private void clearUnusedEntries() { + final java.util.List deadRects = new ArrayList /*<Rect>*/(); + + // Iterate through the contents of the backing store, removing + // text strings that haven't been used recently + packer.visit(new RectVisitor() { + public void visit(Rect rect) { + TextData data = (TextData) rect.getUserData(); + + if (data.used()) { + data.clearUsed(); + } else { + deadRects.add(rect); + } + } + }); + + for (Iterator iter = deadRects.iterator(); iter.hasNext();) { + Rect r = (Rect) iter.next(); + packer.remove(r); + stringLocations.remove(((TextData) r.getUserData()).string()); + + int unicodeToClearFromCache = ((TextData) r.getUserData()).unicodeID; + + if (unicodeToClearFromCache > 0) { + mGlyphProducer.clearCacheEntry(unicodeToClearFromCache); + } + + // if (DEBUG) { + // Graphics2D g = getGraphics2D(); + // g.setComposite(AlphaComposite.Clear); + // g.fillRect(r.x(), r.y(), r.w(), r.h()); + // g.setComposite(AlphaComposite.Src); + // } + } + + // If we removed dead rectangles this cycle, try to do a compaction + float frag = packer.verticalFragmentationRatio(); + + if (!deadRects.isEmpty() && (frag > MAX_VERTICAL_FRAGMENTATION)) { + if (DEBUG) { + System.err.println( + "Compacting TextRenderer backing store due to vertical fragmentation " + + frag); + } + + packer.compact(); + } + + if (DEBUG) { + getBackingStore().markDirty(0, 0, getBackingStore().getWidth(), + getBackingStore().getHeight()); + } + } + + private void internal_draw3D(CharSequence str, float x, float y, float z, + float scaleFactor) { + List/*<Glyph>*/ glyphs = mGlyphProducer.getGlyphs(str); + for (Iterator iter = glyphs.iterator(); iter.hasNext(); ) { + Glyph glyph = (Glyph) iter.next(); + float advance = glyph.draw3D(x, y, z, scaleFactor); + x += advance * scaleFactor; + } + } + + private void flushGlyphPipeline() { + if (mPipelinedQuadRenderer != null) { + mPipelinedQuadRenderer.draw(); + } + } + + private void draw3D_ROBUST(CharSequence str, float x, float y, float z, + float scaleFactor) { + String curStr; + if (str instanceof String) { + curStr = (String) str; + } else { + curStr = str.toString(); + } + + // Look up the string on the backing store + Rect rect = (Rect) stringLocations.get(curStr); + + if (rect == null) { + // Rasterize this string and place it on the backing store + Graphics2D g = getGraphics2D(); + Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(curStr, font, getFontRenderContext())); + Rectangle2D bbox = normalize(origBBox); + Point origin = new Point((int) -bbox.getMinX(), + (int) -bbox.getMinY()); + rect = new Rect(0, 0, (int) bbox.getWidth(), + (int) bbox.getHeight(), + new TextData(curStr, origin, origBBox, -1)); + + packer.add(rect); + stringLocations.put(curStr, rect); + + // Re-fetch the Graphics2D in case the addition of the rectangle + // caused the old backing store to be thrown away + g = getGraphics2D(); + + // OK, should now have an (x, y) for this rectangle; rasterize + // the String + int strx = rect.x() + origin.x; + int stry = rect.y() + origin.y; + + // Clear out the area we're going to draw into + g.setComposite(AlphaComposite.Clear); + g.fillRect(rect.x(), rect.y(), rect.w(), rect.h()); + g.setComposite(AlphaComposite.Src); + + // Draw the string + renderDelegate.draw(g, curStr, strx, stry); + + if (DRAW_BBOXES) { + TextData data = (TextData) rect.getUserData(); + // Draw a bounding box on the backing store + g.drawRect(strx - data.origOriginX(), + stry - data.origOriginY(), + (int) data.origRect().getWidth(), + (int) data.origRect().getHeight()); + g.drawRect(strx - data.origin().x, + stry - data.origin().y, + rect.w(), + rect.h()); + } + + // Mark this region of the TextureRenderer as dirty + getBackingStore().markDirty(rect.x(), rect.y(), rect.w(), + rect.h()); + } + + // OK, now draw the portion of the backing store to the screen + TextureRenderer renderer = getBackingStore(); + + // NOTE that the rectangles managed by the packer have their + // origin at the upper-left but the TextureRenderer's origin is + // at its lower left!!! + TextData data = (TextData) rect.getUserData(); + data.markUsed(); + + Rectangle2D origRect = data.origRect(); + + // Align the leftmost point of the baseline to the (x, y, z) coordinate requested + renderer.draw3DRect(x - (scaleFactor * data.origOriginX()), + y - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY())), z, + rect.x() + (data.origin().x - data.origOriginX()), + renderer.getHeight() - rect.y() - (int) origRect.getHeight() - + (data.origin().y - data.origOriginY()), + (int) origRect.getWidth(), (int) origRect.getHeight(), scaleFactor); + } + + //---------------------------------------------------------------------- + // Debugging functionality + // + private void debug(GL gl) { + dbgFrame = new Frame("TextRenderer Debug Output"); + + GLCanvas dbgCanvas = new GLCanvas(new GLCapabilities(gl.getGLProfile()), null, + GLContext.getCurrent(), null); + dbgCanvas.addGLEventListener(new DebugListener(gl, dbgFrame)); + dbgFrame.add(dbgCanvas); + + final FPSAnimator anim = new FPSAnimator(dbgCanvas, 10); + dbgFrame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + // Run this on another thread than the AWT event queue to + // make sure the call to Animator.stop() completes before + // exiting + new Thread(new Runnable() { + public void run() { + anim.stop(); + } + }).start(); + } + }); + dbgFrame.setSize(kSize, kSize); + dbgFrame.setVisible(true); + anim.start(); + debugged = true; + } + + /** Class supporting more full control over the process of rendering + the bitmapped text. Allows customization of whether the backing + store text bitmap is full-color or intensity only, the size of + each individual rendered text rectangle, and the contents of + each individual rendered text string. The default implementation + of this interface uses an intensity-only texture, a + closely-cropped rectangle around the text, and renders text + using the color white, which is modulated by the set color + during the rendering process. */ + public static interface RenderDelegate { + /** Indicates whether the backing store of this TextRenderer + should be intensity-only (the default) or full-color. */ + public boolean intensityOnly(); + + /** Computes the bounds of the given String relative to the + origin. */ + public Rectangle2D getBounds(String str, Font font, + FontRenderContext frc); + + /** Computes the bounds of the given character sequence relative + to the origin. */ + public Rectangle2D getBounds(CharSequence str, Font font, + FontRenderContext frc); + + /** Computes the bounds of the given GlyphVector, already + assumed to have been created for a particular Font, + relative to the origin. */ + public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc); + + /** Render the passed character sequence at the designated + location using the supplied Graphics2D instance. The + surrounding region will already have been cleared to the RGB + color (0, 0, 0) with zero alpha. The initial drawing context + of the passed Graphics2D will be set to use + AlphaComposite.Src, the color white, the Font specified in the + TextRenderer's constructor, and the rendering hints specified + in the TextRenderer constructor. Changes made by the end user + may be visible in successive calls to this method, but are not + guaranteed to be preserved. Implementors of this method + should reset the Graphics2D's state to that desired each time + this method is called, in particular those states which are + not the defaults. */ + public void draw(Graphics2D graphics, String str, int x, int y); + + /** Render the passed GlyphVector at the designated location using + the supplied Graphics2D instance. The surrounding region will + already have been cleared to the RGB color (0, 0, 0) with zero + alpha. The initial drawing context of the passed Graphics2D + will be set to use AlphaComposite.Src, the color white, the + Font specified in the TextRenderer's constructor, and the + rendering hints specified in the TextRenderer constructor. + Changes made by the end user may be visible in successive + calls to this method, but are not guaranteed to be preserved. + Implementors of this method should reset the Graphics2D's + state to that desired each time this method is called, in + particular those states which are not the defaults. */ + public void drawGlyphVector(Graphics2D graphics, GlyphVector str, + int x, int y); + } + + private static class CharSequenceIterator implements CharacterIterator { + CharSequence mSequence; + int mLength; + int mCurrentIndex; + + CharSequenceIterator() { + } + + CharSequenceIterator(CharSequence sequence) { + initFromCharSequence(sequence); + } + + public void initFromCharSequence(CharSequence sequence) { + mSequence = sequence; + mLength = mSequence.length(); + mCurrentIndex = 0; + } + + public char last() { + mCurrentIndex = Math.max(0, mLength - 1); + + return current(); + } + + public char current() { + if ((mLength == 0) || (mCurrentIndex >= mLength)) { + return CharacterIterator.DONE; + } + + return mSequence.charAt(mCurrentIndex); + } + + public char next() { + mCurrentIndex++; + + return current(); + } + + public char previous() { + mCurrentIndex = Math.max(mCurrentIndex - 1, 0); + + return current(); + } + + public char setIndex(int position) { + mCurrentIndex = position; + + return current(); + } + + public int getBeginIndex() { + return 0; + } + + public int getEndIndex() { + return mLength; + } + + public int getIndex() { + return mCurrentIndex; + } + + public Object clone() { + CharSequenceIterator iter = new CharSequenceIterator(mSequence); + iter.mCurrentIndex = mCurrentIndex; + + return iter; + } + + public char first() { + if (mLength == 0) { + return CharacterIterator.DONE; + } + + mCurrentIndex = 0; + + return current(); + } + } + + // Data associated with each rectangle of text + static class TextData { + // Back-pointer to String this TextData describes, if it + // represents a String rather than a single glyph + private String str; + + // If this TextData represents a single glyph, this is its + // unicode ID + int unicodeID; + + // The following must be defined and used VERY precisely. This is + // the offset from the upper-left corner of this rectangle (Java + // 2D coordinate system) at which the string must be rasterized in + // order to fit within the rectangle -- the leftmost point of the + // baseline. + private Point origin; + + // This represents the pre-normalized rectangle, which fits + // within the rectangle on the backing store. We keep a + // one-pixel border around entries on the backing store to + // prevent bleeding of adjacent letters when using GL_LINEAR + // filtering for rendering. The origin of this rectangle is + // equivalent to the origin above. + private Rectangle2D origRect; + + private boolean used; // Whether this text was used recently + + TextData(String str, Point origin, Rectangle2D origRect, int unicodeID) { + this.str = str; + this.origin = origin; + this.origRect = origRect; + this.unicodeID = unicodeID; + } + + String string() { + return str; + } + + Point origin() { + return origin; + } + + // The following three methods are used to locate the glyph + // within the expanded rectangle coming from normalize() + int origOriginX() { + return (int) -origRect.getMinX(); + } + + int origOriginY() { + return (int) -origRect.getMinY(); + } + + Rectangle2D origRect() { + return origRect; + } + + boolean used() { + return used; + } + + void markUsed() { + used = true; + } + + void clearUsed() { + used = false; + } + } + + class Manager implements BackingStoreManager { + private Graphics2D g; + + public Object allocateBackingStore(int w, int h) { + // FIXME: should consider checking Font's attributes to see + // whether we're likely to need to support a full RGBA backing + // store (i.e., non-default Paint, foreground color, etc.), but + // for now, let's just be more efficient + TextureRenderer renderer; + + if (renderDelegate.intensityOnly()) { + renderer = TextureRenderer.createAlphaOnlyRenderer(w, h, mipmap); + } else { + renderer = new TextureRenderer(w, h, true, mipmap); + } + renderer.setSmoothing(smoothing); + + if (DEBUG) { + System.err.println(" TextRenderer allocating backing store " + + w + " x " + h); + } + + return renderer; + } + + public void deleteBackingStore(Object backingStore) { + ((TextureRenderer) backingStore).dispose(); + } + + public boolean preExpand(Rect cause, int attemptNumber) { + // Only try this one time; clear out potentially obsolete entries + // NOTE: this heuristic and the fact that it clears the used bit + // of all entries seems to cause cycling of entries in some + // situations, where the backing store becomes small compared to + // the amount of text on the screen (see the TextFlow demo) and + // the entries continually cycle in and out of the backing + // store, decreasing performance. If we added a little age + // information to the entries, and only cleared out entries + // above a certain age, this behavior would be eliminated. + // However, it seems the system usually stabilizes itself, so + // for now we'll just keep things simple. Note that if we don't + // clear the used bit here, the backing store tends to increase + // very quickly to its maximum size, at least with the TextFlow + // demo when the text is being continually re-laid out. + if (attemptNumber == 0) { + if (DEBUG) { + System.err.println( + "Clearing unused entries in preExpand(): attempt number " + + attemptNumber); + } + + if (inBeginEndPair) { + // Draw any outstanding glyphs + flush(); + } + + clearUnusedEntries(); + + return true; + } + + return false; + } + + public boolean additionFailed(Rect cause, int attemptNumber) { + // Heavy hammer -- might consider doing something different + packer.clear(); + stringLocations.clear(); + mGlyphProducer.clearAllCacheEntries(); + + if (DEBUG) { + System.err.println( + " *** Cleared all text because addition failed ***"); + } + + if (attemptNumber == 0) { + return true; + } + + return false; + } + + public boolean canCompact() { + return true; + } + + public void beginMovement(Object oldBackingStore, Object newBackingStore) { + // Exit the begin / end pair if necessary + if (inBeginEndPair) { + // Draw any outstanding glyphs + flush(); + + GL2 gl = GLContext.getCurrentGL().getGL2(); + + // Pop client attrib bits used by the pipelined quad renderer + gl.glPopClientAttrib(); + + // The OpenGL spec is unclear about whether this changes the + // buffer bindings, so preemptively zero out the GL_ARRAY_BUFFER + // binding + if (is15Available(gl)) { + try { + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0); + } catch (Exception e) { + isExtensionAvailable_GL_VERSION_1_5 = false; + } + } + + if (isOrthoMode) { + ((TextureRenderer) oldBackingStore).endOrthoRendering(); + } else { + ((TextureRenderer) oldBackingStore).end3DRendering(); + } + } + + TextureRenderer newRenderer = (TextureRenderer) newBackingStore; + g = newRenderer.createGraphics(); + } + + public void move(Object oldBackingStore, Rect oldLocation, + Object newBackingStore, Rect newLocation) { + TextureRenderer oldRenderer = (TextureRenderer) oldBackingStore; + TextureRenderer newRenderer = (TextureRenderer) newBackingStore; + + if (oldRenderer == newRenderer) { + // Movement on the same backing store -- easy case + g.copyArea(oldLocation.x(), oldLocation.y(), oldLocation.w(), + oldLocation.h(), newLocation.x() - oldLocation.x(), + newLocation.y() - oldLocation.y()); + } else { + // Need to draw from the old renderer's image into the new one + Image img = oldRenderer.getImage(); + g.drawImage(img, newLocation.x(), newLocation.y(), + newLocation.x() + newLocation.w(), + newLocation.y() + newLocation.h(), oldLocation.x(), + oldLocation.y(), oldLocation.x() + oldLocation.w(), + oldLocation.y() + oldLocation.h(), null); + } + } + + public void endMovement(Object oldBackingStore, Object newBackingStore) { + g.dispose(); + + // Sync the whole surface + TextureRenderer newRenderer = (TextureRenderer) newBackingStore; + newRenderer.markDirty(0, 0, newRenderer.getWidth(), + newRenderer.getHeight()); + + // Re-enter the begin / end pair if necessary + if (inBeginEndPair) { + if (isOrthoMode) { + ((TextureRenderer) newBackingStore).beginOrthoRendering(beginRenderingWidth, + beginRenderingHeight, beginRenderingDepthTestDisabled); + } else { + ((TextureRenderer) newBackingStore).begin3DRendering(); + } + + // Push client attrib bits used by the pipelined quad renderer + GL2 gl = GLContext.getCurrentGL().getGL2(); + gl.glPushClientAttrib((int) GL2.GL_ALL_CLIENT_ATTRIB_BITS); + + if (haveCachedColor) { + if (cachedColor == null) { + ((TextureRenderer) newBackingStore).setColor(cachedR, + cachedG, cachedB, cachedA); + } else { + ((TextureRenderer) newBackingStore).setColor(cachedColor); + } + } + } else { + needToResetColor = true; + } + } + } + + public static class DefaultRenderDelegate implements RenderDelegate { + public boolean intensityOnly() { + return true; + } + + public Rectangle2D getBounds(CharSequence str, Font font, + FontRenderContext frc) { + return getBounds(font.createGlyphVector(frc, + new CharSequenceIterator(str)), + frc); + } + + public Rectangle2D getBounds(String str, Font font, + FontRenderContext frc) { + return getBounds(font.createGlyphVector(frc, str), frc); + } + + public Rectangle2D getBounds(GlyphVector gv, FontRenderContext frc) { + return gv.getVisualBounds(); + } + + public void drawGlyphVector(Graphics2D graphics, GlyphVector str, + int x, int y) { + graphics.drawGlyphVector(str, x, y); + } + + public void draw(Graphics2D graphics, String str, int x, int y) { + graphics.drawString(str, x, y); + } + } + + //---------------------------------------------------------------------- + // Glyph-by-glyph rendering support + // + + // A temporary to prevent excessive garbage creation + private char[] singleUnicode = new char[1]; + + /** A Glyph represents either a single unicode glyph or a + substring of characters to be drawn. The reason for the dual + behavior is so that we can take in a sequence of unicode + characters and partition them into runs of individual glyphs, + but if we encounter complex text and/or unicode sequences we + don't understand, we can render them using the + string-by-string method. <P> + + Glyphs need to be able to re-upload themselves to the backing + store on demand as we go along in the render sequence. + */ + + class Glyph { + // If this Glyph represents an individual unicode glyph, this + // is its unicode ID. If it represents a String, this is -1. + private int unicodeID; + // If the above field isn't -1, then these fields are used. + // The glyph code in the font + private int glyphCode; + // The GlyphProducer which created us + private GlyphProducer producer; + // The advance of this glyph + private float advance; + // The GlyphVector for this single character; this is passed + // in during construction but cleared during the upload + // process + private GlyphVector singleUnicodeGlyphVector; + // The rectangle of this glyph on the backing store, or null + // if it has been cleared due to space pressure + private Rect glyphRectForTextureMapping; + // If this Glyph represents a String, this is the sequence of + // characters + private String str; + // Whether we need a valid advance when rendering this string + // (i.e., whether it has other single glyphs coming after it) + private boolean needAdvance; + + // Creates a Glyph representing an individual Unicode character + public Glyph(int unicodeID, + int glyphCode, + float advance, + GlyphVector singleUnicodeGlyphVector, + GlyphProducer producer) { + this.unicodeID = unicodeID; + this.glyphCode = glyphCode; + this.advance = advance; + this.singleUnicodeGlyphVector = singleUnicodeGlyphVector; + this.producer = producer; + } + + // Creates a Glyph representing a sequence of characters, with + // an indication of whether additional single glyphs are being + // rendered after it + public Glyph(String str, boolean needAdvance) { + this.str = str; + this.needAdvance = needAdvance; + } + + /** Returns this glyph's unicode ID */ + public int getUnicodeID() { + return unicodeID; + } + + /** Returns this glyph's (font-specific) glyph code */ + public int getGlyphCode() { + return glyphCode; + } + + /** Returns the advance for this glyph */ + public float getAdvance() { + return advance; + } + + /** Draws this glyph and returns the (x) advance for this glyph */ + public float draw3D(float inX, float inY, float z, float scaleFactor) { + if (str != null) { + draw3D_ROBUST(str, inX, inY, z, scaleFactor); + if (!needAdvance) { + return 0; + } + // Compute and return the advance for this string + GlyphVector gv = font.createGlyphVector(getFontRenderContext(), str); + float totalAdvance = 0; + for (int i = 0; i < gv.getNumGlyphs(); i++) { + totalAdvance += gv.getGlyphMetrics(i).getAdvance(); + } + return totalAdvance; + } + + // This is the code path taken for individual glyphs + if (glyphRectForTextureMapping == null) { + upload(); + } + + try { + if (mPipelinedQuadRenderer == null) { + mPipelinedQuadRenderer = new Pipelined_QuadRenderer(); + } + + TextureRenderer renderer = getBackingStore(); + // Handles case where NPOT texture is used for backing store + TextureCoords wholeImageTexCoords = renderer.getTexture().getImageTexCoords(); + float xScale = wholeImageTexCoords.right(); + float yScale = wholeImageTexCoords.bottom(); + + Rect rect = glyphRectForTextureMapping; + TextData data = (TextData) rect.getUserData(); + data.markUsed(); + + Rectangle2D origRect = data.origRect(); + + float x = inX - (scaleFactor * data.origOriginX()); + float y = inY - (scaleFactor * ((float) origRect.getHeight() - data.origOriginY())); + + int texturex = rect.x() + (data.origin().x - data.origOriginX()); + int texturey = renderer.getHeight() - rect.y() - (int) origRect.getHeight() - + (data.origin().y - data.origOriginY()); + int width = (int) origRect.getWidth(); + int height = (int) origRect.getHeight(); + + float tx1 = xScale * (float) texturex / (float) renderer.getWidth(); + float ty1 = yScale * (1.0f - + ((float) texturey / (float) renderer.getHeight())); + float tx2 = xScale * (float) (texturex + width) / (float) renderer.getWidth(); + float ty2 = yScale * (1.0f - + ((float) (texturey + height) / (float) renderer.getHeight())); + + mPipelinedQuadRenderer.glTexCoord2f(tx1, ty1); + mPipelinedQuadRenderer.glVertex3f(x, y, z); + mPipelinedQuadRenderer.glTexCoord2f(tx2, ty1); + mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor), y, + z); + mPipelinedQuadRenderer.glTexCoord2f(tx2, ty2); + mPipelinedQuadRenderer.glVertex3f(x + (width * scaleFactor), + y + (height * scaleFactor), z); + mPipelinedQuadRenderer.glTexCoord2f(tx1, ty2); + mPipelinedQuadRenderer.glVertex3f(x, + y + (height * scaleFactor), z); + } catch (Exception e) { + e.printStackTrace(); + } + return advance; + } + + /** Notifies this glyph that it's been cleared out of the cache */ + public void clear() { + glyphRectForTextureMapping = null; + } + + private void upload() { + GlyphVector gv = getGlyphVector(); + Rectangle2D origBBox = preNormalize(renderDelegate.getBounds(gv, getFontRenderContext())); + Rectangle2D bbox = normalize(origBBox); + Point origin = new Point((int) -bbox.getMinX(), + (int) -bbox.getMinY()); + Rect rect = new Rect(0, 0, (int) bbox.getWidth(), + (int) bbox.getHeight(), + new TextData(null, origin, origBBox, unicodeID)); + packer.add(rect); + glyphRectForTextureMapping = rect; + Graphics2D g = getGraphics2D(); + // OK, should now have an (x, y) for this rectangle; rasterize + // the glyph + int strx = rect.x() + origin.x; + int stry = rect.y() + origin.y; + + // Clear out the area we're going to draw into + g.setComposite(AlphaComposite.Clear); + g.fillRect(rect.x(), rect.y(), rect.w(), rect.h()); + g.setComposite(AlphaComposite.Src); + + // Draw the string + renderDelegate.drawGlyphVector(g, gv, strx, stry); + + if (DRAW_BBOXES) { + TextData data = (TextData) rect.getUserData(); + // Draw a bounding box on the backing store + g.drawRect(strx - data.origOriginX(), + stry - data.origOriginY(), + (int) data.origRect().getWidth(), + (int) data.origRect().getHeight()); + g.drawRect(strx - data.origin().x, + stry - data.origin().y, + rect.w(), + rect.h()); + } + + // Mark this region of the TextureRenderer as dirty + getBackingStore().markDirty(rect.x(), rect.y(), rect.w(), + rect.h()); + // Re-register ourselves with our producer + producer.register(this); + } + + private GlyphVector getGlyphVector() { + GlyphVector gv = singleUnicodeGlyphVector; + if (gv != null) { + singleUnicodeGlyphVector = null; // Don't need this anymore + return gv; + } + singleUnicode[0] = (char) unicodeID; + return font.createGlyphVector(getFontRenderContext(), singleUnicode); + } + } + + class GlyphProducer { + final int undefined = -2; + FontRenderContext fontRenderContext; + List/*<Glyph>*/ glyphsOutput = new ArrayList/*<Glyph>*/(); + // The mapping from unicode character to font-specific glyph ID + int[] unicodes2Glyphs; + // The mapping from glyph ID to Glyph + Glyph[] glyphCache; + // We re-use this for each incoming string + CharSequenceIterator iter = new CharSequenceIterator(); + + GlyphProducer(int fontLengthInGlyphs) { + unicodes2Glyphs = new int[512]; + glyphCache = new Glyph[fontLengthInGlyphs]; + clearAllCacheEntries(); + } + + public List/*<Glyph>*/ getGlyphs(CharSequence inString) { + glyphsOutput.clear(); + iter.initFromCharSequence(inString); + GlyphVector fullRunGlyphVector = font.createGlyphVector(getFontRenderContext(), + iter); + boolean complex = (fullRunGlyphVector.getLayoutFlags() != 0); + if (complex || DISABLE_GLYPH_CACHE) { + // Punt to the robust version of the renderer + glyphsOutput.add(new Glyph(inString.toString(), false)); + return glyphsOutput; + } + + int lengthInGlyphs = fullRunGlyphVector.getNumGlyphs(); + int i = 0; + while (i < lengthInGlyphs) { + Glyph glyph = getGlyph(inString, fullRunGlyphVector, i); + if (glyph != null) { + glyphsOutput.add(glyph); + i++; + } else { + // Assemble a run of characters that don't fit in + // the cache + StringBuffer buf = new StringBuffer(); + while (i < lengthInGlyphs && + getGlyph(inString, fullRunGlyphVector, i) == null) { + buf.append(inString.charAt(i++)); + } + glyphsOutput.add(new Glyph(buf.toString(), + // Any more glyphs after this run? + i < lengthInGlyphs)); + } + } + return glyphsOutput; + } + + public void clearCacheEntry(int unicodeID) { + int glyphID = unicodes2Glyphs[unicodeID]; + if (glyphID != undefined) { + Glyph glyph = glyphCache[glyphID]; + if (glyph != null) { + glyph.clear(); + } + glyphCache[glyphID] = null; + } + unicodes2Glyphs[unicodeID] = undefined; + } + + public void clearAllCacheEntries() { + for (int i = 0; i < unicodes2Glyphs.length; i++) { + clearCacheEntry(i); + } + } + + public void register(Glyph glyph) { + unicodes2Glyphs[glyph.getUnicodeID()] = glyph.getGlyphCode(); + glyphCache[glyph.getGlyphCode()] = glyph; + } + + public float getGlyphPixelWidth(char unicodeID) { + Glyph glyph = getGlyph(unicodeID); + if (glyph != null) { + return glyph.getAdvance(); + } + + // Have to do this the hard / uncached way + singleUnicode[0] = unicodeID; + GlyphVector gv = font.createGlyphVector(fontRenderContext, + singleUnicode); + return gv.getGlyphMetrics(0).getAdvance(); + } + + // Returns a glyph object for this single glyph. Returns null + // if the unicode or glyph ID would be out of bounds of the + // glyph cache. + private Glyph getGlyph(CharSequence inString, + GlyphVector fullRunGlyphVector, + int index) { + char unicodeID = inString.charAt(index); + + if (unicodeID >= unicodes2Glyphs.length) { + return null; + } + + int glyphID = unicodes2Glyphs[unicodeID]; + if (glyphID != undefined) { + return glyphCache[glyphID]; + } + + // Must fabricate the glyph + singleUnicode[0] = unicodeID; + GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode); + return getGlyph(unicodeID, gv, fullRunGlyphVector.getGlyphMetrics(index)); + } + + // It's unclear whether this variant might produce less + // optimal results than if we can see the entire GlyphVector + // for the incoming string + private Glyph getGlyph(int unicodeID) { + if (unicodeID >= unicodes2Glyphs.length) { + return null; + } + + int glyphID = unicodes2Glyphs[unicodeID]; + if (glyphID != undefined) { + return glyphCache[glyphID]; + } + singleUnicode[0] = (char) unicodeID; + GlyphVector gv = font.createGlyphVector(getFontRenderContext(), singleUnicode); + return getGlyph(unicodeID, gv, gv.getGlyphMetrics(0)); + } + + private Glyph getGlyph(int unicodeID, + GlyphVector singleUnicodeGlyphVector, + GlyphMetrics metrics) { + int glyphCode = singleUnicodeGlyphVector.getGlyphCode(0); + // Have seen huge glyph codes (65536) coming out of some fonts in some Unicode situations + if (glyphCode >= glyphCache.length) { + return null; + } + Glyph glyph = new Glyph(unicodeID, + glyphCode, + metrics.getAdvance(), + singleUnicodeGlyphVector, + this); + register(glyph); + return glyph; + } + } + + class Pipelined_QuadRenderer { + int mOutstandingGlyphsVerticesPipeline = 0; + FloatBuffer mTexCoords; + FloatBuffer mVertCoords; + boolean usingVBOs; + int mVBO_For_ResuableTileVertices; + int mVBO_For_ResuableTileTexCoords; + + Pipelined_QuadRenderer() { + GL2 gl = GLContext.getCurrentGL().getGL2(); + mVertCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsVerts); + mTexCoords = Buffers.newDirectFloatBuffer(kTotalBufferSizeCoordsTex); + + usingVBOs = is15Available(gl); + + if (usingVBOs) { + try { + int[] vbos = new int[2]; + gl.glGenBuffers(2, IntBuffer.wrap(vbos)); + + mVBO_For_ResuableTileVertices = vbos[0]; + mVBO_For_ResuableTileTexCoords = vbos[1]; + + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, + mVBO_For_ResuableTileVertices); + gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesVerts, + null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline + + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, + mVBO_For_ResuableTileTexCoords); + gl.glBufferData(GL2.GL_ARRAY_BUFFER, kTotalBufferSizeBytesTex, + null, GL2.GL_STREAM_DRAW); // stream draw because this is a single quad use pipeline + } catch (Exception e) { + isExtensionAvailable_GL_VERSION_1_5 = false; + usingVBOs = false; + } + } + } + + public void glTexCoord2f(float v, float v1) { + mTexCoords.put(v); + mTexCoords.put(v1); + } + + public void glVertex3f(float inX, float inY, float inZ) { + mVertCoords.put(inX); + mVertCoords.put(inY); + mVertCoords.put(inZ); + + mOutstandingGlyphsVerticesPipeline++; + + if (mOutstandingGlyphsVerticesPipeline >= kTotalBufferSizeVerts) { + this.draw(); + } + } + + private void draw() { + if (useVertexArrays) { + drawVertexArrays(); + } else { + drawIMMEDIATE(); + } + } + + private void drawVertexArrays() { + if (mOutstandingGlyphsVerticesPipeline > 0) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + + TextureRenderer renderer = getBackingStore(); + Texture texture = renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious? + + mVertCoords.rewind(); + mTexCoords.rewind(); + + gl.glEnableClientState(GL2.GL_VERTEX_ARRAY); + + if (usingVBOs) { + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, + mVBO_For_ResuableTileVertices); + gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0, + mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_VertexData, + mVertCoords); // upload only the new stuff + gl.glVertexPointer(3, GL2.GL_FLOAT, 0, 0); + } else { + gl.glVertexPointer(3, GL2.GL_FLOAT, 0, mVertCoords); + } + + gl.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY); + + if (usingVBOs) { + gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, + mVBO_For_ResuableTileTexCoords); + gl.glBufferSubData(GL2.GL_ARRAY_BUFFER, 0, + mOutstandingGlyphsVerticesPipeline * kSizeInBytes_OneVertices_TexData, + mTexCoords); // upload only the new stuff + gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, 0); + } else { + gl.glTexCoordPointer(2, GL2.GL_FLOAT, 0, mTexCoords); + } + + gl.glDrawArrays(GL2.GL_QUADS, 0, + mOutstandingGlyphsVerticesPipeline); + + mVertCoords.rewind(); + mTexCoords.rewind(); + mOutstandingGlyphsVerticesPipeline = 0; + } + } + + private void drawIMMEDIATE() { + if (mOutstandingGlyphsVerticesPipeline > 0) { + TextureRenderer renderer = getBackingStore(); + Texture texture = renderer.getTexture(); // triggers texture uploads. Maybe this should be more obvious? + + GL2 gl = GLContext.getCurrentGL().getGL2(); + gl.glBegin(GL2.GL_QUADS); + + try { + int numberOfQuads = mOutstandingGlyphsVerticesPipeline / 4; + mVertCoords.rewind(); + mTexCoords.rewind(); + + for (int i = 0; i < numberOfQuads; i++) { + gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get()); + gl.glVertex3f(mVertCoords.get(), mVertCoords.get(), + mVertCoords.get()); + + gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get()); + gl.glVertex3f(mVertCoords.get(), mVertCoords.get(), + mVertCoords.get()); + + gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get()); + gl.glVertex3f(mVertCoords.get(), mVertCoords.get(), + mVertCoords.get()); + + gl.glTexCoord2f(mTexCoords.get(), mTexCoords.get()); + gl.glVertex3f(mVertCoords.get(), mVertCoords.get(), + mVertCoords.get()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + gl.glEnd(); + mVertCoords.rewind(); + mTexCoords.rewind(); + mOutstandingGlyphsVerticesPipeline = 0; + } + } + } + } + + class DebugListener implements GLEventListener { + private GLU glu; + private Frame frame; + + DebugListener(GL gl, Frame frame) { + this.glu = GLU.createGLU(gl); + this.frame = frame; + } + + public void display(GLAutoDrawable drawable) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + gl.glClear(GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_COLOR_BUFFER_BIT); + + if (packer == null) { + return; + } + + TextureRenderer rend = getBackingStore(); + final int w = rend.getWidth(); + final int h = rend.getHeight(); + rend.beginOrthoRendering(w, h); + rend.drawOrthoRect(0, 0); + rend.endOrthoRendering(); + + if ((frame.getWidth() != w) || (frame.getHeight() != h)) { + EventQueue.invokeLater(new Runnable() { + public void run() { + frame.setSize(w, h); + } + }); + } + } + + public void dispose(GLAutoDrawable drawable) { + glu.destroy(); + glu=null; + frame=null; + } + + // Unused methods + public void init(GLAutoDrawable drawable) { + } + + public void reshape(GLAutoDrawable drawable, int x, int y, int width, + int height) { + } + + public void displayChanged(GLAutoDrawable drawable, + boolean modeChanged, boolean deviceChanged) { + } + } + + /** + * Sets whether vertex arrays are being used internally for + * rendering, or whether text is rendered using the OpenGL + * immediate mode commands. This is provided as a concession for + * certain graphics cards which have poor vertex array + * performance. Defaults to true. + */ + public void setUseVertexArrays(boolean useVertexArrays) { + this.useVertexArrays = useVertexArrays; + } + + /** + * Indicates whether vertex arrays are being used internally for + * rendering, or whether text is rendered using the OpenGL + * immediate mode commands. Defaults to true. + */ + public boolean getUseVertexArrays() { + return useVertexArrays; + } + + /** + * Sets whether smoothing (i.e., GL_LINEAR filtering) is enabled + * in the backing TextureRenderer of this TextRenderer. A few + * graphics cards do not behave well when this is enabled, + * resulting in fuzzy text. Defaults to true. + */ + public void setSmoothing(boolean smoothing) { + this.smoothing = smoothing; + getBackingStore().setSmoothing(smoothing); + } + + /** + * Indicates whether smoothing is enabled in the backing + * TextureRenderer of this TextRenderer. A few graphics cards do + * not behave well when this is enabled, resulting in fuzzy text. + * Defaults to true. + */ + public boolean getSmoothing() { + return smoothing; + } + + private boolean is15Available(GL gl) { + if (!checkFor_isExtensionAvailable_GL_VERSION_1_5) { + isExtensionAvailable_GL_VERSION_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5"); + checkFor_isExtensionAvailable_GL_VERSION_1_5 = true; + } + return isExtensionAvailable_GL_VERSION_1_5; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java new file mode 100755 index 000000000..bc5aa517e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/awt/TextureRenderer.java @@ -0,0 +1,699 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.awt; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.image.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.spi.*; +import com.jogamp.opengl.util.texture.awt.*; + +/** Provides the ability to render into an OpenGL {@link + com.jogamp.opengl.util.texture.Texture Texture} using the Java 2D + APIs. This renderer class uses an internal Java 2D image (of + unspecified type) for its backing store and flushes portions of + that image to an OpenGL texture on demand. The resulting OpenGL + texture can then be mapped on to a polygon for display. */ + +public class TextureRenderer { + // For now, we supply only a BufferedImage back-end for this + // renderer. In theory we could use the Java 2D/JOGL bridge to fully + // accelerate the rendering paths, but there are restrictions on + // what work can be done where; for example, Graphics2D-related work + // must not be done on the Queue Flusher Thread, but JOGL's + // OpenGL-related work must be. This implies that the user's code + // would need to be split up into multiple callbacks run from the + // appropriate threads, which would be somewhat unfortunate. + + // Whether we have an alpha channel in the (RGB/A) backing store + private boolean alpha; + + // Whether we're using only a GL_INTENSITY backing store + private boolean intensity; + + // Whether we're attempting to use automatic mipmap generation support + private boolean mipmap; + + // Whether smoothing is enabled for the OpenGL texture (switching + // between GL_LINEAR and GL_NEAREST filtering) + private boolean smoothing = true; + private boolean smoothingChanged; + + // The backing store itself + private BufferedImage image; + + private Texture texture; + private AWTTextureData textureData; + private boolean mustReallocateTexture; + private Rectangle dirtyRegion; + + private GLUgl2 glu = new GLUgl2(); + + // Current color + private float r = 1.0f; + private float g = 1.0f; + private float b = 1.0f; + private float a = 1.0f; + + /** Creates a new renderer with backing store of the specified width + and height. If <CODE>alpha</CODE> is true, allocates an alpha + channel in the backing store image. No mipmap support is + requested. + + @param width the width of the texture to render into + @param height the height of the texture to render into + @param alpha whether to allocate an alpha channel for the texture + */ + public TextureRenderer(int width, int height, boolean alpha) { + this(width, height, alpha, false); + } + + /** Creates a new renderer with backing store of the specified width + and height. If <CODE>alpha</CODE> is true, allocates an alpha channel in the + backing store image. If <CODE>mipmap</CODE> is true, attempts to use OpenGL's + automatic mipmap generation for better smoothing when rendering + the TextureRenderer's contents at a distance. + + @param width the width of the texture to render into + @param height the height of the texture to render into + @param alpha whether to allocate an alpha channel for the texture + @param mipmap whether to attempt use of automatic mipmap generation + */ + public TextureRenderer(int width, int height, boolean alpha, boolean mipmap) { + this(width, height, alpha, false, mipmap); + } + + // Internal constructor to avoid confusion since alpha only makes + // sense when intensity is not set + private TextureRenderer(int width, int height, boolean alpha, boolean intensity, boolean mipmap) { + this.alpha = alpha; + this.intensity = intensity; + this.mipmap = mipmap; + init(width, height); + } + + /** Creates a new renderer with a special kind of backing store + which acts only as an alpha channel. No mipmap support is + requested. Internally, this associates a GL_INTENSITY OpenGL + texture with the backing store. */ + public static TextureRenderer createAlphaOnlyRenderer(int width, int height) { + return createAlphaOnlyRenderer(width, height, false); + } + + /** Creates a new renderer with a special kind of backing store + which acts only as an alpha channel. If <CODE>mipmap</CODE> is + true, attempts to use OpenGL's automatic mipmap generation for + better smoothing when rendering the TextureRenderer's contents + at a distance. Internally, this associates a GL_INTENSITY OpenGL + texture with the backing store. */ + public static TextureRenderer createAlphaOnlyRenderer(int width, int height, boolean mipmap) { + return new TextureRenderer(width, height, false, true, mipmap); + } + + /** Returns the width of the backing store of this renderer. + + @return the width of the backing store of this renderer + */ + public int getWidth() { + return image.getWidth(); + } + + /** Returns the height of the backing store of this renderer. + + @return the height of the backing store of this renderer + */ + public int getHeight() { + return image.getHeight(); + } + + /** Returns the size of the backing store of this renderer in a + newly-allocated {@link java.awt.Dimension Dimension} object. + + @return the size of the backing store of this renderer + */ + public Dimension getSize() { + return getSize(null); + } + + /** Returns the size of the backing store of this renderer. Uses the + {@link java.awt.Dimension Dimension} object if one is supplied, + or allocates a new one if null is passed. + + @param d a {@link java.awt.Dimension Dimension} object in which + to store the results, or null to allocate a new one + + @return the size of the backing store of this renderer + */ + public Dimension getSize(Dimension d) { + if (d == null) + d = new Dimension(); + d.setSize(image.getWidth(), image.getHeight()); + return d; + } + + /** Sets the size of the backing store of this renderer. This may + cause the OpenGL texture object associated with this renderer to + be invalidated; it is not recommended to cache this texture + object outside this class but to instead call {@link #getTexture + getTexture} when it is needed. + + @param width the new width of the backing store of this renderer + @param height the new height of the backing store of this renderer + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setSize(int width, int height) throws GLException { + init(width, height); + } + + /** Sets the size of the backing store of this renderer. This may + cause the OpenGL texture object associated with this renderer to + be invalidated. + + @param d the new size of the backing store of this renderer + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setSize(Dimension d) throws GLException { + setSize(d.width, d.height); + } + + /** Sets whether smoothing is enabled for the OpenGL texture; if so, + uses GL_LINEAR interpolation for the minification and + magnification filters. Defaults to true. Changes to this setting + will not take effect until the next call to {@link + #beginOrthoRendering beginOrthoRendering}. + + @param smoothing whether smoothing is enabled for the OpenGL texture + */ + public void setSmoothing(boolean smoothing) { + this.smoothing = smoothing; + smoothingChanged = true; + } + + /** Returns whether smoothing is enabled for the OpenGL texture; see + {@link #setSmoothing setSmoothing}. Defaults to true. + + @return whether smoothing is enabled for the OpenGL texture + */ + public boolean getSmoothing() { + return smoothing; + } + + /** Creates a {@link java.awt.Graphics2D Graphics2D} instance for + rendering to the backing store of this renderer. The returned + object should be disposed of using the normal {@link + java.awt.Graphics#dispose() Graphics.dispose()} method once it + is no longer being used. + + @return a new {@link java.awt.Graphics2D Graphics2D} object for + rendering into the backing store of this renderer + */ + public Graphics2D createGraphics() { + return image.createGraphics(); + } + + /** Returns the underlying Java 2D {@link java.awt.Image Image} + being rendered into. */ + public Image getImage() { + return image; + } + + /** Marks the given region of the TextureRenderer as dirty. This + region, and any previously set dirty regions, will be + automatically synchronized with the underlying Texture during + the next {@link #getTexture getTexture} operation, at which + point the dirty region will be cleared. It is not necessary for + an OpenGL context to be current when this method is called. + + @param x the x coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param y the y coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param width the width of the region to update + @param height the height of the region to update + */ + public void markDirty(int x, int y, int width, int height) { + Rectangle curRegion = new Rectangle(x, y, width, height); + if (dirtyRegion == null) { + dirtyRegion = curRegion; + } else { + dirtyRegion.add(curRegion); + } + } + + /** Returns the underlying OpenGL Texture object associated with + this renderer, synchronizing any dirty regions of the + TextureRenderer with the underlying OpenGL texture. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public Texture getTexture() throws GLException { + if (dirtyRegion != null) { + sync(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height); + dirtyRegion = null; + } + + ensureTexture(); + return texture; + } + + /** Disposes all resources associated with this renderer. It is not + valid to use this renderer after calling this method. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void dispose() throws GLException { + if (texture != null) { + texture.dispose(); + texture = null; + } + if (image != null) { + image.flush(); + image = null; + } + } + + /** Convenience method which assists in rendering portions of the + OpenGL texture to the screen, if the application intends to draw + them as a flat overlay on to the screen. Pushes OpenGL state + bits (GL_ENABLE_BIT, GL_DEPTH_BUFFER_BIT and GL_TRANSFORM_BIT); + disables the depth test, back-face culling, and lighting; + enables the texture in this renderer; and sets up the viewing + matrices for orthographic rendering where the coordinates go + from (0, 0) at the lower left to (width, height) at the upper + right. Equivalent to beginOrthoRendering(width, height, true). + {@link #endOrthoRendering} must be used in conjunction with this + method to restore all OpenGL states. + + @param width the width of the current on-screen OpenGL drawable + @param height the height of the current on-screen OpenGL drawable + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void beginOrthoRendering(int width, int height) throws GLException { + beginOrthoRendering(width, height, true); + } + + /** Convenience method which assists in rendering portions of the + OpenGL texture to the screen, if the application intends to draw + them as a flat overlay on to the screen. Pushes OpenGL state + bits (GL_ENABLE_BIT, GL_DEPTH_BUFFER_BIT and GL_TRANSFORM_BIT); + disables the depth test (if the "disableDepthTest" argument is + true), back-face culling, and lighting; enables the texture in + this renderer; and sets up the viewing matrices for orthographic + rendering where the coordinates go from (0, 0) at the lower left + to (width, height) at the upper right. {@link + #endOrthoRendering} must be used in conjunction with this method + to restore all OpenGL states. + + @param width the width of the current on-screen OpenGL drawable + @param height the height of the current on-screen OpenGL drawable + @param disableDepthTest whether the depth test should be disabled + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void beginOrthoRendering(int width, int height, boolean disableDepthTest) throws GLException { + beginRendering(true, width, height, disableDepthTest); + } + + /** Convenience method which assists in rendering portions of the + OpenGL texture to the screen as 2D quads in 3D space. Pushes + OpenGL state (GL_ENABLE_BIT); disables lighting; and enables the + texture in this renderer. Unlike {@link #beginOrthoRendering + beginOrthoRendering}, does not modify the depth test, back-face + culling, lighting, or the modelview or projection matrices. The + user is responsible for setting up the view matrices for correct + results of {@link #draw3DRect draw3DRect}. {@link + #end3DRendering} must be used in conjunction with this method to + restore all OpenGL states. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void begin3DRendering() throws GLException { + beginRendering(false, 0, 0, false); + } + + /** Changes the color of the polygons, and therefore the drawn + images, this TextureRenderer produces. Use of this method is + optional. The TextureRenderer uses the GL_MODULATE texture + environment mode, which causes the portions of the rendered + texture to be multiplied by the color of the rendered + polygons. The polygon color can be varied to achieve effects + like tinting of the overall output or fading in and out by + changing the alpha of the color. <P> + + Each component ranges from 0.0f - 1.0f. The alpha component, if + used, does not need to be premultiplied into the color channels + as described in the documentation for {@link + com.jogamp.opengl.util.texture.Texture Texture}, although + premultiplied colors are used internally. The default color is + opaque white. + + @param r the red component of the new color + @param g the green component of the new color + @param b the blue component of the new color + @param a the alpha component of the new color, 0.0f = completely + transparent, 1.0f = completely opaque + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setColor(float r, float g, float b, float a) throws GLException { + GL2 gl = GLContext.getCurrentGL().getGL2(); + this.r = r * a; + this.g = g * a; + this.b = b * a; + this.a = a; + + gl.glColor4f(this.r, this.g, this.b, this.a); + } + + private float[] compArray; + /** Changes the current color of this TextureRenderer to the + supplied one. The default color is opaque white. See {@link + #setColor(float,float,float,float) setColor} for more details. + + @param color the new color to use for rendering + @throws GLException If an OpenGL context is not current when this method is called + */ + public void setColor(Color color) throws GLException { + // Get color's RGBA components as floats in the range [0,1]. + if (compArray == null) { + compArray = new float[4]; + } + color.getRGBComponents(compArray); + setColor(compArray[0], compArray[1], compArray[2], compArray[3]); + } + + /** Draws an orthographically projected rectangle containing all of + the underlying texture to the specified location on the + screen. All (x, y) coordinates are specified relative to the + lower left corner of either the texture image or the current + OpenGL drawable. This method is equivalent to + <code>drawOrthoRect(screenx, screeny, 0, 0, getWidth(), + getHeight());</code>. + + @param screenx the on-screen x coordinate at which to draw the rectangle + @param screeny the on-screen y coordinate (relative to lower left) at + which to draw the rectangle + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void drawOrthoRect(int screenx, int screeny) throws GLException { + drawOrthoRect(screenx, screeny, 0, 0, getWidth(), getHeight()); + } + + /** Draws an orthographically projected rectangle of the underlying + texture to the specified location on the screen. All (x, y) + coordinates are specified relative to the lower left corner of + either the texture image or the current OpenGL drawable. + + @param screenx the on-screen x coordinate at which to draw the rectangle + @param screeny the on-screen y coordinate (relative to lower left) at + which to draw the rectangle + @param texturex the x coordinate of the pixel in the texture of + the lower left portion of the rectangle to draw + @param texturey the y coordinate of the pixel in the texture + (relative to lower left) of the lower left portion of the + rectangle to draw + @param width the width of the rectangle to draw + @param height the height of the rectangle to draw + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void drawOrthoRect(int screenx, int screeny, + int texturex, int texturey, + int width, int height) throws GLException { + draw3DRect(screenx, screeny, 0, texturex, texturey, width, height, 1); + } + + /** Draws a rectangle of the underlying texture to the specified 3D + location. In the current coordinate system, the lower left + corner of the rectangle is placed at (x, y, z), and the upper + right corner is placed at (x + width * scaleFactor, y + height * + scaleFactor, z). The lower left corner of the sub-rectangle of + the texture is (texturex, texturey) and the upper right corner + is (texturex + width, texturey + height). For back-face culling + purposes, the rectangle is drawn with counterclockwise + orientation of the vertices when viewed from the front. + + @param x the x coordinate at which to draw the rectangle + @param y the y coordinate at which to draw the rectangle + @param z the z coordinate at which to draw the rectangle + @param texturex the x coordinate of the pixel in the texture of + the lower left portion of the rectangle to draw + @param texturey the y coordinate of the pixel in the texture + (relative to lower left) of the lower left portion of the + rectangle to draw + @param width the width in texels of the rectangle to draw + @param height the height in texels of the rectangle to draw + @param scaleFactor the scale factor to apply (multiplicatively) + to the size of the drawn rectangle + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void draw3DRect(float x, float y, float z, + int texturex, int texturey, + int width, int height, + float scaleFactor) throws GLException { + GL2 gl = GLContext.getCurrentGL().getGL2(); + Texture texture = getTexture(); + TextureCoords coords = texture.getSubImageTexCoords(texturex, texturey, + texturex + width, + texturey + height); + gl.glBegin(GL2.GL_QUADS); + gl.glTexCoord2f(coords.left(), coords.bottom()); + gl.glVertex3f(x, y, z); + gl.glTexCoord2f(coords.right(), coords.bottom()); + gl.glVertex3f(x + width * scaleFactor, y, z); + gl.glTexCoord2f(coords.right(), coords.top()); + gl.glVertex3f(x + width * scaleFactor, y + height * scaleFactor, z); + gl.glTexCoord2f(coords.left(), coords.top()); + gl.glVertex3f(x, y + height * scaleFactor, z); + gl.glEnd(); + } + + /** Convenience method which assists in rendering portions of the + OpenGL texture to the screen, if the application intends to draw + them as a flat overlay on to the screen. Must be used if {@link + #beginOrthoRendering} is used to set up the rendering stage for + this overlay. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void endOrthoRendering() throws GLException { + endRendering(true); + } + + /** Convenience method which assists in rendering portions of the + OpenGL texture to the screen as 2D quads in 3D space. Must be + used if {@link #begin3DRendering} is used to set up the + rendering stage for this overlay. + + @throws GLException If an OpenGL context is not current when this method is called + */ + public void end3DRendering() throws GLException { + endRendering(false); + } + + /** Indicates whether automatic mipmap generation is in use for this + TextureRenderer. The result of this method may change from true + to false if it is discovered during allocation of the + TextureRenderer's backing store that automatic mipmap generation + is not supported at the OpenGL level. */ + public boolean isUsingAutoMipmapGeneration() { + return mipmap; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void beginRendering(boolean ortho, int width, int height, boolean disableDepthTestForOrtho) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + int attribBits = + GL2.GL_ENABLE_BIT | GL2.GL_TEXTURE_BIT | GL2.GL_COLOR_BUFFER_BIT | + (ortho ? (GL2.GL_DEPTH_BUFFER_BIT | GL2.GL_TRANSFORM_BIT) : 0); + gl.glPushAttrib(attribBits); + gl.glDisable(GL2.GL_LIGHTING); + if (ortho) { + if (disableDepthTestForOrtho) { + gl.glDisable(GL2.GL_DEPTH_TEST); + } + gl.glDisable(GL2.GL_CULL_FACE); + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glPushMatrix(); + gl.glLoadIdentity(); + glu.gluOrtho2D(0, width, 0, height); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2.GL_TEXTURE); + gl.glPushMatrix(); + gl.glLoadIdentity(); + } + gl.glEnable(GL2.GL_BLEND); + gl.glBlendFunc(GL2.GL_ONE, GL2.GL_ONE_MINUS_SRC_ALPHA); + Texture texture = getTexture(); + texture.enable(); + texture.bind(); + gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE); + // Change polygon color to last saved + gl.glColor4f(r, g, b, a); + if (smoothingChanged) { + smoothingChanged = false; + if (smoothing) { + texture.setTexParameteri(GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR); + if (mipmap) { + texture.setTexParameteri(GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR_MIPMAP_LINEAR); + } else { + texture.setTexParameteri(GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR); + } + } else { + texture.setTexParameteri(GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST); + texture.setTexParameteri(GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST); + } + } + } + + private void endRendering(boolean ortho) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + Texture texture = getTexture(); + texture.disable(); + if (ortho) { + gl.glMatrixMode(GL2.GL_PROJECTION); + gl.glPopMatrix(); + gl.glMatrixMode(GL2.GL_MODELVIEW); + gl.glPopMatrix(); + gl.glMatrixMode(GL2.GL_TEXTURE); + gl.glPopMatrix(); + } + gl.glPopAttrib(); + } + + private void init(int width, int height) { + GL2 gl = GLContext.getCurrentGL().getGL2(); + // Discard previous BufferedImage if any + if (image != null) { + image.flush(); + image = null; + } + + // Infer the internal format if not an intensity texture + int internalFormat = (intensity ? GL2.GL_INTENSITY : 0); + int imageType = + (intensity ? BufferedImage.TYPE_BYTE_GRAY : + (alpha ? BufferedImage.TYPE_INT_ARGB_PRE : BufferedImage.TYPE_INT_RGB)); + image = new BufferedImage(width, height, imageType); + // Always realllocate the TextureData associated with this + // BufferedImage; it's just a reference to the contents but we + // need it in order to update sub-regions of the underlying + // texture + textureData = new AWTTextureData(gl.getGLProfile(), internalFormat, 0, mipmap, image); + // For now, always reallocate the underlying OpenGL texture when + // the backing store size changes + mustReallocateTexture = true; + } + + /** Synchronizes the specified region of the backing store down to + the underlying OpenGL texture. If {@link #markDirty markDirty} + is used instead to indicate the regions that are out of sync, + this method does not need to be called. + + @param x the x coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param y the y coordinate (in Java 2D coordinates -- relative to + upper left) of the region to update + @param width the width of the region to update + @param height the height of the region to update + + @throws GLException If an OpenGL context is not current when this method is called + */ + private void sync(int x, int y, int width, int height) throws GLException { + // Force allocation if necessary + boolean canSkipUpdate = ensureTexture(); + + if (!canSkipUpdate) { + // Update specified region. + // NOTE that because BufferedImage-based TextureDatas now don't + // do anything to their contents, the coordinate systems for + // OpenGL and Java 2D actually line up correctly for + // updateSubImage calls, so we don't need to do any argument + // conversion here (i.e., flipping the Y coordinate). + texture.updateSubImage(textureData, 0, x, y, x, y, width, height); + } + } + + // Returns true if the texture was newly allocated, false if not + private boolean ensureTexture() { + if (mustReallocateTexture) { + if (texture != null) { + texture.dispose(); + texture = null; + } + mustReallocateTexture = false; + } + + if (texture == null) { + texture = TextureIO.newTexture(textureData); + if (mipmap && !texture.isUsingAutoMipmapGeneration()) { + // Only try this once + texture.dispose(); + mipmap = false; + textureData.setMipmap(false); + texture = TextureIO.newTexture(textureData); + } + + if (!smoothing) { + // The TextureIO classes default to GL_LINEAR filtering + texture.setTexParameteri(GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST); + texture.setTexParameteri(GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST); + } + return true; + } + + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java new file mode 100644 index 000000000..34685e1b2 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapCharRec.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class BitmapCharRec { + public int width; + public int height; + public float xorig; + public float yorig; + public float advance; + public byte[] bitmap; + + public BitmapCharRec(int width, + int height, + float xorig, + float yorig, + float advance, + byte[] bitmap) { + this.width = width; + this.height = height; + this.xorig = xorig; + this.yorig = yorig; + this.advance = advance; + this.bitmap = bitmap; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java new file mode 100644 index 000000000..18f7d3b28 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/BitmapFontRec.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class BitmapFontRec { + public String name; + public int num_chars; + public int first; + public BitmapCharRec[] ch; + + public BitmapFontRec(String name, + int num_chars, + int first, + BitmapCharRec[] ch) { + this.name = name; + this.num_chars = num_chars; + this.first = first; + this.ch = ch; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java new file mode 100644 index 000000000..9ad95ec03 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/CoordRec.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class CoordRec { + public float x; + public float y; + + public CoordRec(float x, float y) { + this.x = x; + this.y = y; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java new file mode 100644 index 000000000..8befc13ba --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUT.java @@ -0,0 +1,1342 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; + +/** Subset of the routines provided by the GLUT interface. Note the + signatures of many of the methods are necessarily different than + the corresponding C version. A GLUT object must only be used from + one particular thread at a time. <P> + + Copyright (c) Mark J. Kilgard, 1994, 1997. <P> + + (c) Copyright 1993, Silicon Graphics, Inc. <P> + + ALL RIGHTS RESERVED <P> + + Permission to use, copy, modify, and distribute this software + for any purpose and without fee is hereby granted, provided + that the above copyright notice appear in all copies and that + both the copyright notice and this permission notice appear in + supporting documentation, and that the name of Silicon + Graphics, Inc. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. <P> + + THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU + "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR + OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO + EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE + ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR + CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER, + INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE, + SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR + NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY + OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR + PERFORMANCE OF THIS SOFTWARE. <P> + + US Government Users Restricted Rights <P> + + Use, duplication, or disclosure by the Government is subject to + restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + (c)(1)(ii) of the Rights in Technical Data and Computer + Software clause at DFARS 252.227-7013 and/or in similar or + successor clauses in the FAR or the DOD or NASA FAR + Supplement. Unpublished-- rights reserved under the copyright + laws of the United States. Contractor/manufacturer is Silicon + Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA + 94039-7311. <P> + + OpenGL(TM) is a trademark of Silicon Graphics, Inc. <P> +*/ + +public class GLUT { + public static final int STROKE_ROMAN = 0; + public static final int STROKE_MONO_ROMAN = 1; + public static final int BITMAP_9_BY_15 = 2; + public static final int BITMAP_8_BY_13 = 3; + public static final int BITMAP_TIMES_ROMAN_10 = 4; + public static final int BITMAP_TIMES_ROMAN_24 = 5; + public static final int BITMAP_HELVETICA_10 = 6; + public static final int BITMAP_HELVETICA_12 = 7; + public static final int BITMAP_HELVETICA_18 = 8; + + private GLUgl2 glu = new GLUgl2(); + + //---------------------------------------------------------------------- + // Shapes + // + + public void glutWireSphere(double radius, int slices, int stacks) { + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluSphere(quadObj, radius, slices, stacks); + } + + public void glutSolidSphere(double radius, int slices, int stacks) { + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluSphere(quadObj, radius, slices, stacks); + } + + public void glutWireCone(double base, double height, + int slices, int stacks) { + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks); + } + + public void glutSolidCone(double base, double height, + int slices, int stacks) { + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluCylinder(quadObj, base, 0.0, height, slices, stacks); + } + + public void glutWireCylinder(double radius, double height, int slices, int stacks) { + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_LINE); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluCylinder(quadObj, radius, radius, height, slices, stacks); + } + + public void glutSolidCylinder(double radius, double height, int slices, int stacks) { + GL2 gl = GLUgl2.getCurrentGL2(); + + // Prepare table of points for drawing end caps + double [] x = new double[slices]; + double [] y = new double[slices]; + double angleDelta = Math.PI * 2 / slices; + double angle = 0; + for (int i = 0 ; i < slices ; i ++) { + angle = i * angleDelta; + x[i] = Math.cos(angle) * radius; + y[i] = Math.sin(angle) * radius; + } + + // Draw bottom cap + gl.glBegin(GL2.GL_TRIANGLE_FAN); + gl.glNormal3d(0,0,-1); + gl.glVertex3d(0,0,0); + for (int i = 0 ; i < slices ; i ++) { + gl.glVertex3d(x[i], y[i], 0); + } + gl.glVertex3d(x[0], y[0], 0); + gl.glEnd(); + + // Draw top cap + gl.glBegin(GL2.GL_TRIANGLE_FAN); + gl.glNormal3d(0,0,1); + gl.glVertex3d(0,0,height); + for (int i = 0 ; i < slices ; i ++) { + gl.glVertex3d(x[i], y[i], height); + } + gl.glVertex3d(x[0], y[0], height); + gl.glEnd(); + + // Draw walls + quadObjInit(glu); + glu.gluQuadricDrawStyle(quadObj, GLU.GLU_FILL); + glu.gluQuadricNormals(quadObj, GLU.GLU_SMOOTH); + /* If we ever changed/used the texture or orientation state + of quadObj, we'd need to change it to the defaults here + with gluQuadricTexture and/or gluQuadricOrientation. */ + glu.gluCylinder(quadObj, radius, radius, height, slices, stacks); + } + + public void glutWireCube(float size) { + drawBox(GLUgl2.getCurrentGL2(), size, GL2.GL_LINE_LOOP); + } + + public void glutSolidCube(float size) { + drawBox(GLUgl2.getCurrentGL2(), size, GL2.GL_QUADS); + } + + public void glutWireTorus(double innerRadius, double outerRadius, + int nsides, int rings) { + GL2 gl = GLUgl2.getCurrentGL2(); + gl.glPushAttrib(GL2.GL_POLYGON_BIT); + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_LINE); + doughnut(gl, innerRadius, outerRadius, nsides, rings); + gl.glPopAttrib(); + } + + public void glutSolidTorus(double innerRadius, double outerRadius, + int nsides, int rings) { + doughnut(GLUgl2.getCurrentGL2(), innerRadius, outerRadius, nsides, rings); + } + + public void glutWireDodecahedron() { + dodecahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP); + } + + public void glutSolidDodecahedron() { + dodecahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLE_FAN); + } + + public void glutWireOctahedron() { + octahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP); + } + + public void glutSolidOctahedron() { + octahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES); + } + + public void glutWireIcosahedron() { + icosahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP); + } + + public void glutSolidIcosahedron() { + icosahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES); + } + + public void glutWireTetrahedron() { + tetrahedron(GLUgl2.getCurrentGL2(), GL2.GL_LINE_LOOP); + } + + public void glutSolidTetrahedron() { + tetrahedron(GLUgl2.getCurrentGL2(), GL2.GL_TRIANGLES); + } + +/** + * Renders the teapot as a solid shape of the specified size. The teapot is + * created in a way that replicates the C GLUT implementation. + * + * @param scale + * the factor by which to scale the teapot + */ + public void glutSolidTeapot(double scale) { + glutSolidTeapot(scale, true); + } + + /** + * Renders the teapot as a solid shape of the specified size. The teapot can + * either be created in a way that is backward-compatible with the standard + * C glut library (i.e. broken), or in a more pleasing way (i.e. with + * surfaces whose front-faces point outwards and standing on the z=0 plane, + * instead of the y=-1 plane). Both surface normals and texture coordinates + * for the teapot are generated. The teapot is generated with OpenGL + * evaluators. + * + * @param scale + * the factor by which to scale the teapot + * @param cStyle + * whether to create the teapot in exactly the same way as in the C + * implementation of GLUT + */ + public void glutSolidTeapot(double scale, boolean cStyle) { + teapot(GLUgl2.getCurrentGL2(), 14, scale, GL2.GL_FILL, cStyle); + } + + /** + * Renders the teapot as a wireframe shape of the specified size. The teapot + * is created in a way that replicates the C GLUT implementation. + * + * @param scale + * the factor by which to scale the teapot + */ + public void glutWireTeapot(double scale) { + glutWireTeapot(scale, true); + } + + /** + * Renders the teapot as a wireframe shape of the specified size. The teapot + * can either be created in a way that is backward-compatible with the + * standard C glut library (i.e. broken), or in a more pleasing way (i.e. + * with surfaces whose front-faces point outwards and standing on the z=0 + * plane, instead of the y=-1 plane). Both surface normals and texture + * coordinates for the teapot are generated. The teapot is generated with + * OpenGL evaluators. + * + * @param scale + * the factor by which to scale the teapot + * @param cStyle + * whether to create the teapot in exactly the same way as in the C + * implementation of GLUT + */ + public void glutWireTeapot(double scale, boolean cStyle) { + teapot(GLUgl2.getCurrentGL2(), 10, scale, GL2.GL_LINE, cStyle); + } + + //---------------------------------------------------------------------- + // Fonts + // + + public void glutBitmapCharacter(int font, char character) { + GL2 gl = GLUgl2.getCurrentGL2(); + int[] swapbytes = new int[1]; + int[] lsbfirst = new int[1]; + int[] rowlength = new int[1]; + int[] skiprows = new int[1]; + int[] skippixels = new int[1]; + int[] alignment = new int[1]; + beginBitmap(gl, + swapbytes, + lsbfirst, + rowlength, + skiprows, + skippixels, + alignment); + bitmapCharacterImpl(gl, font, character); + endBitmap(gl, + swapbytes, + lsbfirst, + rowlength, + skiprows, + skippixels, + alignment); + } + + public void glutBitmapString (int font, String string) { + GL2 gl = GLUgl2.getCurrentGL2(); + int[] swapbytes = new int[1]; + int[] lsbfirst = new int[1]; + int[] rowlength = new int[1]; + int[] skiprows = new int[1]; + int[] skippixels = new int[1]; + int[] alignment = new int[1]; + beginBitmap(gl, + swapbytes, + lsbfirst, + rowlength, + skiprows, + skippixels, + alignment); + int len = string.length(); + for (int i = 0; i < len; i++) { + bitmapCharacterImpl(gl, font, string.charAt(i)); + } + endBitmap(gl, + swapbytes, + lsbfirst, + rowlength, + skiprows, + skippixels, + alignment); + } + + public int glutBitmapWidth (int font, char character) { + BitmapFontRec fontinfo = getBitmapFont(font); + int c = character & 0xFFFF; + if (c < fontinfo.first || c >= fontinfo.first + fontinfo.num_chars) + return 0; + BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; + if (ch != null) + return (int) ch.advance; + else + return 0; + } + + public void glutStrokeCharacter(int font, char character) { + GL2 gl = GLUgl2.getCurrentGL2(); + StrokeFontRec fontinfo = getStrokeFont(font); + int c = character & 0xFFFF; + if (c < 0 || c >= fontinfo.num_chars) + return; + StrokeCharRec ch = fontinfo.ch[c]; + if (ch != null) { + for (int i = 0; i < ch.num_strokes; i++) { + StrokeRec stroke = ch.stroke[i]; + gl.glBegin(GL2.GL_LINE_STRIP); + for (int j = 0; j < stroke.num_coords; j++) { + CoordRec coord = stroke.coord[j]; + gl.glVertex2f(coord.x, coord.y); + } + gl.glEnd(); + } + gl.glTranslatef(ch.right, 0.0f, 0.0f); + } + } + + public void glutStrokeString(int font, String string) { + GL2 gl = GLUgl2.getCurrentGL2(); + StrokeFontRec fontinfo = getStrokeFont(font); + int len = string.length(); + for (int pos = 0; pos < len; pos++) { + int c = string.charAt(pos) & 0xFFFF; + if (c < 0 || c >= fontinfo.num_chars) + continue; + StrokeCharRec ch = fontinfo.ch[c]; + if (ch != null) { + for (int i = 0; i < ch.num_strokes; i++) { + StrokeRec stroke = ch.stroke[i]; + gl.glBegin(GL2.GL_LINE_STRIP); + for (int j = 0; j < stroke.num_coords; j++) { + CoordRec coord = stroke.coord[j]; + gl.glVertex2f(coord.x, coord.y); + } + gl.glEnd(); + } + gl.glTranslatef(ch.right, 0.0f, 0.0f); + } + } + } + + public int glutStrokeWidth (int font, char character) { + return (int) glutStrokeWidthf(font, character); + } + + public float glutStrokeWidthf (int font, char character) { + StrokeFontRec fontinfo = getStrokeFont(font); + int c = character & 0xFFFF; + if (c < 0 || c >= fontinfo.num_chars) + return 0; + StrokeCharRec ch = fontinfo.ch[c]; + if (ch != null) + return ch.right; + else + return 0; + } + + public int glutBitmapLength (int font, String string) { + BitmapFontRec fontinfo = getBitmapFont(font); + int length = 0; + int len = string.length(); + for (int pos = 0; pos < len; pos++) { + int c = string.charAt(pos) & 0xFFFF; + if (c >= fontinfo.first && c < fontinfo.first + fontinfo.num_chars) { + BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; + if (ch != null) + length += ch.advance; + } + } + return length; + } + + public int glutStrokeLength (int font, String string) { + return (int) glutStrokeLengthf(font, string); + } + + public float glutStrokeLengthf (int font, String string) { + StrokeFontRec fontinfo = getStrokeFont(font); + float length = 0; + int len = string.length(); + for (int i = 0; i < len; i++) { + char c = string.charAt(i); + if (c >= 0 && c < fontinfo.num_chars) { + StrokeCharRec ch = fontinfo.ch[c]; + if (ch != null) + length += ch.right; + } + } + return length; + } + + /** + This function draws a wireframe dodecahedron whose + facets are rhombic and + whose vertices are at unit radius. + No facet lies normal to any coordinate axes. + The polyhedron is centered at the origin. + */ + public void glutWireRhombicDodecahedron() { + GL2 gl = GLUgl2.getCurrentGL2(); + for( int i = 0; i < 12; i++ ) { + gl.glBegin( GL2.GL_LINE_LOOP ); + gl.glNormal3dv( rdod_n[ i ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 1 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 2 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 3 ] ],0 ); + gl.glEnd( ); + } + } + + /** + This function draws a solid-shaded dodecahedron + whose facets are rhombic and + whose vertices are at unit radius. + No facet lies normal to any coordinate axes. + The polyhedron is centered at the origin. + */ + public void glutSolidRhombicDodecahedron() { + GL2 gl = GLUgl2.getCurrentGL2(); + gl.glBegin( GL2.GL_QUADS ); + for( int i = 0; i < 12; i++ ) { + gl.glNormal3dv( rdod_n[ i ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 0 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 1 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 2 ] ],0 ); + gl.glVertex3dv( rdod_r[ rdod_v[ i ][ 3 ] ],0 ); + } + gl.glEnd( ); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + //---------------------------------------------------------------------- + // Shape implementation + // + + private GLUquadric quadObj; + private void quadObjInit(GLUgl2 glu) { + if (quadObj == null) { + quadObj = glu.gluNewQuadric(); + } + if (quadObj == null) { + throw new GLException("Out of memory"); + } + } + + private static void doughnut(GL2 gl, double r, double R, int nsides, int rings) { + int i, j; + float theta, phi, theta1; + float cosTheta, sinTheta; + float cosTheta1, sinTheta1; + float ringDelta, sideDelta; + + ringDelta = (float) (2.0 * Math.PI / rings); + sideDelta = (float) (2.0 * Math.PI / nsides); + + theta = 0.0f; + cosTheta = 1.0f; + sinTheta = 0.0f; + for (i = rings - 1; i >= 0; i--) { + theta1 = theta + ringDelta; + cosTheta1 = (float) Math.cos(theta1); + sinTheta1 = (float) Math.sin(theta1); + gl.glBegin(GL2.GL_QUAD_STRIP); + phi = 0.0f; + for (j = nsides; j >= 0; j--) { + float cosPhi, sinPhi, dist; + + phi += sideDelta; + cosPhi = (float) Math.cos(phi); + sinPhi = (float) Math.sin(phi); + dist = (float) (R + r * cosPhi); + + gl.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); + gl.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, (float) r * sinPhi); + gl.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); + gl.glVertex3f(cosTheta * dist, -sinTheta * dist, (float) r * sinPhi); + } + gl.glEnd(); + theta = theta1; + cosTheta = cosTheta1; + sinTheta = sinTheta1; + } + } + + private static float[][] boxVertices; + private static final float[][] boxNormals = { + {-1.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, -1.0f} + }; + private static final int[][] boxFaces = { + {0, 1, 2, 3}, + {3, 2, 6, 7}, + {7, 6, 5, 4}, + {4, 5, 1, 0}, + {5, 6, 2, 1}, + {7, 4, 0, 3} + }; + private void drawBox(GL2 gl, float size, int type) { + if (boxVertices == null) { + float[][] v = new float[8][]; + for (int i = 0; i < 8; i++) { + v[i] = new float[3]; + } + v[0][0] = v[1][0] = v[2][0] = v[3][0] = -0.5f; + v[4][0] = v[5][0] = v[6][0] = v[7][0] = 0.5f; + v[0][1] = v[1][1] = v[4][1] = v[5][1] = -0.5f; + v[2][1] = v[3][1] = v[6][1] = v[7][1] = 0.5f; + v[0][2] = v[3][2] = v[4][2] = v[7][2] = -0.5f; + v[1][2] = v[2][2] = v[5][2] = v[6][2] = 0.5f; + boxVertices = v; + } + float[][] v = boxVertices; + float[][] n = boxNormals; + int[][] faces = boxFaces; + for (int i = 5; i >= 0; i--) { + gl.glBegin(type); + gl.glNormal3fv(n[i], 0); + float[] vt = v[faces[i][0]]; + gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); + vt = v[faces[i][1]]; + gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); + vt = v[faces[i][2]]; + gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); + vt = v[faces[i][3]]; + gl.glVertex3f(vt[0] * size, vt[1] * size, vt[2] * size); + gl.glEnd(); + } + } + + private float[][] dodec; + + private void initDodecahedron() { + dodec = new float[20][]; + for (int i = 0; i < dodec.length; i++) { + dodec[i] = new float[3]; + } + + float alpha, beta; + + alpha = (float) Math.sqrt(2.0f / (3.0f + Math.sqrt(5.0))); + beta = 1.0f + (float) Math.sqrt(6.0 / (3.0 + Math.sqrt(5.0)) - + 2.0 + 2.0 * Math.sqrt(2.0 / (3.0 + Math.sqrt(5.0)))); + dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta; + dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta; + dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1; + dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1; + dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1; + dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1; + dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1; + dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1; + dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1; + dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1; + dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0; + dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0; + dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0; + dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0; + dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta; + dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta; + dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha; + dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha; + dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha; + dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha; + } + + private static void diff3(float[] a, float[] b, float[] c) { + c[0] = a[0] - b[0]; + c[1] = a[1] - b[1]; + c[2] = a[2] - b[2]; + } + + private static void crossprod(float[] v1, float[] v2, float[] prod) { + float[] p = new float[3]; /* in case prod == v1 or v2 */ + + p[0] = v1[1] * v2[2] - v2[1] * v1[2]; + p[1] = v1[2] * v2[0] - v2[2] * v1[0]; + p[2] = v1[0] * v2[1] - v2[0] * v1[1]; + prod[0] = p[0]; + prod[1] = p[1]; + prod[2] = p[2]; + } + + private static void normalize(float[] v) { + float d; + + d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); + if (d == 0.0) { + v[0] = d = 1.0f; + } + d = 1 / d; + v[0] *= d; + v[1] *= d; + v[2] *= d; + } + + private void pentagon(GL2 gl, int a, int b, int c, int d, int e, int shadeType) { + float[] n0 = new float[3]; + float[] d1 = new float[3]; + float[] d2 = new float[3]; + + diff3(dodec[a], dodec[b], d1); + diff3(dodec[b], dodec[c], d2); + crossprod(d1, d2, n0); + normalize(n0); + + gl.glBegin(shadeType); + gl.glNormal3fv(n0, 0); + gl.glVertex3fv(dodec[a], 0); + gl.glVertex3fv(dodec[b], 0); + gl.glVertex3fv(dodec[c], 0); + gl.glVertex3fv(dodec[d], 0); + gl.glVertex3fv(dodec[e], 0); + gl.glEnd(); + } + + private void dodecahedron(GL2 gl, int type) { + if (dodec == null) { + initDodecahedron(); + } + pentagon(gl, 0, 1, 9, 16, 5, type); + pentagon(gl, 1, 0, 3, 18, 7, type); + pentagon(gl, 1, 7, 11, 10, 9, type); + pentagon(gl, 11, 7, 18, 19, 6, type); + pentagon(gl, 8, 17, 16, 9, 10, type); + pentagon(gl, 2, 14, 15, 6, 19, type); + pentagon(gl, 2, 13, 12, 4, 14, type); + pentagon(gl, 2, 19, 18, 3, 13, type); + pentagon(gl, 3, 0, 5, 12, 13, type); + pentagon(gl, 6, 15, 8, 10, 11, type); + pentagon(gl, 4, 17, 8, 15, 14, type); + pentagon(gl, 4, 12, 5, 16, 17, type); + } + + private static void recorditem(GL2 gl, float[] n1, float[] n2, float[] n3, int shadeType) { + float[] q0 = new float[3]; + float[] q1 = new float[3]; + + diff3(n1, n2, q0); + diff3(n2, n3, q1); + crossprod(q0, q1, q1); + normalize(q1); + + gl.glBegin(shadeType); + gl.glNormal3fv(q1, 0); + gl.glVertex3fv(n1, 0); + gl.glVertex3fv(n2, 0); + gl.glVertex3fv(n3, 0); + gl.glEnd(); + } + + private static void subdivide(GL2 gl, float[] v0, float[] v1, float[] v2, int shadeType) { + int depth; + float[] w0 = new float[3]; + float[] w1 = new float[3]; + float[] w2 = new float[3]; + float l; + int i, j, k, n; + + depth = 1; + for (i = 0; i < depth; i++) { + for (j = 0; i + j < depth; j++) { + k = depth - i - j; + for (n = 0; n < 3; n++) { + w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth; + w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n]) + / depth; + w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n]) + / depth; + } + l = (float) Math.sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]); + w0[0] /= l; + w0[1] /= l; + w0[2] /= l; + l = (float) Math.sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]); + w1[0] /= l; + w1[1] /= l; + w1[2] /= l; + l = (float) Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]); + w2[0] /= l; + w2[1] /= l; + w2[2] /= l; + recorditem(gl, w1, w0, w2, shadeType); + } + } + } + + private static void drawtriangle(GL2 gl, int i, float[][] data, int[][] ndx, int shadeType) { + float[] x0 = data[ndx[i][0]]; + float[] x1 = data[ndx[i][1]]; + float[] x2 = data[ndx[i][2]]; + subdivide(gl, x0, x1, x2, shadeType); + } + + /* octahedron data: The octahedron produced is centered at the + origin and has radius 1.0 */ + private static final float[][] odata = + { + {1.0f, 0.0f, 0.0f}, + {-1.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + {0.0f, -1.0f, 0.0f}, + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, -1.0f} + }; + + private static final int[][] ondex = + { + {0, 4, 2}, + {1, 2, 4}, + {0, 3, 4}, + {1, 4, 3}, + {0, 2, 5}, + {1, 5, 2}, + {0, 5, 3}, + {1, 3, 5} + }; + + private static void octahedron(GL2 gl, int shadeType) { + int i; + + for (i = 7; i >= 0; i--) { + drawtriangle(gl, i, odata, ondex, shadeType); + } + } + + /* icosahedron data: These numbers are rigged to make an + icosahedron of radius 1.0 */ + + private static final float X = .525731112119133606f; + private static final float Z = .850650808352039932f; + + private static final float[][] idata = + { + {-X, 0, Z}, + {X, 0, Z}, + {-X, 0, -Z}, + {X, 0, -Z}, + {0, Z, X}, + {0, Z, -X}, + {0, -Z, X}, + {0, -Z, -X}, + {Z, X, 0}, + {-Z, X, 0}, + {Z, -X, 0}, + {-Z, -X, 0} + }; + + private static final int[][] index = + { + {0, 4, 1}, + {0, 9, 4}, + {9, 5, 4}, + {4, 5, 8}, + {4, 8, 1}, + {8, 10, 1}, + {8, 3, 10}, + {5, 3, 8}, + {5, 2, 3}, + {2, 7, 3}, + {7, 10, 3}, + {7, 6, 10}, + {7, 11, 6}, + {11, 0, 6}, + {0, 1, 6}, + {6, 1, 10}, + {9, 0, 11}, + {9, 11, 2}, + {9, 2, 5}, + {7, 2, 11}, + }; + + private static void icosahedron(GL2 gl, int shadeType) { + int i; + + for (i = 19; i >= 0; i--) { + drawtriangle(gl, i, idata, index, shadeType); + } + } + + /* rhombic dodecahedron data: */ + + private static final double rdod_r[][] = + { + { 0.0, 0.0, 1.0 }, + { 0.707106781187, 0.000000000000, 0.5 }, + { 0.000000000000, 0.707106781187, 0.5 }, + { -0.707106781187, 0.000000000000, 0.5 }, + { 0.000000000000, -0.707106781187, 0.5 }, + { 0.707106781187, 0.707106781187, 0.0 }, + { -0.707106781187, 0.707106781187, 0.0 }, + { -0.707106781187, -0.707106781187, 0.0 }, + { 0.707106781187, -0.707106781187, 0.0 }, + { 0.707106781187, 0.000000000000, -0.5 }, + { 0.000000000000, 0.707106781187, -0.5 }, + { -0.707106781187, 0.000000000000, -0.5 }, + { 0.000000000000, -0.707106781187, -0.5 }, + { 0.0, 0.0, -1.0 } + }; + + private static final int rdod_v[][] = + { + { 0, 1, 5, 2 }, + { 0, 2, 6, 3 }, + { 0, 3, 7, 4 }, + { 0, 4, 8, 1 }, + { 5, 10, 6, 2 }, + { 6, 11, 7, 3 }, + { 7, 12, 8, 4 }, + { 8, 9, 5, 1 }, + { 5, 9, 13, 10 }, + { 6, 10, 13, 11 }, + { 7, 11, 13, 12 }, + { 8, 12, 13, 9 } + }; + + private static final double rdod_n[][] = + { + { 0.353553390594, 0.353553390594, 0.5 }, + { -0.353553390594, 0.353553390594, 0.5 }, + { -0.353553390594, -0.353553390594, 0.5 }, + { 0.353553390594, -0.353553390594, 0.5 }, + { 0.000000000000, 1.000000000000, 0.0 }, + { -1.000000000000, 0.000000000000, 0.0 }, + { 0.000000000000, -1.000000000000, 0.0 }, + { 1.000000000000, 0.000000000000, 0.0 }, + { 0.353553390594, 0.353553390594, -0.5 }, + { -0.353553390594, 0.353553390594, -0.5 }, + { -0.353553390594, -0.353553390594, -0.5 }, + { 0.353553390594, -0.353553390594, -0.5 } + }; + + /* tetrahedron data: */ + + private static final float T = 1.73205080756887729f; + + private static final float[][] tdata = + { + {T, T, T}, + {T, -T, -T}, + {-T, T, -T}, + {-T, -T, T} + }; + + private static final int[][] tndex = + { + {0, 1, 3}, + {2, 1, 0}, + {3, 2, 0}, + {1, 2, 3} + }; + + private static final void tetrahedron(GL2 gl, int shadeType) { + for (int i = 3; i >= 0; i--) + drawtriangle(gl, i, tdata, tndex, shadeType); + } + + // Teapot implementation (a modified port of glut_teapot.c) + // + // Rim, body, lid, and bottom data must be reflected in x and + // y; handle and spout data across the y axis only. + private static final int[][] teapotPatchData = { + /* rim */ + {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + /* body */ + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}, + {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, + /* lid */ + {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,}, + {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117}, + /* bottom */ + {118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37}, + /* handle */ + {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56}, + {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67}, + /* spout */ + {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83}, + {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95} + }; + private static final float[][] teapotCPData = { + {0.2f, 0f, 2.7f}, + {0.2f, -0.112f, 2.7f}, + {0.112f, -0.2f, 2.7f}, + {0f, -0.2f, 2.7f}, + {1.3375f, 0f, 2.53125f}, + {1.3375f, -0.749f, 2.53125f}, + {0.749f, -1.3375f, 2.53125f}, + {0f, -1.3375f, 2.53125f}, + {1.4375f, 0f, 2.53125f}, + {1.4375f, -0.805f, 2.53125f}, + {0.805f, -1.4375f, 2.53125f}, + {0f, -1.4375f, 2.53125f}, + {1.5f, 0f, 2.4f}, + {1.5f, -0.84f, 2.4f}, + {0.84f, -1.5f, 2.4f}, + {0f, -1.5f, 2.4f}, + {1.75f, 0f, 1.875f}, + {1.75f, -0.98f, 1.875f}, + {0.98f, -1.75f, 1.875f}, + {0f, -1.75f, 1.875f}, + {2f, 0f, 1.35f}, + {2f, -1.12f, 1.35f}, + {1.12f, -2f, 1.35f}, + {0f, -2f, 1.35f}, + {2f, 0f, 0.9f}, + {2f, -1.12f, 0.9f}, + {1.12f, -2f, 0.9f}, + {0f, -2f, 0.9f}, + {-2f, 0f, 0.9f}, + {2f, 0f, 0.45f}, + {2f, -1.12f, 0.45f}, + {1.12f, -2f, 0.45f}, + {0f, -2f, 0.45f}, + {1.5f, 0f, 0.225f}, + {1.5f, -0.84f, 0.225f}, + {0.84f, -1.5f, 0.225f}, + {0f, -1.5f, 0.225f}, + {1.5f, 0f, 0.15f}, + {1.5f, -0.84f, 0.15f}, + {0.84f, -1.5f, 0.15f}, + {0f, -1.5f, 0.15f}, + {-1.6f, 0f, 2.025f}, + {-1.6f, -0.3f, 2.025f}, + {-1.5f, -0.3f, 2.25f}, + {-1.5f, 0f, 2.25f}, + {-2.3f, 0f, 2.025f}, + {-2.3f, -0.3f, 2.025f}, + {-2.5f, -0.3f, 2.25f}, + {-2.5f, 0f, 2.25f}, + {-2.7f, 0f, 2.025f}, + {-2.7f, -0.3f, 2.025f}, + {-3f, -0.3f, 2.25f}, + {-3f, 0f, 2.25f}, + {-2.7f, 0f, 1.8f}, + {-2.7f, -0.3f, 1.8f}, + {-3f, -0.3f, 1.8f}, + {-3f, 0f, 1.8f}, + {-2.7f, 0f, 1.575f}, + {-2.7f, -0.3f, 1.575f}, + {-3f, -0.3f, 1.35f}, + {-3f, 0f, 1.35f}, + {-2.5f, 0f, 1.125f}, + {-2.5f, -0.3f, 1.125f}, + {-2.65f, -0.3f, 0.9375f}, + {-2.65f, 0f, 0.9375f}, + {-2f, -0.3f, 0.9f}, + {-1.9f, -0.3f, 0.6f}, + {-1.9f, 0f, 0.6f}, + {1.7f, 0f, 1.425f}, + {1.7f, -0.66f, 1.425f}, + {1.7f, -0.66f, 0.6f}, + {1.7f, 0f, 0.6f}, + {2.6f, 0f, 1.425f}, + {2.6f, -0.66f, 1.425f}, + {3.1f, -0.66f, 0.825f}, + {3.1f, 0f, 0.825f}, + {2.3f, 0f, 2.1f}, + {2.3f, -0.25f, 2.1f}, + {2.4f, -0.25f, 2.025f}, + {2.4f, 0f, 2.025f}, + {2.7f, 0f, 2.4f}, + {2.7f, -0.25f, 2.4f}, + {3.3f, -0.25f, 2.4f}, + {3.3f, 0f, 2.4f}, + {2.8f, 0f, 2.475f}, + {2.8f, -0.25f, 2.475f}, + {3.525f, -0.25f, 2.49375f}, + {3.525f, 0f, 2.49375f}, + {2.9f, 0f, 2.475f}, + {2.9f, -0.15f, 2.475f}, + {3.45f, -0.15f, 2.5125f}, + {3.45f, 0f, 2.5125f}, + {2.8f, 0f, 2.4f}, + {2.8f, -0.15f, 2.4f}, + {3.2f, -0.15f, 2.4f}, + {3.2f, 0f, 2.4f}, + {0f, 0f, 3.15f}, + {0.8f, 0f, 3.15f}, + {0.8f, -0.45f, 3.15f}, + {0.45f, -0.8f, 3.15f}, + {0f, -0.8f, 3.15f}, + {0f, 0f, 2.85f}, + {1.4f, 0f, 2.4f}, + {1.4f, -0.784f, 2.4f}, + {0.784f, -1.4f, 2.4f}, + {0f, -1.4f, 2.4f}, + {0.4f, 0f, 2.55f}, + {0.4f, -0.224f, 2.55f}, + {0.224f, -0.4f, 2.55f}, + {0f, -0.4f, 2.55f}, + {1.3f, 0f, 2.55f}, + {1.3f, -0.728f, 2.55f}, + {0.728f, -1.3f, 2.55f}, + {0f, -1.3f, 2.55f}, + {1.3f, 0f, 2.4f}, + {1.3f, -0.728f, 2.4f}, + {0.728f, -1.3f, 2.4f}, + {0f, -1.3f, 2.4f}, + {0f, 0f, 0f}, + {1.425f, -0.798f, 0f}, + {1.5f, 0f, 0.075f}, + {1.425f, 0f, 0f}, + {0.798f, -1.425f, 0f}, + {0f, -1.5f, 0.075f}, + {0f, -1.425f, 0f}, + {1.5f, -0.84f, 0.075f}, + {0.84f, -1.5f, 0.075f} + }; + // Since GL2.glMap2f expects a packed array of floats, we must convert + // from a 3-dimensional array to a 1-dimensional array + private static final float[] teapotTex = { + 0, 0, 1, 0, 0, 1, 1, 1 + }; + + private static void teapot(GL2 gl, + int grid, + double scale, + int type, + boolean backCompatible) + { + // As mentioned above, GL2.glMap2f expects a packed array of floats + float[] p = new float[4*4*3]; + float[] q = new float[4*4*3]; + float[] r = new float[4*4*3]; + float[] s = new float[4*4*3]; + int i, j, k, l; + + gl.glPushAttrib(GL2.GL_ENABLE_BIT | GL2.GL_EVAL_BIT | GL2.GL_POLYGON_BIT); + gl.glEnable(GL2.GL_AUTO_NORMAL); + gl.glEnable(GL2.GL_NORMALIZE); + gl.glEnable(GL2.GL_MAP2_VERTEX_3); + gl.glEnable(GL2.GL_MAP2_TEXTURE_COORD_2); + gl.glPushMatrix(); + if (!backCompatible) { + // The time has come to have the teapot no longer be inside out + gl.glFrontFace(GL2.GL_CW); + gl.glScaled(0.5*scale, 0.5*scale, 0.5*scale); + } else { + // We want the teapot in it's backward compatible position and + // orientation + gl.glRotatef(270.0f, 1, 0, 0); + gl.glScalef((float)(0.5 * scale), + (float)(0.5 * scale), + (float)(0.5 * scale)); + gl.glTranslatef(0.0f, 0.0f, -1.5f); + } + for (i = 0; i < 10; i++) { + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + for (l = 0; l < 3; l++) { + p[(j*4+k)*3+l] = teapotCPData[teapotPatchData[i][j * 4 + k]][l]; + q[(j*4+k)*3+l] = + teapotCPData[teapotPatchData[i][j * 4 + (3 - k)]][l]; + if (l == 1) + q[(j*4+k)*3+l] *= -1.0; + if (i < 6) { + r[(j*4+k)*3+l] = + teapotCPData[teapotPatchData[i][j * 4 + (3 - k)]][l]; + if (l == 0) + r[(j*4+k)*3+l] *= -1.0; + s[(j*4+k)*3+l] = teapotCPData[teapotPatchData[i][j * 4 + k]][l]; + if (l == 0) + s[(j*4+k)*3+l] *= -1.0; + if (l == 1) + s[(j*4+k)*3+l] *= -1.0; + } + } + } + } + gl.glMap2f(GL2.GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, teapotTex, 0); + gl.glMap2f(GL2.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, p, 0); + gl.glMapGrid2f(grid, 0.0f, 1.0f, grid, 0.0f, 1.0f); + evaluateTeapotMesh(gl, grid, type, i, !backCompatible); + gl.glMap2f(GL2.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, q, 0); + evaluateTeapotMesh(gl, grid, type, i, !backCompatible); + if (i < 6) { + gl.glMap2f(GL2.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, r, 0); + evaluateTeapotMesh(gl, grid, type, i, !backCompatible); + gl.glMap2f(GL2.GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, s, 0); + evaluateTeapotMesh(gl, grid, type, i, !backCompatible); + } + } + gl.glPopMatrix(); + gl.glPopAttrib(); + } + + private static void evaluateTeapotMesh(GL2 gl, + int grid, + int type, + int partNum, + boolean repairSingularities) + { + if (repairSingularities && (partNum == 5 || partNum == 3)) { + // Instead of using evaluators that give bad results at singularities, + // evaluate by hand + gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, type); + for (int nv = 0; nv < grid; nv++) { + if (nv == 0) { + // Draw a small triangle-fan to fill the hole + gl.glDisable(GL2.GL_AUTO_NORMAL); + gl.glNormal3f(0, 0, partNum == 3 ? 1 : -1); + gl.glBegin(GL2.GL_TRIANGLE_FAN); + { + gl.glEvalCoord2f(0, 0); + // Note that we draw in clock-wise order to match the evaluator + // method + for (int nu = 0; nu <= grid; nu++) + { + gl.glEvalCoord2f(nu / (float)grid, (1f / grid) / (float)grid); + } + } + gl.glEnd(); + gl.glEnable(GL2.GL_AUTO_NORMAL); + } + // Draw the rest of the piece as an evaluated quad-strip + gl.glBegin(GL2.GL_QUAD_STRIP); + { + // Note that we draw in clock-wise order to match the evaluator method + for (int nu = grid; nu >= 0; nu--) { + gl.glEvalCoord2f(nu / (float)grid, (nv + 1) / (float)grid); + gl.glEvalCoord2f(nu / (float)grid, Math.max(nv, 1f / grid) + / (float)grid); + } + } + gl.glEnd(); + } + } else { + gl.glEvalMesh2(type, 0, grid, 0, grid); + } + } + + //---------------------------------------------------------------------- + // Font implementation + // + + private static void bitmapCharacterImpl(GL2 gl, int font, char cin) { + BitmapFontRec fontinfo = getBitmapFont(font); + int c = cin & 0xFFFF; + if (c < fontinfo.first || + c >= fontinfo.first + fontinfo.num_chars) + return; + BitmapCharRec ch = fontinfo.ch[c - fontinfo.first]; + if (ch != null) { + gl.glBitmap(ch.width, ch.height, ch.xorig, ch.yorig, + ch.advance, 0, ch.bitmap, 0); + } + } + + private static final BitmapFontRec[] bitmapFonts = new BitmapFontRec[9]; + private static final StrokeFontRec[] strokeFonts = new StrokeFontRec[9]; + + private static BitmapFontRec getBitmapFont(int font) { + BitmapFontRec rec = bitmapFonts[font]; + if (rec == null) { + switch (font) { + case BITMAP_9_BY_15: + rec = GLUTBitmap9x15.glutBitmap9By15; + break; + case BITMAP_8_BY_13: + rec = GLUTBitmap8x13.glutBitmap8By13; + break; + case BITMAP_TIMES_ROMAN_10: + rec = GLUTBitmapTimesRoman10.glutBitmapTimesRoman10; + break; + case BITMAP_TIMES_ROMAN_24: + rec = GLUTBitmapTimesRoman24.glutBitmapTimesRoman24; + break; + case BITMAP_HELVETICA_10: + rec = GLUTBitmapHelvetica10.glutBitmapHelvetica10; + break; + case BITMAP_HELVETICA_12: + rec = GLUTBitmapHelvetica12.glutBitmapHelvetica12; + break; + case BITMAP_HELVETICA_18: + rec = GLUTBitmapHelvetica18.glutBitmapHelvetica18; + break; + default: + throw new GLException("Unknown bitmap font number " + font); + } + bitmapFonts[font] = rec; + } + return rec; + } + + private static StrokeFontRec getStrokeFont(int font) { + StrokeFontRec rec = strokeFonts[font]; + if (rec == null) { + switch (font) { + case STROKE_ROMAN: + rec = GLUTStrokeRoman.glutStrokeRoman; + break; + case STROKE_MONO_ROMAN: + rec = GLUTStrokeMonoRoman.glutStrokeMonoRoman; + break; + default: + throw new GLException("Unknown stroke font number " + font); + } + } + return rec; + } + + private static void beginBitmap(GL2 gl, + int[] swapbytes, + int[] lsbfirst, + int[] rowlength, + int[] skiprows, + int[] skippixels, + int[] alignment) { + gl.glGetIntegerv(GL2.GL_UNPACK_SWAP_BYTES, swapbytes, 0); + gl.glGetIntegerv(GL2.GL_UNPACK_LSB_FIRST, lsbfirst, 0); + gl.glGetIntegerv(GL2.GL_UNPACK_ROW_LENGTH, rowlength, 0); + gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_ROWS, skiprows, 0); + gl.glGetIntegerv(GL2.GL_UNPACK_SKIP_PIXELS, skippixels, 0); + gl.glGetIntegerv(GL2.GL_UNPACK_ALIGNMENT, alignment, 0); + /* Little endian machines (DEC Alpha for example) could + benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE + instead of GL_FALSE, but this would require changing the + generated bitmaps too. */ + gl.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, GL2.GL_FALSE); + gl.glPixelStorei(GL2.GL_UNPACK_LSB_FIRST, GL2.GL_FALSE); + gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1); + } + + private static void endBitmap(GL2 gl, + int[] swapbytes, + int[] lsbfirst, + int[] rowlength, + int[] skiprows, + int[] skippixels, + int[] alignment) { + /* Restore saved modes. */ + gl.glPixelStorei(GL2.GL_UNPACK_SWAP_BYTES, swapbytes[0]); + gl.glPixelStorei(GL2.GL_UNPACK_LSB_FIRST, lsbfirst[0]); + gl.glPixelStorei(GL2.GL_UNPACK_ROW_LENGTH, rowlength[0]); + gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, skiprows[0]); + gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, skippixels[0]); + gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, alignment[0]); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java new file mode 100644 index 000000000..07ded652a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap8x13.java @@ -0,0 +1,2078 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmap8x13 { + +/* GENERATED FILE -- DO NOT MODIFY */ + + +static final BitmapCharRec ch0 = new BitmapCharRec(0,0,0,0,8,null); + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,8,null); + +static final BitmapCharRec ch127 = new BitmapCharRec(0,0,0,0,8,null); + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,8,null); + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(6,12,-1,2,8,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0x80,(byte) 0x80,(byte) 0xb8,(byte) 0xc4,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(6,10,-1,2,8,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(6,12,-1,2,8,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(6,10,-1,0,8,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(6,10,-1,0,8,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(6,10,-1,0,8,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(6,10,-1,0,8,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0x80,(byte) 0x78,(byte) 0xc4,(byte) 0xa4,(byte) 0x94,(byte) 0x8c,(byte) 0x78,(byte) 0x4, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(6,8,-1,1,8,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x20,(byte) 0x20,(byte) 0x0,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(5,7,-1,-1,8,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(6,10,-1,0,8,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(6,10,-1,0,8,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(6,10,-1,0,8,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(6,10,-1,0,8,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(6,10,-1,0,8,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(6,10,-1,0,8,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x8,(byte) 0x50,(byte) 0x30,(byte) 0x48, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(6,10,-1,0,8,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x50, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(5,10,-1,0,8,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(5,10,-1,0,8,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(5,10,-1,0,8,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(5,10,-1,0,8,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0xfc,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(6,10,-1,0,8,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0xfc,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(6,10,-1,0,8,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0xfc,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(6,10,-1,0,8,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0xfc,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(6,10,-1,0,8,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x20,(byte) 0x10,(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(6,8,-1,2,8,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x6c,(byte) 0x92,(byte) 0x90,(byte) 0x7c,(byte) 0x12,(byte) 0x6c, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(7,6,0,0,8,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x30,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(6,10,-1,0,8,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(6,10,-1,0,8,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(6,10,-1,0,8,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(6,10,-1,0,8,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(6,10,-1,0,8,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(6,10,-1,0,8,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0x80,(byte) 0xb8,(byte) 0xc4,(byte) 0x84,(byte) 0x84,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(6,9,-1,1,8,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8,(byte) 0x80, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(6,9,-1,0,8,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x50,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(5,10,-1,0,8,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(6,10,-1,0,8,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(6,10,-1,0,8,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(6,10,-1,0,8,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(6,10,-1,0,8,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x80,(byte) 0x78,(byte) 0xc4,(byte) 0xa4,(byte) 0xa4,(byte) 0xa4,(byte) 0x94,(byte) 0x94,(byte) 0x8c,(byte) 0x78,(byte) 0x4, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(6,11,-1,1,8,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x30,(byte) 0x48,(byte) 0x84, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(6,6,-1,-1,8,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(7,10,0,0,8,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(7,10,0,0,8,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x24,(byte) 0x18, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(7,10,0,0,8,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(7,10,0,0,8,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x8,(byte) 0x10, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(7,10,0,0,8,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0x82,(byte) 0x86,(byte) 0x8a,(byte) 0x92,(byte) 0xa2,(byte) 0xc2,(byte) 0x82,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(7,10,0,0,8,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xe2,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(7,9,0,0,8,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x50,(byte) 0x50, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(5,10,-1,0,8,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(5,10,-1,0,8,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(5,10,-1,0,8,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(5,10,-1,0,8,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(6,10,-1,0,8,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(6,10,-1,0,8,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(6,10,-1,0,8,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(6,10,-1,0,8,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x20,(byte) 0x10,(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(6,11,-1,2,8,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0x9e,(byte) 0x90,(byte) 0x90,(byte) 0xf0,(byte) 0x9c,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x6e, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(7,9,0,0,8,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x30,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(6,10,-1,0,8,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x0,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(6,10,-1,0,8,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(6,10,-1,0,8,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x0,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(6,10,-1,0,8,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(6,10,-1,0,8,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(6,10,-1,0,8,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(6,9,-1,0,8,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x6,(byte) 0x1a,(byte) 0x12,(byte) 0xa,(byte) 0x66,(byte) 0x92,(byte) 0x10,(byte) 0x20,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(7,10,0,0,8,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x1e,(byte) 0x10,(byte) 0xc,(byte) 0x2,(byte) 0xf2,(byte) 0x4c,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(7,10,0,0,8,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x6,(byte) 0x1a,(byte) 0x12,(byte) 0xa,(byte) 0xe6,(byte) 0x42,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(7,10,0,0,8,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0x90,(byte) 0x48,(byte) 0x24,(byte) 0x12,(byte) 0x24,(byte) 0x48,(byte) 0x90, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(7,7,0,-1,8,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xf0,(byte) 0x0,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(4,6,-1,-3,8,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(3,6,-1,-4,8,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(2,2,-3,2,8,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0xc0, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(2,1,-3,-4,8,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x68,(byte) 0xe8,(byte) 0xe8,(byte) 0xe8,(byte) 0x7c, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(6,9,-1,0,8,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x80,(byte) 0xb4,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(6,7,-1,1,8,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(2,2,-3,-8,8,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x20,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(4,6,-1,-4,8,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x60,(byte) 0x10,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(4,6,-1,-4,8,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(5,7,-1,-1,8,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(4,4,-2,-5,8,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(6,1,-1,-8,8,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x38,(byte) 0x44,(byte) 0xaa,(byte) 0xb2,(byte) 0xaa,(byte) 0xaa,(byte) 0x92,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(7,9,0,-1,8,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(6,1,-1,-4,8,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(6,4,-1,-1,8,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x12,(byte) 0x24,(byte) 0x48,(byte) 0x90,(byte) 0x48,(byte) 0x24,(byte) 0x12, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(7,7,0,-1,8,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x78,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x70, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(5,7,-1,-2,8,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x38,(byte) 0x44,(byte) 0x92,(byte) 0xaa,(byte) 0xa2,(byte) 0xaa,(byte) 0x92,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(7,9,0,-1,8,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xd8, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(5,1,-1,-8,8,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x80,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(4,10,-2,0,8,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(1,9,-3,0,8,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x10,(byte) 0x10,(byte) 0x7c,(byte) 0x10,(byte) 0x7c,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(7,9,0,0,8,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0x84,(byte) 0x78,(byte) 0x48,(byte) 0x48,(byte) 0x78,(byte) 0x84, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(6,6,-1,-1,8,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xdc,(byte) 0x62,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x70,(byte) 0x20,(byte) 0x22,(byte) 0x1c, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(7,9,0,0,8,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x20,(byte) 0x70,(byte) 0xa8,(byte) 0xa0,(byte) 0xa0,(byte) 0xa8,(byte) 0x70,(byte) 0x20, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(5,8,-1,-1,8,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(1,9,-3,0,8,ch161data); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x90,(byte) 0xa8,(byte) 0x48, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(5,3,-1,-6,8,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0xe0,(byte) 0x10,(byte) 0x10,(byte) 0x20,(byte) 0x18,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0xe0, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(5,9,-1,0,8,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(1,9,-3,0,8,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x38,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x38, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(5,9,-2,0,8,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xfc,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0xfc, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(6,6,-1,0,8,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(6,8,-1,2,8,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x30,(byte) 0x48,(byte) 0x84, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(6,6,-1,0,8,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x44,(byte) 0xaa,(byte) 0x92,(byte) 0x92,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(7,6,0,0,8,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x20,(byte) 0x50,(byte) 0x50,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(5,6,-1,0,8,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(6,6,-1,0,8,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x38,(byte) 0x44,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xf8,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(6,8,-1,0,8,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0x78,(byte) 0x84,(byte) 0x18,(byte) 0x60,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(6,6,-1,0,8,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x44,(byte) 0xb8, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(6,6,-1,0,8,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x8c,(byte) 0x74, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(6,8,-1,2,8,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xb8,(byte) 0xc4,(byte) 0x84,(byte) 0xc4,(byte) 0xb8, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(6,8,-1,2,8,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(6,6,-1,0,8,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(6,6,-1,0,8,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0x82,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xec, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(7,6,0,0,8,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(5,9,-1,0,8,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xe0,(byte) 0x90,(byte) 0x88,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(6,9,-1,0,8,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x18,(byte) 0x0,(byte) 0x8, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(5,10,-1,2,8,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(5,8,-1,0,8,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(6,9,-1,0,8,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x78,(byte) 0x84,(byte) 0x78,(byte) 0x80,(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x74, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(6,8,-1,2,8,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xf8,(byte) 0x40,(byte) 0x40,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(6,9,-1,0,8,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0xfc,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(6,6,-1,0,8,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x8c,(byte) 0x74,(byte) 0x4,(byte) 0x4,(byte) 0x4, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(6,9,-1,0,8,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(6,6,-1,0,8,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xb8,(byte) 0xc4,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(6,9,-1,0,8,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x7c,(byte) 0x4,(byte) 0x78, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(6,6,-1,0,8,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0x10,(byte) 0x60,(byte) 0xe0, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(4,3,-2,-6,8,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xfe, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(7,1,0,1,8,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x88,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(5,3,-1,-6,8,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xf0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xf0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(4,9,-1,0,8,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x2,(byte) 0x2,(byte) 0x4,(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(7,9,0,0,8,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(4,9,-2,0,8,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(6,9,-1,0,8,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(7,9,0,0,8,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(7,9,0,0,8,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x44,(byte) 0xaa,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(7,9,0,0,8,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(7,9,0,0,8,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(6,9,-1,0,8,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xfe, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(7,9,0,0,8,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x4,(byte) 0x78,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(6,9,-1,0,8,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xa0,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(6,9,-1,0,8,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x4,(byte) 0x78,(byte) 0x94,(byte) 0xa4,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(6,10,-1,1,8,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(6,9,-1,0,8,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(6,9,-1,0,8,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x8c,(byte) 0x94,(byte) 0xa4,(byte) 0xc4,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(6,9,-1,0,8,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x92,(byte) 0x92,(byte) 0xaa,(byte) 0xc6,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(7,9,0,0,8,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(6,9,-1,0,8,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xa0,(byte) 0xc0,(byte) 0xa0,(byte) 0x90,(byte) 0x88,(byte) 0x84, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(6,9,-1,0,8,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x3c, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(6,9,-1,0,8,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(5,9,-1,0,8,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(6,9,-1,0,8,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x9c,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(6,9,-1,0,8,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(6,9,-1,0,8,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(6,9,-1,0,8,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(7,9,0,0,8,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(6,9,-1,0,8,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x7c,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(7,9,0,0,8,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(6,9,-1,0,8,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x78,(byte) 0x80,(byte) 0x94,(byte) 0xac,(byte) 0xa4,(byte) 0x9c,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(6,9,-1,0,8,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(6,9,-1,0,8,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(5,9,-1,0,8,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x0,(byte) 0xfc, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(6,4,-1,-2,8,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(5,9,-2,0,8,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x60,(byte) 0x70,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x70,(byte) 0x20, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(4,8,-1,1,8,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x0,(byte) 0x0,(byte) 0x40,(byte) 0xe0,(byte) 0x40, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(3,8,-2,1,8,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0x70,(byte) 0x8,(byte) 0x4,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(6,9,-1,0,8,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(6,9,-1,0,8,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(6,9,-1,0,8,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0xc4,(byte) 0xb8,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x38, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(6,9,-1,0,8,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x4,(byte) 0xc4,(byte) 0xb8,(byte) 0x80,(byte) 0x80,(byte) 0xfc, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(6,9,-1,0,8,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x8,(byte) 0x8,(byte) 0xfc,(byte) 0x88,(byte) 0x88,(byte) 0x48,(byte) 0x28,(byte) 0x18,(byte) 0x8, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(6,9,-1,0,8,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x4,(byte) 0x38,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(6,9,-1,0,8,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x40,(byte) 0x30,(byte) 0x8,(byte) 0x4,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(6,9,-1,0,8,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xa0,(byte) 0x60,(byte) 0x20, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(5,9,-1,0,8,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x30,(byte) 0x48,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(6,9,-1,0,8,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0x2, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(7,9,0,0,8,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0x40,(byte) 0xe0,(byte) 0x40, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(3,3,-2,1,8,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(6,1,-1,-4,8,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x60,(byte) 0x70, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(4,3,-1,1,8,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(5,5,-1,-2,8,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0x48,(byte) 0x30,(byte) 0xfc,(byte) 0x30,(byte) 0x48, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(6,5,-1,-2,8,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(3,9,-2,0,8,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(3,9,-3,0,8,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x80,(byte) 0x60,(byte) 0x70, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(4,3,-1,-6,8,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x74,(byte) 0x88,(byte) 0x94,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(6,7,-1,0,8,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x88,(byte) 0x54,(byte) 0x48,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x48,(byte) 0xa4,(byte) 0x44, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(6,9,-1,0,8,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x20,(byte) 0xf0,(byte) 0x28,(byte) 0x70,(byte) 0xa0,(byte) 0x78,(byte) 0x20, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(5,7,-1,-1,8,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x48,(byte) 0x48,(byte) 0xfc,(byte) 0x48,(byte) 0xfc,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(6,7,-1,-1,8,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(4,3,-2,-6,8,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(1,9,-3,0,8,ch33data); + +/* char: 0x1f */ + +static final byte[] ch31data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch31 = new BitmapCharRec(1,1,-3,-3,8,ch31data); + +/* char: 0x1e */ + +static final byte[] ch30data = { +(byte) 0xdc,(byte) 0x62,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x70,(byte) 0x20,(byte) 0x22,(byte) 0x1c, +}; + +static final BitmapCharRec ch30 = new BitmapCharRec(7,9,0,0,8,ch30data); + +/* char: 0x1d */ + +static final byte[] ch29data = { +(byte) 0x80,(byte) 0x40,(byte) 0xfe,(byte) 0x10,(byte) 0xfe,(byte) 0x4,(byte) 0x2, +}; + +static final BitmapCharRec ch29 = new BitmapCharRec(7,7,0,0,8,ch29data); + +/* char: 0x1c */ + +static final byte[] ch28data = { +(byte) 0x88,(byte) 0x48,(byte) 0x48,(byte) 0x48,(byte) 0x48,(byte) 0xfc, +}; + +static final BitmapCharRec ch28 = new BitmapCharRec(6,6,-1,0,8,ch28data); + +/* char: 0x1b */ + +static final byte[] ch27data = { +(byte) 0xfe,(byte) 0x80,(byte) 0x20,(byte) 0x8,(byte) 0x2,(byte) 0x8,(byte) 0x20,(byte) 0x80, +}; + +static final BitmapCharRec ch27 = new BitmapCharRec(7,8,0,0,8,ch27data); + +/* char: 0x1a */ + +static final byte[] ch26data = { +(byte) 0xfe,(byte) 0x2,(byte) 0x8,(byte) 0x20,(byte) 0x80,(byte) 0x20,(byte) 0x8,(byte) 0x2, +}; + +static final BitmapCharRec ch26 = new BitmapCharRec(7,8,0,0,8,ch26data); + +/* char: 0x19 */ + +static final byte[] ch25data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch25 = new BitmapCharRec(1,13,-3,2,8,ch25data); + +/* char: 0x18 */ + +static final byte[] ch24data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xff, +}; + +static final BitmapCharRec ch24 = new BitmapCharRec(8,6,0,2,8,ch24data); + +/* char: 0x17 */ + +static final byte[] ch23data = { +(byte) 0xff,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch23 = new BitmapCharRec(8,8,0,-3,8,ch23data); + +/* char: 0x16 */ + +static final byte[] ch22data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xf0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch22 = new BitmapCharRec(4,13,0,2,8,ch22data); + +/* char: 0x15 */ + +static final byte[] ch21data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch21 = new BitmapCharRec(5,13,-3,2,8,ch21data); + +/* char: 0x14 */ + +static final byte[] ch20data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch20 = new BitmapCharRec(8,1,0,1,8,ch20data); + +/* char: 0x13 */ + +static final byte[] ch19data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch19 = new BitmapCharRec(8,1,0,-1,8,ch19data); + +/* char: 0x12 */ + +static final byte[] ch18data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch18 = new BitmapCharRec(8,1,0,-3,8,ch18data); + +/* char: 0x11 */ + +static final byte[] ch17data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch17 = new BitmapCharRec(8,1,0,-5,8,ch17data); + +/* char: 0x10 */ + +static final byte[] ch16data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch16 = new BitmapCharRec(8,1,0,-7,8,ch16data); + +/* char: 0xf */ + +static final byte[] ch15data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xff,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch15 = new BitmapCharRec(8,13,0,2,8,ch15data); + +/* char: 0xe */ + +static final byte[] ch14data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch14 = new BitmapCharRec(5,8,-3,-3,8,ch14data); + +/* char: 0xd */ + +static final byte[] ch13data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch13 = new BitmapCharRec(5,6,-3,2,8,ch13data); + +/* char: 0xc */ + +static final byte[] ch12data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xf0, +}; + +static final BitmapCharRec ch12 = new BitmapCharRec(4,6,0,2,8,ch12data); + +/* char: 0xb */ + +static final byte[] ch11data = { +(byte) 0xf0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch11 = new BitmapCharRec(4,8,0,-3,8,ch11data); + +/* char: 0xa */ + +static final byte[] ch10data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x3e,(byte) 0x20,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch10 = new BitmapCharRec(7,9,0,2,8,ch10data); + +/* char: 0x9 */ + +static final byte[] ch9data = { +(byte) 0x3e,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x88,(byte) 0x98,(byte) 0xa8,(byte) 0xc8,(byte) 0x88, +}; + +static final BitmapCharRec ch9 = new BitmapCharRec(7,9,0,2,8,ch9data); + +/* char: 0x8 */ + +static final byte[] ch8data = { +(byte) 0xfe,(byte) 0x10,(byte) 0x10,(byte) 0xfe,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch8 = new BitmapCharRec(7,6,0,0,8,ch8data); + +/* char: 0x7 */ + +static final byte[] ch7data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch7 = new BitmapCharRec(5,4,-1,-5,8,ch7data); + +/* char: 0x6 */ + +static final byte[] ch6data = { +(byte) 0x20,(byte) 0x20,(byte) 0x3c,(byte) 0x20,(byte) 0x3e,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch6 = new BitmapCharRec(7,9,0,2,8,ch6data); + +/* char: 0x5 */ + +static final byte[] ch5data = { +(byte) 0x22,(byte) 0x22,(byte) 0x3c,(byte) 0x22,(byte) 0x3c,(byte) 0x78,(byte) 0x80,(byte) 0x80,(byte) 0x78, +}; + +static final BitmapCharRec ch5 = new BitmapCharRec(7,9,0,2,8,ch5data); + +/* char: 0x4 */ + +static final byte[] ch4data = { +(byte) 0x10,(byte) 0x10,(byte) 0x1c,(byte) 0x10,(byte) 0x9e,(byte) 0x80,(byte) 0xe0,(byte) 0x80,(byte) 0xf0, +}; + +static final BitmapCharRec ch4 = new BitmapCharRec(7,9,0,2,8,ch4data); + +/* char: 0x3 */ + +static final byte[] ch3data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x3e,(byte) 0x88,(byte) 0x88,(byte) 0xf8,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch3 = new BitmapCharRec(7,9,0,2,8,ch3data); + +/* char: 0x2 */ + +static final byte[] ch2data = { +(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa, +}; + +static final BitmapCharRec ch2 = new BitmapCharRec(8,12,0,2,8,ch2data); + +/* char: 0x1 */ + +static final byte[] ch1data = { +(byte) 0x10,(byte) 0x38,(byte) 0x7c,(byte) 0xfe,(byte) 0x7c,(byte) 0x38,(byte) 0x10, +}; + +static final BitmapCharRec ch1 = new BitmapCharRec(7,7,0,-1,8,ch1data); + +static final BitmapCharRec[] chars = { +ch0, +ch1, +ch2, +ch3, +ch4, +ch5, +ch6, +ch7, +ch8, +ch9, +ch10, +ch11, +ch12, +ch13, +ch14, +ch15, +ch16, +ch17, +ch18, +ch19, +ch20, +ch21, +ch22, +ch23, +ch24, +ch25, +ch26, +ch27, +ch28, +ch29, +ch30, +ch31, +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +ch127, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmap8By13 = new BitmapFontRec("-misc-fixed-medium-r-normal--13-120-75-75-C-80-iso8859-1", + 256, + 0, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java new file mode 100644 index 000000000..5d357f3f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmap9x15.java @@ -0,0 +1,2079 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmap9x15 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +static final BitmapCharRec ch0 = new BitmapCharRec(0,0,0,0,9,null); + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,9,null); + +static final BitmapCharRec ch127 = new BitmapCharRec(0,0,0,0,9,null); + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,9,null); + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(6,14,-1,3,9,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xbc,(byte) 0xc2,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(7,12,-1,3,9,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(6,14,-1,3,9,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x7a,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(7,11,-1,0,9,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x7a,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(7,11,-1,0,9,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x7a,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(7,11,-1,0,9,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x7a,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(7,11,-1,0,9,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0x80,(byte) 0x7c,(byte) 0xa2,(byte) 0xa2,(byte) 0x92,(byte) 0x8a,(byte) 0x8a,(byte) 0x7c,(byte) 0x2, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(7,9,-1,1,9,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x10,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0xfe,(byte) 0x0,(byte) 0x10,(byte) 0x38,(byte) 0x10, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(7,9,-1,0,9,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(7,11,-1,0,9,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(7,11,-1,0,9,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(7,11,-1,0,9,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(7,11,-1,0,9,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(7,11,-1,0,9,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(7,11,-1,0,9,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x8,(byte) 0x50,(byte) 0x30,(byte) 0x48, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(7,11,-1,0,9,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x50, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(5,11,-2,0,9,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(5,11,-2,0,9,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x60,(byte) 0x10, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(5,11,-2,0,9,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x40, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(5,11,-2,0,9,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(7,11,-1,0,9,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(7,11,-1,0,9,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(7,11,-1,0,9,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(7,11,-1,0,9,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x30,(byte) 0x48,(byte) 0x18,(byte) 0x7c,(byte) 0x82,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(7,10,-1,3,9,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x6e,(byte) 0x92,(byte) 0x90,(byte) 0x7c,(byte) 0x12,(byte) 0x92,(byte) 0x6c, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(7,7,-1,0,9,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x18,(byte) 0x24,(byte) 0x18, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(7,11,-1,0,9,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(7,11,-1,0,9,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(7,11,-1,0,9,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(7,11,-1,0,9,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(7,11,-1,0,9,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(7,11,-1,0,9,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0x80,(byte) 0xbc,(byte) 0xc2,(byte) 0x82,(byte) 0x82,(byte) 0xfc,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(7,9,-1,1,9,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfc,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(7,10,-1,0,9,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(7,11,-1,0,9,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(7,11,-1,0,9,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(7,11,-1,0,9,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(7,11,-1,0,9,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(7,11,-1,0,9,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x80,(byte) 0x7c,(byte) 0xc2,(byte) 0xa2,(byte) 0xa2,(byte) 0x92,(byte) 0x92,(byte) 0x8a,(byte) 0x8a,(byte) 0x86,(byte) 0x7c,(byte) 0x2, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(7,12,-1,1,9,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(7,7,-1,-1,9,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(7,11,-1,0,9,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(7,11,-1,0,9,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(7,11,-1,0,9,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(7,11,-1,0,9,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(7,11,-1,0,9,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0x82,(byte) 0x86,(byte) 0x8a,(byte) 0x92,(byte) 0x92,(byte) 0xa2,(byte) 0xc2,(byte) 0x82,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(7,11,-1,0,9,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xf2,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(7,10,-1,0,9,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x50,(byte) 0x50, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(5,11,-2,0,9,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(5,11,-2,0,9,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x60,(byte) 0x10, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(5,11,-2,0,9,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x0,(byte) 0x30,(byte) 0x40, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(5,11,-2,0,9,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0xfe,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(7,11,-1,0,9,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0xfe,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(7,11,-1,0,9,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0xfe,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(7,11,-1,0,9,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0xfe,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(7,11,-1,0,9,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x30,(byte) 0x48,(byte) 0x18,(byte) 0x7c,(byte) 0x82,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(7,13,-1,3,9,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0x9e,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xfc,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x6e, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(7,10,-1,0,9,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x10,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(7,11,-1,0,9,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x0,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(7,11,-1,0,9,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(7,11,-1,0,9,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x0,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(7,11,-1,0,9,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x0,(byte) 0x30,(byte) 0x8, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(7,11,-1,0,9,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x0,(byte) 0x18,(byte) 0x20, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(7,11,-1,0,9,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x10, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(7,10,-1,0,9,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x6,(byte) 0x1a,(byte) 0x12,(byte) 0xa,(byte) 0x66,(byte) 0x92,(byte) 0x10,(byte) 0x20,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(7,10,-1,0,9,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x1e,(byte) 0x10,(byte) 0xc,(byte) 0x2,(byte) 0xf2,(byte) 0x4c,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(7,10,-1,0,9,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x6,(byte) 0x1a,(byte) 0x12,(byte) 0xa,(byte) 0xe6,(byte) 0x42,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(7,10,-1,0,9,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0x90,(byte) 0x48,(byte) 0x24,(byte) 0x12,(byte) 0x12,(byte) 0x24,(byte) 0x48,(byte) 0x90, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(7,8,-1,-1,9,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(5,6,-1,-5,9,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(3,6,-1,-4,9,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0x60,(byte) 0x90,(byte) 0x30, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(4,3,-2,3,9,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(2,2,-4,-4,9,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0xa,(byte) 0xa,(byte) 0xa,(byte) 0xa,(byte) 0xa,(byte) 0x7a,(byte) 0x8a,(byte) 0x8a,(byte) 0x8a,(byte) 0x7e, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(7,10,-1,0,9,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x80,(byte) 0x80,(byte) 0xba,(byte) 0xc6,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(7,9,-1,2,9,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0xc0,(byte) 0x20, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(3,2,-3,-9,9,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x20,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(4,6,-1,-4,9,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x60,(byte) 0x10,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(4,6,-1,-4,9,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xfe,(byte) 0x0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xfe,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(7,9,-1,-1,9,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(4,4,-3,-6,9,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(6,1,-1,-9,9,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x3c,(byte) 0x42,(byte) 0xa5,(byte) 0xa9,(byte) 0xbd,(byte) 0xa5,(byte) 0xb9,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(8,9,0,-1,9,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(6,1,-1,-4,9,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(6,4,-1,-2,9,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x12,(byte) 0x24,(byte) 0x48,(byte) 0x90,(byte) 0x90,(byte) 0x48,(byte) 0x24,(byte) 0x12, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(7,8,-1,-1,9,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x78,(byte) 0x90,(byte) 0x70,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(5,7,-3,-3,9,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x99,(byte) 0xa5,(byte) 0xa1,(byte) 0xa5,(byte) 0x99,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(8,9,0,-1,9,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xa0,(byte) 0xa0, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(3,2,-3,-9,9,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(5,11,-2,1,9,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(1,11,-4,1,9,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x7c,(byte) 0x10,(byte) 0x7c,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(7,10,-1,0,9,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x7c,(byte) 0x82, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(7,6,-1,-3,9,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0x5c,(byte) 0xa2,(byte) 0x60,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x22,(byte) 0x1c, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(7,10,-1,0,9,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x40,(byte) 0x78,(byte) 0xa4,(byte) 0xa0,(byte) 0x90,(byte) 0x94,(byte) 0x78,(byte) 0x8, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(6,8,-1,0,9,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(1,11,-4,0,9,ch161data); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x8c,(byte) 0x92,(byte) 0x62, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(7,3,-1,-7,9,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0xe0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x20,(byte) 0x18,(byte) 0x18,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xe0, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(5,12,-1,1,9,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(1,12,-4,1,9,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x38,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0xc0,(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x38, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(5,12,-3,1,9,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0xfe, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(7,7,-1,0,9,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(6,10,-1,3,9,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(7,7,-1,0,9,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x44,(byte) 0xaa,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(7,7,-1,0,9,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(7,7,-1,0,9,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x7a,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(7,7,-1,0,9,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x1c,(byte) 0x22,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xfc,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(7,9,-1,0,9,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x2,(byte) 0x7c,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(7,7,-1,0,9,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x42,(byte) 0x62,(byte) 0x9c, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(7,7,-1,0,9,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x2,(byte) 0x2,(byte) 0x2,(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x86,(byte) 0x7a, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(7,10,-1,3,9,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xbc,(byte) 0xc2,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(7,10,-1,3,9,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(7,7,-1,0,9,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(7,7,-1,0,9,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0x82,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xec, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(7,7,-1,0,9,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(5,10,-2,0,9,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0x82,(byte) 0x8c,(byte) 0xb0,(byte) 0xc0,(byte) 0xb0,(byte) 0x8c,(byte) 0x82,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(7,10,-1,0,9,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x1c,(byte) 0x0,(byte) 0x0,(byte) 0xc, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(6,13,-1,3,9,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x60, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(5,10,-2,0,9,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(7,10,-1,0,9,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x80,(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x7a, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(7,10,-1,3,9,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x22,(byte) 0x22,(byte) 0x1c, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(7,10,-1,0,9,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(7,7,-1,0,9,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x86,(byte) 0x7a,(byte) 0x2,(byte) 0x2,(byte) 0x2, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(7,10,-1,0,9,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(7,7,-1,0,9,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xbc,(byte) 0xc2,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(7,10,-1,0,9,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x7e,(byte) 0x2,(byte) 0x2,(byte) 0x7c, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(7,7,-1,0,9,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(4,4,-3,-6,9,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xff, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(8,1,0,1,9,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(7,4,-1,-6,9,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xf0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xf0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(4,12,-2,1,9,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x2,(byte) 0x4,(byte) 0x4,(byte) 0x8,(byte) 0x10,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(7,10,-1,0,9,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(4,12,-3,1,9,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xfe,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0xfe, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(7,10,-1,0,9,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(7,10,-1,0,9,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(7,10,-1,0,9,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x44,(byte) 0xaa,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(7,10,-1,0,9,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(7,10,-1,0,9,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(7,10,-1,0,9,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xfe, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(7,10,-1,0,9,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x2,(byte) 0xc,(byte) 0x70,(byte) 0x80,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(7,10,-1,0,9,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0x82,(byte) 0x82,(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xfc,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfc, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(7,10,-1,0,9,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x6,(byte) 0x8,(byte) 0x7c,(byte) 0x92,(byte) 0xa2,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(7,12,-1,2,9,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfc, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(7,10,-1,0,9,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(7,10,-1,0,9,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x86,(byte) 0x8a,(byte) 0x92,(byte) 0xa2,(byte) 0xc2,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(7,10,-1,0,9,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x92,(byte) 0x92,(byte) 0xaa,(byte) 0xaa,(byte) 0xc6,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(7,10,-1,0,9,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xfe,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(7,10,-1,0,9,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0x82,(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xa0,(byte) 0xe0,(byte) 0x90,(byte) 0x88,(byte) 0x84,(byte) 0x82, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(7,10,-1,0,9,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x78,(byte) 0x84,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0x1e, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(7,10,-1,0,9,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(5,10,-2,0,9,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(7,10,-1,0,9,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x8e,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(7,10,-1,0,9,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xfe, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(7,10,-1,0,9,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xfe,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x78,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xfe, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(7,10,-1,0,9,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(7,10,-1,0,9,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(7,10,-1,0,9,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xfc,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0x7c,(byte) 0x42,(byte) 0x42,(byte) 0x42,(byte) 0xfc, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(7,10,-1,0,9,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(7,10,-1,0,9,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x7c,(byte) 0x80,(byte) 0x80,(byte) 0x9a,(byte) 0xa6,(byte) 0xa2,(byte) 0x9e,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(7,10,-1,0,9,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(7,10,-1,0,9,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(5,10,-2,0,9,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xfe,(byte) 0x0,(byte) 0x0,(byte) 0xfe, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(7,4,-1,-2,9,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(5,10,-2,0,9,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(2,10,-4,3,9,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(2,7,-4,0,9,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0x78,(byte) 0x4,(byte) 0x2,(byte) 0x2,(byte) 0x7a,(byte) 0x86,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(7,10,-1,0,9,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x38,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38,(byte) 0x44,(byte) 0x82,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(7,10,-1,0,9,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0x2,(byte) 0xfe, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(7,10,-1,0,9,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xc2,(byte) 0xbc,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x3c, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(7,10,-1,0,9,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x2,(byte) 0x2,(byte) 0x2,(byte) 0xc2,(byte) 0xbc,(byte) 0x80,(byte) 0x80,(byte) 0xfe, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(7,10,-1,0,9,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0xfe,(byte) 0x84,(byte) 0x44,(byte) 0x24,(byte) 0x14,(byte) 0xc,(byte) 0x4, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(7,10,-1,0,9,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x7c,(byte) 0x82,(byte) 0x2,(byte) 0x2,(byte) 0x2,(byte) 0x1c,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0xfe, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(7,10,-1,0,9,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xfe,(byte) 0x80,(byte) 0x40,(byte) 0x30,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0x82,(byte) 0x82,(byte) 0x7c, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(7,10,-1,0,9,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0xfe,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x90,(byte) 0x50,(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(7,10,-1,0,9,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x38,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(7,10,-1,0,9,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x4,(byte) 0x2, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(7,10,-1,0,9,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(2,2,-4,0,9,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xfe, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(7,1,-1,-4,9,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(2,5,-4,3,9,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xfe,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(7,7,-1,-1,9,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0x10,(byte) 0x92,(byte) 0x54,(byte) 0x38,(byte) 0x54,(byte) 0x92,(byte) 0x10, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(7,7,-1,-1,9,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(3,12,-3,1,9,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(3,12,-3,1,9,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x30, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(4,4,-3,-6,9,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x62,(byte) 0x94,(byte) 0x88,(byte) 0x94,(byte) 0x62,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(7,10,-1,0,9,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x84,(byte) 0x4a,(byte) 0x4a,(byte) 0x24,(byte) 0x10,(byte) 0x10,(byte) 0x48,(byte) 0xa4,(byte) 0xa4,(byte) 0x42, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(7,10,-1,0,9,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x10,(byte) 0x7c,(byte) 0x92,(byte) 0x12,(byte) 0x12,(byte) 0x14,(byte) 0x38,(byte) 0x50,(byte) 0x90,(byte) 0x92,(byte) 0x7c,(byte) 0x10, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(7,12,-1,1,9,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x48,(byte) 0x48,(byte) 0xfc,(byte) 0x48,(byte) 0x48,(byte) 0xfc,(byte) 0x48,(byte) 0x48, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(6,8,-1,-1,9,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(4,3,-3,-7,9,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(1,11,-4,0,9,ch33data); + +/* char: 0x1f */ + +static final byte[] ch31data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch31 = new BitmapCharRec(2,2,-4,-2,9,ch31data); + +/* char: 0x1e */ + +static final byte[] ch30data = { +(byte) 0x5c,(byte) 0xa2,(byte) 0x60,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x22,(byte) 0x1c, +}; + +static final BitmapCharRec ch30 = new BitmapCharRec(7,10,-1,0,9,ch30data); + +/* char: 0x1d */ + +static final byte[] ch29data = { +(byte) 0x80,(byte) 0x40,(byte) 0xfe,(byte) 0x10,(byte) 0xfe,(byte) 0x4,(byte) 0x2, +}; + +static final BitmapCharRec ch29 = new BitmapCharRec(7,7,-1,0,9,ch29data); + +/* char: 0x1c */ + +static final byte[] ch28data = { +(byte) 0x44,(byte) 0x24,(byte) 0x24,(byte) 0x24,(byte) 0x24,(byte) 0x24,(byte) 0xfe, +}; + +static final BitmapCharRec ch28 = new BitmapCharRec(7,7,-1,0,9,ch28data); + +/* char: 0x1b */ + +static final byte[] ch27data = { +(byte) 0xfe,(byte) 0x0,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch27 = new BitmapCharRec(7,12,-1,2,9,ch27data); + +/* char: 0x1a */ + +static final byte[] ch26data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x4,(byte) 0x8,(byte) 0x10,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4, +}; + +static final BitmapCharRec ch26 = new BitmapCharRec(6,12,-2,2,9,ch26data); + +/* char: 0x19 */ + +static final byte[] ch25data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch25 = new BitmapCharRec(1,15,-4,3,9,ch25data); + +/* char: 0x18 */ + +static final byte[] ch24data = { +(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch24 = new BitmapCharRec(9,7,0,3,9,ch24data); + +/* char: 0x17 */ + +static final byte[] ch23data = { +(byte) 0xff,(byte) 0x80,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0, +(byte) 0x8,(byte) 0x0, +}; + +static final BitmapCharRec ch23 = new BitmapCharRec(9,9,0,-3,9,ch23data); + +/* char: 0x16 */ + +static final byte[] ch22data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0xf8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8, +}; + +static final BitmapCharRec ch22 = new BitmapCharRec(5,15,0,3,9,ch22data); + +/* char: 0x15 */ + +static final byte[] ch21data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch21 = new BitmapCharRec(5,15,-4,3,9,ch21data); + +/* char: 0x14 */ + +static final byte[] ch20data = { +(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch20 = new BitmapCharRec(9,1,0,1,9,ch20data); + +/* char: 0x13 */ + +static final byte[] ch19data = { +(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch19 = new BitmapCharRec(9,1,0,-1,9,ch19data); + +/* char: 0x12 */ + +static final byte[] ch18data = { +(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch18 = new BitmapCharRec(9,1,0,-3,9,ch18data); + +/* char: 0x11 */ + +static final byte[] ch17data = { +(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch17 = new BitmapCharRec(9,1,0,-5,9,ch17data); + +/* char: 0x10 */ + +static final byte[] ch16data = { +(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch16 = new BitmapCharRec(9,1,0,-7,9,ch16data); + +/* char: 0xf */ + +static final byte[] ch15data = { +(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0x8,(byte) 0x0, +(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0, +}; + +static final BitmapCharRec ch15 = new BitmapCharRec(9,15,0,3,9,ch15data); + +/* char: 0xe */ + +static final byte[] ch14data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch14 = new BitmapCharRec(5,9,-4,-3,9,ch14data); + +/* char: 0xd */ + +static final byte[] ch13data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch13 = new BitmapCharRec(5,7,-4,3,9,ch13data); + +/* char: 0xc */ + +static final byte[] ch12data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch12 = new BitmapCharRec(5,7,0,3,9,ch12data); + +/* char: 0xb */ + +static final byte[] ch11data = { +(byte) 0xf8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8, +}; + +static final BitmapCharRec ch11 = new BitmapCharRec(5,9,0,-3,9,ch11data); + +/* char: 0xa */ + +static final byte[] ch10data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x3e,(byte) 0x0,(byte) 0x20,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch10 = new BitmapCharRec(7,10,-1,2,9,ch10data); + +/* char: 0x9 */ + +static final byte[] ch9data = { +(byte) 0x3e,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x88,(byte) 0x98,(byte) 0xa8,(byte) 0xc8,(byte) 0x88, +}; + +static final BitmapCharRec ch9 = new BitmapCharRec(7,10,-1,2,9,ch9data); + +/* char: 0x8 */ + +static final byte[] ch8data = { +(byte) 0xfe,(byte) 0x10,(byte) 0x10,(byte) 0xfe,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch8 = new BitmapCharRec(7,6,-1,0,9,ch8data); + +/* char: 0x7 */ + +static final byte[] ch7data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch7 = new BitmapCharRec(5,4,-2,-6,9,ch7data); + +/* char: 0x6 */ + +static final byte[] ch6data = { +(byte) 0x20,(byte) 0x20,(byte) 0x3c,(byte) 0x20,(byte) 0x3e,(byte) 0x0,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch6 = new BitmapCharRec(7,10,-1,2,9,ch6data); + +/* char: 0x5 */ + +static final byte[] ch5data = { +(byte) 0x22,(byte) 0x22,(byte) 0x3c,(byte) 0x22,(byte) 0x3c,(byte) 0x0,(byte) 0x78,(byte) 0x80,(byte) 0x80,(byte) 0x78, +}; + +static final BitmapCharRec ch5 = new BitmapCharRec(7,10,-1,2,9,ch5data); + +/* char: 0x4 */ + +static final byte[] ch4data = { +(byte) 0x10,(byte) 0x10,(byte) 0x1c,(byte) 0x10,(byte) 0x1e,(byte) 0x80,(byte) 0x80,(byte) 0xe0,(byte) 0x80,(byte) 0xf0, +}; + +static final BitmapCharRec ch4 = new BitmapCharRec(7,10,-1,2,9,ch4data); + +/* char: 0x3 */ + +static final byte[] ch3data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x3e,(byte) 0x0,(byte) 0x88,(byte) 0x88,(byte) 0xf8,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch3 = new BitmapCharRec(7,10,-1,2,9,ch3data); + +/* char: 0x2 */ + +static final byte[] ch2data = { +(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa,(byte) 0x55,(byte) 0xaa, +}; + +static final BitmapCharRec ch2 = new BitmapCharRec(8,14,0,3,9,ch2data); + +/* char: 0x1 */ + +static final byte[] ch1data = { +(byte) 0x10,(byte) 0x38,(byte) 0x7c,(byte) 0xfe,(byte) 0x7c,(byte) 0x38,(byte) 0x10, +}; + +static final BitmapCharRec ch1 = new BitmapCharRec(7,7,-1,0,9,ch1data); + +static final BitmapCharRec[] chars = { +ch0, +ch1, +ch2, +ch3, +ch4, +ch5, +ch6, +ch7, +ch8, +ch9, +ch10, +ch11, +ch12, +ch13, +ch14, +ch15, +ch16, +ch17, +ch18, +ch19, +ch20, +ch21, +ch22, +ch23, +ch24, +ch25, +ch26, +ch27, +ch28, +ch29, +ch30, +ch31, +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +ch127, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmap9By15 = new BitmapFontRec("-misc-fixed-medium-r-normal--15-140-75-75-C-90-iso8859-1", + 256, + 0, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java new file mode 100644 index 000000000..b9c7e6e50 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica10.java @@ -0,0 +1,1798 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmapHelvetica10 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x60,(byte) 0xa0,(byte) 0xa0,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(4,10,0,2,5,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0x80,(byte) 0x80,(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(5,10,0,2,6,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x60,(byte) 0xa0,(byte) 0xa0,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(4,11,0,2,5,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(4,8,0,0,5,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(4,9,0,0,5,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(4,9,0,0,5,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(4,9,0,0,5,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0x70,(byte) 0x88,(byte) 0xc8,(byte) 0xa8,(byte) 0x98,(byte) 0x74, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(6,6,0,0,6,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x20,(byte) 0x0,(byte) 0xf8,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(5,5,0,-1,6,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(5,8,0,0,6,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(5,9,0,0,6,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(5,9,0,0,6,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(5,9,0,0,6,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(5,9,0,0,6,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(4,9,0,0,5,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x90,(byte) 0x60,(byte) 0x50, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(5,9,0,0,6,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(3,8,0,0,2,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(3,9,1,0,2,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(2,9,0,0,2,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(2,9,1,0,2,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(4,8,0,0,5,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(4,9,0,0,5,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(4,9,0,0,5,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(4,9,0,0,5,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x60,(byte) 0x20,(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0x80,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(4,8,0,2,5,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x6c,(byte) 0x92,(byte) 0x90,(byte) 0x7e,(byte) 0x12,(byte) 0xec, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(7,6,0,0,8,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x20,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(5,9,0,0,5,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(5,8,0,0,5,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(5,9,0,0,5,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(5,9,0,0,5,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(5,9,0,0,5,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(5,9,0,0,5,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0xa0,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xa0,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(4,8,0,0,5,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x88,(byte) 0x88,(byte) 0xf0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(5,8,-1,0,7,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(7,11,0,0,7,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x48, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(6,10,-1,0,8,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(6,11,-1,0,8,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(6,11,-1,0,8,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(6,11,-1,0,8,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x80,(byte) 0x78,(byte) 0xc4,(byte) 0xa4,(byte) 0xa4,(byte) 0x94,(byte) 0x94,(byte) 0x8c,(byte) 0x78,(byte) 0x4, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(6,10,-1,1,8,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x88,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0x88, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(5,5,0,-1,6,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x48, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(6,10,-1,0,8,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(6,11,-1,0,8,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(6,11,-1,0,8,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(6,11,-1,0,8,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(6,11,-1,0,8,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0x8c,(byte) 0x8c,(byte) 0x94,(byte) 0x94,(byte) 0xa4,(byte) 0xa4,(byte) 0xc4,(byte) 0xc4,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(6,11,-1,0,8,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0x78,(byte) 0x44,(byte) 0x42,(byte) 0x42,(byte) 0xf2,(byte) 0x42,(byte) 0x44,(byte) 0x78, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(7,8,0,0,8,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(3,10,0,0,3,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(3,11,0,0,3,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(2,11,-1,0,3,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(2,11,0,0,3,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(5,10,-1,0,7,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(5,11,-1,0,7,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(5,11,-1,0,7,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(5,11,-1,0,7,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x30,(byte) 0x10,(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(6,10,-1,2,8,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0x8f,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0x48,(byte) 0x0,(byte) 0x2f,(byte) 0x80,(byte) 0x28,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(9,8,0,0,10,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(7,11,0,0,7,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(7,10,0,0,7,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(7,11,0,0,7,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(7,11,0,0,7,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(7,11,0,0,7,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(7,11,0,0,7,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(4,8,-1,2,6,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x21,(byte) 0x0,(byte) 0x17,(byte) 0x80,(byte) 0x13,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0xc8,(byte) 0x0,(byte) 0x24,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0xe2,(byte) 0x0, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(9,8,0,0,9,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x27,(byte) 0x12,(byte) 0x15,(byte) 0xb,(byte) 0x48,(byte) 0x44,(byte) 0xc4,(byte) 0x42, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(8,8,0,0,9,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x21,(byte) 0x0,(byte) 0x17,(byte) 0x80,(byte) 0x13,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x48,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0xc4,(byte) 0x0,(byte) 0x42,(byte) 0x0, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(9,8,0,0,9,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0xa0,(byte) 0x50,(byte) 0x28,(byte) 0x50,(byte) 0xa0, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(5,5,0,0,6,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xe0,(byte) 0xa0,(byte) 0xe0, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(3,5,0,-3,4,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(2,4,0,-3,3,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(2,2,0,2,3,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0xc0, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(2,1,0,-3,3,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x68,(byte) 0xe8,(byte) 0xe8,(byte) 0xe8,(byte) 0x7c, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(6,10,0,2,6,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(4,8,0,2,5,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(2,2,0,-6,3,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0xe0, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(3,4,0,-3,3,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xe0,(byte) 0x40,(byte) 0xa0,(byte) 0x60, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(3,4,0,-3,3,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(5,7,0,0,6,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(4,4,0,-3,4,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xe0, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(3,1,0,-7,3,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x38,(byte) 0x44,(byte) 0xaa,(byte) 0xb2,(byte) 0xba,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(7,7,-1,0,9,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xe0, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(3,1,0,-3,4,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x8,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(5,3,-1,-2,7,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x28,(byte) 0x50,(byte) 0xa0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(5,5,0,0,6,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x20,(byte) 0xe0, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(3,5,0,-3,4,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x38,(byte) 0x44,(byte) 0x9a,(byte) 0xa2,(byte) 0x9a,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(7,7,-1,0,9,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xa0, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(3,1,0,-7,3,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x70,(byte) 0x88,(byte) 0x18,(byte) 0x70,(byte) 0xc8,(byte) 0x98,(byte) 0x70,(byte) 0xc0,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(5,10,0,2,6,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(1,10,-1,2,3,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0xf8,(byte) 0x50,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(5,8,0,0,6,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0x90,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x90, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(4,6,0,-1,5,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xb0,(byte) 0x48,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(5,8,0,0,6,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x40,(byte) 0x70,(byte) 0xa8,(byte) 0xa0,(byte) 0xa0,(byte) 0xa8,(byte) 0x70,(byte) 0x10, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(5,8,0,1,6,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(1,8,-1,2,3,ch161data); + +/* char: 0xa0 */ + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,3,null); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x98,(byte) 0x64, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(6,2,0,-3,7,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(3,10,0,2,3,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(1,10,-1,2,3,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(3,10,0,2,3,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0xf0, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(4,6,0,0,5,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x60,(byte) 0xa0,(byte) 0xa0,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(4,8,0,2,5,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0x88,(byte) 0x88,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0x88, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(5,6,0,0,6,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x28,(byte) 0x28,(byte) 0x54,(byte) 0x54,(byte) 0x92,(byte) 0x92, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(7,6,0,0,8,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x20,(byte) 0x20,(byte) 0x50,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(5,6,0,0,6,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(4,6,0,0,5,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x60,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(3,8,0,0,4,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x60,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(4,6,0,0,5,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc0,(byte) 0xa0, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(3,6,0,0,4,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x8,(byte) 0x8,(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(5,8,0,2,6,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0x80,(byte) 0x80,(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(5,8,0,2,6,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(5,6,0,0,6,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(5,6,0,0,6,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xec, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(7,6,0,0,8,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(1,8,0,0,2,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0x90,(byte) 0x90,(byte) 0xa0,(byte) 0xc0,(byte) 0xa0,(byte) 0x90,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(4,8,0,0,5,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(1,9,0,1,2,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(1,8,0,0,2,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(5,8,0,0,6,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x70,(byte) 0x8,(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(5,8,0,2,6,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x30, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(4,8,0,0,4,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0xf0,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(4,6,0,0,5,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68,(byte) 0x8,(byte) 0x8, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(5,8,0,0,6,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x60,(byte) 0x90,(byte) 0x80,(byte) 0x80,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(4,6,0,0,5,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(5,8,0,0,6,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0xe0, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(5,6,0,0,5,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0x80,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(2,3,0,-5,3,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xfc, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(6,1,0,2,6,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x88,(byte) 0x50,(byte) 0x50,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(5,5,0,-3,6,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xc0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(2,10,0,2,3,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(3,8,0,0,3,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xc0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(2,10,-1,2,3,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(5,8,-1,0,7,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(7,8,0,0,7,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0x88,(byte) 0x88,(byte) 0x50,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(5,8,-1,0,7,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x88,(byte) 0x80,(byte) 0x88,(byte) 0x80, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(9,8,0,0,9,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(7,8,0,0,7,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(6,8,-1,0,8,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xf8, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(5,8,0,0,5,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x8,(byte) 0x70,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(5,8,-1,0,7,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xf0,(byte) 0x88,(byte) 0x88,(byte) 0xf0, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(5,8,-1,0,7,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x2,(byte) 0x7c,(byte) 0x8c,(byte) 0x94,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(7,9,-1,1,8,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x88,(byte) 0x88,(byte) 0xf0, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(5,8,-1,0,7,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(6,8,-1,0,8,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0x8c,(byte) 0x8c,(byte) 0x94,(byte) 0x94,(byte) 0xa4,(byte) 0xa4,(byte) 0xc4,(byte) 0xc4, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(6,8,-1,0,8,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xaa,(byte) 0xaa,(byte) 0xc6,(byte) 0xc6,(byte) 0x82, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(7,8,-1,0,9,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(4,8,-1,0,6,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0x88,(byte) 0x88,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0xa0,(byte) 0x90,(byte) 0x88, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(5,8,-1,0,7,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(4,8,0,0,5,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(1,8,-1,0,3,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xfc,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(6,8,-1,0,8,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x74,(byte) 0x8c,(byte) 0x84,(byte) 0x8c,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(6,8,-1,0,8,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(5,8,-1,0,6,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(5,8,-1,0,7,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xf0,(byte) 0x88,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x88,(byte) 0xf0, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(6,8,-1,0,8,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x78,(byte) 0x84,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(6,8,-1,0,8,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xf0,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xf0,(byte) 0x88,(byte) 0x88,(byte) 0xf0, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(5,8,-1,0,7,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(7,8,0,0,7,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x40,(byte) 0x0,(byte) 0x9b,(byte) 0x0,(byte) 0xa4,(byte) 0x80,(byte) 0xa4,(byte) 0x80,(byte) 0xa2,(byte) 0x40,(byte) 0x92,(byte) 0x40,(byte) 0x4d,(byte) 0x40, +(byte) 0x20,(byte) 0x80,(byte) 0x1f,(byte) 0x0, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(10,10,0,2,11,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(4,8,-1,0,6,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(3,5,-1,-1,6,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xf0,(byte) 0x0,(byte) 0xf0, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(4,3,0,-2,5,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x20,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(3,5,-1,-1,6,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(2,8,0,2,3,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(1,6,-1,0,3,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(5,8,0,0,6,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(5,8,0,0,6,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(5,8,0,0,6,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(5,8,0,0,6,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(5,8,0,0,6,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x10,(byte) 0x10,(byte) 0xf8,(byte) 0x90,(byte) 0x50,(byte) 0x50,(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(5,8,0,0,6,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(5,8,0,0,6,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x40,(byte) 0x30,(byte) 0x8,(byte) 0x8,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(5,8,0,0,6,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(2,8,-1,0,6,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(5,8,0,0,6,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(3,8,0,0,3,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(1,1,-1,0,3,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xf8, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(5,1,-1,-3,7,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(2,3,0,2,3,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(5,5,0,-1,6,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0xa0,(byte) 0x40,(byte) 0xa0, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(3,3,0,-5,4,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(3,10,-1,2,4,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(3,10,0,2,4,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(2,3,-1,-5,3,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x64,(byte) 0x98,(byte) 0x98,(byte) 0xa4,(byte) 0x60,(byte) 0x50,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(6,8,-1,0,8,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x26,(byte) 0x29,(byte) 0x16,(byte) 0x10,(byte) 0x8,(byte) 0x68,(byte) 0x94,(byte) 0x64, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(8,8,0,0,9,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x20,(byte) 0x70,(byte) 0xa8,(byte) 0x28,(byte) 0x70,(byte) 0xa0,(byte) 0xa8,(byte) 0x70,(byte) 0x20, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(5,9,0,1,6,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x50,(byte) 0x50,(byte) 0xf8,(byte) 0x28,(byte) 0x7c,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(6,7,0,0,6,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0xa0,(byte) 0xa0, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(3,2,-1,-6,4,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(1,8,-1,0,3,ch33data); + +/* char: 0x20 ' ' */ + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,3,null); + +static final BitmapCharRec[] chars = { +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmapHelvetica10 = new BitmapFontRec("-adobe-helvetica-medium-r-normal--10-100-75-75-p-56-iso8859-1", + 224, + 32, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java new file mode 100644 index 000000000..bc86f6216 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica12.java @@ -0,0 +1,1808 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmapHelvetica12 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x30,(byte) 0x50,(byte) 0x50,(byte) 0x48,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(5,12,-1,3,7,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(5,12,-1,3,7,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x50,(byte) 0x50,(byte) 0x90,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(5,13,-1,3,7,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(5,9,-1,0,7,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(5,10,-1,0,7,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(5,10,-1,0,7,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(5,10,-1,0,7,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0xb8,(byte) 0x44,(byte) 0x64,(byte) 0x54,(byte) 0x4c,(byte) 0x44,(byte) 0x3a, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(7,7,0,0,7,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x20,(byte) 0x0,(byte) 0xf8,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(5,5,-1,-1,7,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(5,9,-1,0,7,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(5,10,-1,0,7,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(5,10,-1,0,7,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(5,10,-1,0,7,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(5,10,-1,0,7,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(5,10,-1,0,7,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x50,(byte) 0x30,(byte) 0x68, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(5,10,-1,0,7,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(3,9,0,0,3,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(3,10,0,0,3,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(2,10,-1,0,3,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(2,10,0,0,3,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0xf8,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(5,9,-1,0,7,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0xf8,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(5,10,-1,0,7,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0xf8,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(5,10,-1,0,7,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0xf8,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(5,10,-1,0,7,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x60,(byte) 0x10,(byte) 0x20,(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(5,10,-1,3,7,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x77,(byte) 0x0,(byte) 0x88,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x7f,(byte) 0x80,(byte) 0x8,(byte) 0x80,(byte) 0x88,(byte) 0x80,(byte) 0x77,(byte) 0x0, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(9,7,-1,0,11,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x30,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(6,10,-1,0,7,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(6,9,-1,0,7,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(6,10,-1,0,7,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(6,10,-1,0,7,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(6,10,-1,0,7,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(6,10,-1,0,7,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0xb0,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xb0,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(5,9,-1,0,7,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(6,9,-1,0,8,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(7,12,-1,0,9,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x48, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(6,11,-1,0,8,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(6,12,-1,0,8,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(6,12,-1,0,8,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(6,12,-1,0,8,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x80,(byte) 0x0,(byte) 0x5e,(byte) 0x0,(byte) 0x21,(byte) 0x0,(byte) 0x50,(byte) 0x80,(byte) 0x48,(byte) 0x80,(byte) 0x44,(byte) 0x80,(byte) 0x44,(byte) 0x80,(byte) 0x42,(byte) 0x80, +(byte) 0x21,(byte) 0x0,(byte) 0x1e,(byte) 0x80,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(10,11,0,1,10,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x88,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0x88, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(5,5,-1,-1,7,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c,(byte) 0x0,(byte) 0x24, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(8,11,-1,0,10,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(8,12,-1,0,10,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c,(byte) 0x0,(byte) 0x14,(byte) 0x8, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(8,12,-1,0,10,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c,(byte) 0x0,(byte) 0x8,(byte) 0x4, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(8,12,-1,0,10,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c,(byte) 0x0,(byte) 0x8,(byte) 0x10, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(8,12,-1,0,10,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0x82,(byte) 0x86,(byte) 0x8a,(byte) 0x8a,(byte) 0x92,(byte) 0xa2,(byte) 0xa2,(byte) 0xc2,(byte) 0x82,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(7,12,-1,0,9,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0x7c,(byte) 0x42,(byte) 0x41,(byte) 0x41,(byte) 0xf1,(byte) 0x41,(byte) 0x41,(byte) 0x42,(byte) 0x7c, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(8,9,0,0,9,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(3,11,0,0,3,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(3,12,0,0,3,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(2,12,-1,0,3,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(2,12,0,0,3,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x28, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(6,11,-1,0,8,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(6,12,-1,0,8,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(6,12,-1,0,8,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(6,12,-1,0,8,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x30,(byte) 0x8,(byte) 0x8,(byte) 0x3c,(byte) 0x42,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(7,12,-1,3,9,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0x8f,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x88,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0x4f,(byte) 0x80,(byte) 0x48,(byte) 0x0,(byte) 0x28,(byte) 0x0,(byte) 0x28,(byte) 0x0, +(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(9,9,-1,0,11,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(7,12,-1,0,9,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(7,11,-1,0,9,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(7,12,-1,0,9,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(7,12,-1,0,9,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(7,12,-1,0,9,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(7,12,-1,0,9,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(5,9,-1,3,7,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x21,(byte) 0x0,(byte) 0x17,(byte) 0x80,(byte) 0x15,(byte) 0x0,(byte) 0xb,(byte) 0x0,(byte) 0xc9,(byte) 0x0,(byte) 0x24,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0x22,(byte) 0x0, +(byte) 0xe1,(byte) 0x0, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(9,9,0,0,10,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x47,(byte) 0x80,(byte) 0x22,(byte) 0x0,(byte) 0x11,(byte) 0x0,(byte) 0x14,(byte) 0x80,(byte) 0x4b,(byte) 0x0,(byte) 0x48,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0xc2,(byte) 0x0, +(byte) 0x41,(byte) 0x0, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(9,9,0,0,10,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x41,(byte) 0x0,(byte) 0x27,(byte) 0x80,(byte) 0x15,(byte) 0x0,(byte) 0x13,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0x44,(byte) 0x0,(byte) 0xc2,(byte) 0x0, +(byte) 0x41,(byte) 0x0, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(9,9,0,0,10,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0xa0,(byte) 0x50,(byte) 0x28,(byte) 0x50,(byte) 0xa0, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(5,5,-1,-1,7,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xe0,(byte) 0xa0,(byte) 0xe0, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(3,5,-1,-4,5,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(2,5,-1,-3,4,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(3,4,0,3,3,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(1,1,-1,-3,3,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x68,(byte) 0xe8,(byte) 0xe8,(byte) 0xe8,(byte) 0x68,(byte) 0x3c, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(6,12,0,3,7,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xe8,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(5,10,-1,3,7,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(2,2,0,-8,2,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x20,(byte) 0xe0, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(3,5,0,-3,4,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xf0,(byte) 0x40,(byte) 0x20,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(4,5,0,-3,4,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(5,7,-1,0,7,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(4,4,0,-4,5,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xf0, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(4,1,0,-8,4,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x41,(byte) 0x0,(byte) 0x94,(byte) 0x80,(byte) 0x94,(byte) 0x80,(byte) 0x98,(byte) 0x80,(byte) 0x94,(byte) 0x80,(byte) 0x9c,(byte) 0x80,(byte) 0x41,(byte) 0x0, +(byte) 0x3e,(byte) 0x0, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(9,9,-1,0,11,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xf0, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(4,1,0,-3,5,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x4,(byte) 0x4,(byte) 0x4,(byte) 0xfc, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(6,4,-1,-2,8,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x28,(byte) 0x50,(byte) 0xa0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(5,5,-1,-1,7,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x20,(byte) 0xe0, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(3,5,-1,-4,5,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x41,(byte) 0x0,(byte) 0x9c,(byte) 0x80,(byte) 0xa2,(byte) 0x80,(byte) 0xa0,(byte) 0x80,(byte) 0xa2,(byte) 0x80,(byte) 0x9c,(byte) 0x80,(byte) 0x41,(byte) 0x0, +(byte) 0x3e,(byte) 0x0, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(9,9,-1,0,11,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xa0, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(3,1,0,-8,3,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x30,(byte) 0x48,(byte) 0x88,(byte) 0x88,(byte) 0x90,(byte) 0x60,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(5,12,0,3,6,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(1,11,-1,2,3,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x50,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(5,9,-1,0,7,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0x84,(byte) 0x78,(byte) 0x48,(byte) 0x48,(byte) 0x78,(byte) 0x84, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(6,6,0,-1,7,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xb0,(byte) 0x48,(byte) 0x20,(byte) 0x20,(byte) 0xf0,(byte) 0x40,(byte) 0x40,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(5,9,-1,0,7,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x40,(byte) 0x70,(byte) 0xc8,(byte) 0xa0,(byte) 0xa0,(byte) 0xa0,(byte) 0xa8,(byte) 0x70,(byte) 0x10, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(5,9,-1,1,7,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(1,10,-1,3,3,ch161data); + +/* char: 0xa0 */ + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,4,null); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x98,(byte) 0x64, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(6,2,0,-3,7,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xc0, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(4,12,0,3,4,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(1,12,-1,3,3,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x30,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x30, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(4,12,0,3,4,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xf0,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0xf0, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(4,7,-1,0,6,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x50,(byte) 0x50,(byte) 0x90,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(5,10,-1,3,7,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0x84,(byte) 0x84,(byte) 0x48,(byte) 0x30,(byte) 0x30,(byte) 0x48,(byte) 0x84, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(6,7,0,0,6,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x88,(byte) 0x80,(byte) 0x88,(byte) 0x80, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(9,7,0,0,9,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x20,(byte) 0x20,(byte) 0x50,(byte) 0x50,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(5,7,-1,0,7,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(5,7,-1,0,7,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x60,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(3,9,0,0,3,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0x60,(byte) 0x90,(byte) 0x10,(byte) 0x60,(byte) 0x80,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(4,7,-1,0,6,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc0,(byte) 0xa0, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(3,7,-1,0,4,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(5,10,-1,3,7,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(5,10,-1,3,7,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(5,7,-1,0,7,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(5,7,-1,0,7,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xda,(byte) 0xa4, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(7,7,-1,0,9,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(1,9,-1,0,3,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0x88,(byte) 0x90,(byte) 0xa0,(byte) 0xc0,(byte) 0xc0,(byte) 0xa0,(byte) 0x90,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(5,9,-1,0,6,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(2,12,0,3,3,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(1,9,-1,0,3,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(5,9,-1,0,7,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(5,10,-1,3,7,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x30, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(4,9,0,0,3,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0xf8,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(5,7,-1,0,7,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x68,(byte) 0x98,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x98,(byte) 0x68,(byte) 0x8,(byte) 0x8, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(5,9,-1,0,7,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x70,(byte) 0x88,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(5,7,-1,0,7,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xb0,(byte) 0xc8,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(5,9,-1,0,7,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x74,(byte) 0x88,(byte) 0x88,(byte) 0x78,(byte) 0x8,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(6,7,-1,0,7,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0xc0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(2,3,0,-6,3,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xfe, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(7,1,0,2,7,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x88,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(5,3,0,-5,6,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xc0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(2,12,0,3,3,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x10,(byte) 0x10,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(4,9,0,0,4,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xc0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(2,12,-1,3,3,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xfe,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x4,(byte) 0x2,(byte) 0xfe, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(7,9,-1,0,9,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(7,9,-1,0,9,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0x82,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x82, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(7,9,-1,0,9,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x49,(byte) 0x0,(byte) 0x88,(byte) 0x80,(byte) 0x88,(byte) 0x80, +(byte) 0x88,(byte) 0x80, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(9,9,-1,0,11,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(7,9,-1,0,9,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x84, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(6,9,-1,0,8,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0xfe, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(7,9,0,0,7,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x78,(byte) 0x84,(byte) 0x84,(byte) 0x4,(byte) 0x18,(byte) 0x60,(byte) 0x80,(byte) 0x84,(byte) 0x78, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(6,9,-1,0,8,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0x88,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(6,9,-1,0,8,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x3d,(byte) 0x42,(byte) 0x85,(byte) 0x89,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(8,9,-1,0,10,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(6,9,-1,0,8,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x81,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(8,9,-1,0,10,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0x82,(byte) 0x86,(byte) 0x8a,(byte) 0x8a,(byte) 0x92,(byte) 0xa2,(byte) 0xa2,(byte) 0xc2,(byte) 0x82, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(7,9,-1,0,9,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0x88,(byte) 0x80,(byte) 0x88,(byte) 0x80,(byte) 0x94,(byte) 0x80,(byte) 0x94,(byte) 0x80,(byte) 0xa2,(byte) 0x80,(byte) 0xa2,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80, +(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(9,9,-1,0,11,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(5,9,-1,0,7,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0x82,(byte) 0x84,(byte) 0x88,(byte) 0x90,(byte) 0xe0,(byte) 0xa0,(byte) 0x90,(byte) 0x88,(byte) 0x84, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(7,9,-1,0,8,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8,(byte) 0x8, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(5,9,-1,0,7,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(1,9,-1,0,3,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0xfe,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(7,9,-1,0,9,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x3a,(byte) 0x46,(byte) 0x82,(byte) 0x82,(byte) 0x8e,(byte) 0x80,(byte) 0x80,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(7,9,-1,0,9,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(6,9,-1,0,8,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xfc, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(6,9,-1,0,8,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xf8,(byte) 0x84,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(7,9,-1,0,9,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x3c,(byte) 0x42,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(7,9,-1,0,9,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xf8, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(6,9,-1,0,8,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0x28,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(7,9,-1,0,9,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x40,(byte) 0x0,(byte) 0x9b,(byte) 0x0,(byte) 0xa6,(byte) 0x80,(byte) 0xa2,(byte) 0x40,(byte) 0xa2,(byte) 0x40,(byte) 0x92,(byte) 0x40,(byte) 0x4d,(byte) 0x40, +(byte) 0x60,(byte) 0x80,(byte) 0x1f,(byte) 0x0, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(10,10,-1,1,12,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x20,(byte) 0x0,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(5,9,-1,0,7,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0xc0, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(6,5,-1,-1,7,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xf8,(byte) 0x0,(byte) 0xf8, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(5,3,-1,-2,7,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0xc,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(6,5,0,-1,7,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(2,8,0,2,3,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(1,6,-1,0,3,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x78,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(5,9,-1,0,7,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(5,9,-1,0,7,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x10,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(5,9,-1,0,7,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0xc8,(byte) 0xb0,(byte) 0x80,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(5,9,-1,0,7,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0xf0,(byte) 0x80,(byte) 0x80,(byte) 0xf8, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(5,9,-1,0,7,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x8,(byte) 0x8,(byte) 0xfc,(byte) 0x88,(byte) 0x48,(byte) 0x28,(byte) 0x28,(byte) 0x18,(byte) 0x8, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(6,9,0,0,7,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x8,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(5,9,-1,0,7,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xf8,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x8,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(5,9,-1,0,7,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xe0,(byte) 0x20, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(3,9,-1,0,7,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x70,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x88,(byte) 0x70, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(5,9,-1,0,7,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x10, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(4,9,0,0,4,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(1,1,-1,0,3,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xf8, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(5,1,-1,-3,8,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(2,3,-1,2,4,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(5,5,-1,-1,7,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0xa0,(byte) 0x40,(byte) 0xa0, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(3,3,-1,-6,5,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(3,12,0,3,4,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(3,12,-1,3,4,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x80,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(2,3,-1,-6,3,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x72,(byte) 0x8c,(byte) 0x84,(byte) 0x8a,(byte) 0x50,(byte) 0x30,(byte) 0x48,(byte) 0x48,(byte) 0x30, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(7,9,-1,0,9,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x23,(byte) 0x0,(byte) 0x14,(byte) 0x80,(byte) 0x14,(byte) 0x80,(byte) 0x13,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x68,(byte) 0x0,(byte) 0x94,(byte) 0x0,(byte) 0x94,(byte) 0x0, +(byte) 0x62,(byte) 0x0, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(9,9,-1,0,11,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x20,(byte) 0x70,(byte) 0xa8,(byte) 0xa8,(byte) 0x28,(byte) 0x70,(byte) 0xa0,(byte) 0xa8,(byte) 0x70,(byte) 0x20, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(5,10,-1,1,7,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x50,(byte) 0x50,(byte) 0x50,(byte) 0xfc,(byte) 0x28,(byte) 0xfc,(byte) 0x28,(byte) 0x28, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(6,8,0,0,7,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0xa0,(byte) 0xa0,(byte) 0xa0, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(3,3,-1,-6,5,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(1,9,-1,0,3,ch33data); + +/* char: 0x20 ' ' */ + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,4,null); + +static final BitmapCharRec[] chars = { +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmapHelvetica12 = new BitmapFontRec("-adobe-helvetica-medium-r-normal--12-120-75-75-p-67-iso8859-1", + 224, + 32, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java new file mode 100644 index 000000000..1b2e69ba4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapHelvetica18.java @@ -0,0 +1,1917 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmapHelvetica18 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0x70,(byte) 0x70,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x3c,(byte) 0x24,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0x66, +(byte) 0x66, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(8,17,-1,4,10,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xde,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xe3,(byte) 0x0,(byte) 0xc1,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xe3,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xde,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(9,18,-1,4,11,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x70,(byte) 0x70,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x3c,(byte) 0x24,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0x18, +(byte) 0xc,(byte) 0x6, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(8,18,-1,4,10,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x73,(byte) 0xfb,(byte) 0xc7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0x66,(byte) 0x66, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(8,13,-1,0,10,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x73,(byte) 0xfb,(byte) 0xc7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0x66,(byte) 0x3c,(byte) 0x18, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(8,14,-1,0,10,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x73,(byte) 0xfb,(byte) 0xc7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x6, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(8,14,-1,0,10,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x73,(byte) 0xfb,(byte) 0xc7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x30, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(8,14,-1,0,10,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0xce,(byte) 0x0,(byte) 0x7f,(byte) 0x80,(byte) 0x31,(byte) 0x80,(byte) 0x78,(byte) 0xc0,(byte) 0x6c,(byte) 0xc0,(byte) 0x66,(byte) 0xc0,(byte) 0x63,(byte) 0xc0,(byte) 0x31,(byte) 0x80, +(byte) 0x3f,(byte) 0xc0,(byte) 0xe,(byte) 0x60, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(11,10,0,0,11,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x18,(byte) 0x18,(byte) 0x0,(byte) 0xff,(byte) 0xff,(byte) 0x0,(byte) 0x18,(byte) 0x18, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(8,8,-1,-1,10,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x36,(byte) 0x0,(byte) 0x36,(byte) 0x0, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(9,13,-1,0,11,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x26,(byte) 0x0,(byte) 0x2d,(byte) 0x0,(byte) 0x19,(byte) 0x0, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(9,14,-1,0,11,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(9,14,-1,0,11,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(9,14,-1,0,11,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(9,14,-1,0,11,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xe3,(byte) 0xdf,(byte) 0xce,(byte) 0x0,(byte) 0x4c,(byte) 0x5a,(byte) 0x32, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(8,14,-1,0,10,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x4c,(byte) 0x0,(byte) 0x38,(byte) 0x0,(byte) 0x36,(byte) 0x0,(byte) 0x60,(byte) 0x0, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(9,14,-1,0,11,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x0,(byte) 0xd8,(byte) 0xd8, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(5,13,0,0,4,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0xcc,(byte) 0x78,(byte) 0x30, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(6,14,1,0,4,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x0,(byte) 0xc0,(byte) 0x60,(byte) 0x30, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(4,14,0,0,4,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x0,(byte) 0x30,(byte) 0x60,(byte) 0xc0, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(4,14,0,0,4,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x3c,(byte) 0x7f,(byte) 0xe3,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c,(byte) 0x0,(byte) 0x36,(byte) 0x36, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(8,13,-1,0,10,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x3c,(byte) 0x7f,(byte) 0xe3,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c,(byte) 0x0,(byte) 0x66,(byte) 0x3c,(byte) 0x18, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(8,14,-1,0,10,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x3c,(byte) 0x7f,(byte) 0xe3,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x6, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(8,14,-1,0,10,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x3c,(byte) 0x7f,(byte) 0xe3,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c,(byte) 0x0,(byte) 0x18,(byte) 0x30,(byte) 0x60, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(8,14,-1,0,10,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x78,(byte) 0x6c,(byte) 0xc,(byte) 0x38,(byte) 0x3e,(byte) 0x7f,(byte) 0x63,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x63,(byte) 0x7f,(byte) 0x3e, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(8,14,-1,4,10,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x75,(byte) 0xe0,(byte) 0xef,(byte) 0xf8,(byte) 0xc7,(byte) 0x18,(byte) 0xc6,(byte) 0x0,(byte) 0xe6,(byte) 0x0,(byte) 0x7f,(byte) 0xf8,(byte) 0xe,(byte) 0x18,(byte) 0xc6,(byte) 0x18, +(byte) 0xef,(byte) 0xf0,(byte) 0x7d,(byte) 0xe0, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(13,10,-1,0,15,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x38,(byte) 0x6c,(byte) 0x6c,(byte) 0x38, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(7,14,-1,0,9,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x0,(byte) 0x6c,(byte) 0x6c, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(7,13,-1,0,9,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x0,(byte) 0x4c,(byte) 0x5a,(byte) 0x32, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(7,14,-1,0,9,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x0,(byte) 0x66,(byte) 0x3c,(byte) 0x18, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(7,14,-1,0,9,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x0,(byte) 0x30,(byte) 0x18,(byte) 0xc, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(7,14,-1,0,9,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c,(byte) 0x0,(byte) 0x18,(byte) 0x30,(byte) 0x60, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(7,14,-1,0,9,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0xdc,(byte) 0xde,(byte) 0xc6,(byte) 0xc6,(byte) 0xc6,(byte) 0xc6,(byte) 0xdc,(byte) 0xdc,(byte) 0xc6,(byte) 0xc6,(byte) 0xc6,(byte) 0xc6,(byte) 0x7c,(byte) 0x38, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(7,14,-1,0,9,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xc1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc1,(byte) 0xc0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(10,14,-1,0,12,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(12,18,-1,0,14,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x1f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0x19,(byte) 0x80, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(11,17,-1,0,13,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x1f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(11,18,-1,0,13,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x1f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0xc,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(11,18,-1,0,13,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x1f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0x0, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(11,18,-1,0,13,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0xc7,(byte) 0xc0,(byte) 0xff,(byte) 0xf0,(byte) 0x78,(byte) 0x38,(byte) 0x38,(byte) 0x18,(byte) 0x6c,(byte) 0x1c,(byte) 0x6e,(byte) 0xc,(byte) 0x67,(byte) 0xc,(byte) 0x63,(byte) 0x8c, +(byte) 0x61,(byte) 0xcc,(byte) 0x70,(byte) 0xdc,(byte) 0x30,(byte) 0x78,(byte) 0x38,(byte) 0x38,(byte) 0x1f,(byte) 0xfc,(byte) 0x7,(byte) 0xcc, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(14,14,0,0,15,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x61,(byte) 0x80, +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(10,9,0,0,10,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0xd,(byte) 0x80, +(byte) 0xd,(byte) 0x80, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(13,17,-1,0,15,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x9,(byte) 0x80, +(byte) 0xb,(byte) 0x40,(byte) 0x6,(byte) 0x40, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(13,18,-1,0,15,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0xc,(byte) 0xc0, +(byte) 0x7,(byte) 0x80,(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(13,18,-1,0,15,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x3,(byte) 0x0, +(byte) 0x1,(byte) 0x80,(byte) 0x0,(byte) 0xc0, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(13,18,-1,0,15,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x3,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(13,18,-1,0,15,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe0,(byte) 0xc1,(byte) 0xe0,(byte) 0xc1,(byte) 0xe0,(byte) 0xc3,(byte) 0x60,(byte) 0xc6,(byte) 0x60,(byte) 0xc6,(byte) 0x60,(byte) 0xcc,(byte) 0x60, +(byte) 0xcc,(byte) 0x60,(byte) 0xd8,(byte) 0x60,(byte) 0xd8,(byte) 0x60,(byte) 0xf0,(byte) 0x60,(byte) 0xe0,(byte) 0x60,(byte) 0xe0,(byte) 0x60,(byte) 0x0,(byte) 0x0,(byte) 0x13,(byte) 0x0, +(byte) 0x16,(byte) 0x80,(byte) 0xc,(byte) 0x80, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(11,18,-1,0,13,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0x7f,(byte) 0x80,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xe0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0xfc,(byte) 0x30,(byte) 0xfc,(byte) 0x30, +(byte) 0x60,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xe0,(byte) 0x7f,(byte) 0xc0,(byte) 0x7f,(byte) 0x80, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(12,14,0,0,13,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0xcc, +(byte) 0xcc, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(6,17,0,0,6,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0xcc, +(byte) 0x78,(byte) 0x30, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(6,18,0,0,6,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0, +(byte) 0x60,(byte) 0x30, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(4,18,-2,0,6,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0x30, +(byte) 0x60,(byte) 0xc0, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(4,18,0,0,6,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0, +(byte) 0x33,(byte) 0x0, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(9,17,-1,0,11,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0, +(byte) 0x1e,(byte) 0x0,(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(9,18,-1,0,11,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0xc,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(9,18,-1,0,11,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0xc,(byte) 0x0, +(byte) 0x18,(byte) 0x0,(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(9,18,-1,0,11,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x1b,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30, +(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70, +(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(12,18,-1,4,14,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0xc1,(byte) 0xff,(byte) 0xc1,(byte) 0xff,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x3f,(byte) 0x80,(byte) 0x31,(byte) 0xfe,(byte) 0x31,(byte) 0xfe, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xd,(byte) 0x80,(byte) 0xd,(byte) 0x80,(byte) 0x7,(byte) 0xff,(byte) 0x7,(byte) 0xff, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(16,14,-1,0,18,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(12,18,0,0,12,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0x19,(byte) 0x80, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(12,17,0,0,12,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x13,(byte) 0x0, +(byte) 0x16,(byte) 0x80,(byte) 0xc,(byte) 0x80, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(12,18,0,0,12,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(12,18,0,0,12,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(12,18,0,0,12,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0x0, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(12,18,0,0,12,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x7c,(byte) 0xfe,(byte) 0xc6,(byte) 0xc6,(byte) 0xe0,(byte) 0x70,(byte) 0x38,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x0,(byte) 0x0,(byte) 0x18,(byte) 0x18, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(7,14,-1,4,10,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xc,(byte) 0xfc,(byte) 0x6,(byte) 0xd8,(byte) 0x6,(byte) 0x78,(byte) 0x73,(byte) 0x38,(byte) 0xf9,(byte) 0x18,(byte) 0x99,(byte) 0x88, +(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x98,(byte) 0x60,(byte) 0xf8,(byte) 0x30,(byte) 0x70,(byte) 0x30, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(14,13,0,0,15,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x30,(byte) 0xf8,(byte) 0x30,(byte) 0xf8,(byte) 0x18,(byte) 0x60,(byte) 0xc,(byte) 0x30,(byte) 0xc,(byte) 0x18,(byte) 0x66,(byte) 0x98,(byte) 0x62,(byte) 0xf8,(byte) 0x63,(byte) 0x70, +(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xe0,(byte) 0xc0,(byte) 0xe0,(byte) 0x60,(byte) 0x60,(byte) 0x60, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(13,13,-1,0,15,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x19,(byte) 0xf8,(byte) 0xd,(byte) 0xb0,(byte) 0xc,(byte) 0xf0,(byte) 0x66,(byte) 0x70,(byte) 0x62,(byte) 0x30,(byte) 0x63,(byte) 0x10, +(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xe0,(byte) 0xc0,(byte) 0xe0,(byte) 0x60,(byte) 0x60,(byte) 0x60, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(13,13,-1,0,15,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0x90,(byte) 0xd8,(byte) 0x6c,(byte) 0x36,(byte) 0x36,(byte) 0x6c,(byte) 0xd8,(byte) 0x90, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(7,8,-1,-1,9,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x70,(byte) 0xd8,(byte) 0x88,(byte) 0x88,(byte) 0xd8,(byte) 0x70, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(5,8,-1,-6,7,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xe0,(byte) 0xe0,(byte) 0x60, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(3,8,-1,-5,6,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0xf0,(byte) 0xd8,(byte) 0x18,(byte) 0x70,(byte) 0x60, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(5,5,0,4,5,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(2,2,-1,-4,4,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x12,(byte) 0x32,(byte) 0x72,(byte) 0xf2,(byte) 0xf2,(byte) 0xf2,(byte) 0xf2, +(byte) 0x72,(byte) 0x3f, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(8,18,-1,4,10,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xdb,(byte) 0xff,(byte) 0xe7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(8,14,-1,4,10,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0xc0,(byte) 0x60,(byte) 0x30, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(4,3,0,-11,4,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0x70,(byte) 0xf8,(byte) 0x98,(byte) 0x30,(byte) 0x30,(byte) 0x98,(byte) 0xf8,(byte) 0x70, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(5,8,0,-5,6,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xf8,(byte) 0xf8,(byte) 0x60,(byte) 0x30,(byte) 0x18,(byte) 0x98,(byte) 0xf8,(byte) 0x70, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(5,8,0,-5,6,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xff,(byte) 0xff,(byte) 0x0,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xff,(byte) 0xff,(byte) 0x18,(byte) 0x18,(byte) 0x18, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(8,11,-1,0,10,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x70,(byte) 0xd8,(byte) 0x88,(byte) 0xd8,(byte) 0x70, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(5,5,-1,-8,7,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xf8, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(5,1,0,-12,5,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0xf,(byte) 0x80,(byte) 0x30,(byte) 0x60,(byte) 0x40,(byte) 0x10,(byte) 0x48,(byte) 0x50,(byte) 0x88,(byte) 0x88,(byte) 0x89,(byte) 0x8,(byte) 0x8f,(byte) 0x88,(byte) 0x88,(byte) 0x48, +(byte) 0x88,(byte) 0x48,(byte) 0x4f,(byte) 0x90,(byte) 0x40,(byte) 0x10,(byte) 0x30,(byte) 0x60,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(13,13,-1,0,14,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xf8,(byte) 0xf8, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(5,2,-1,-4,7,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(9,5,-1,-3,11,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x12,(byte) 0x36,(byte) 0x6c,(byte) 0xd8,(byte) 0xd8,(byte) 0x6c,(byte) 0x36,(byte) 0x12, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(7,8,-1,-1,9,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x68,(byte) 0xd8,(byte) 0x48,(byte) 0x38,(byte) 0xc8,(byte) 0x70, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(5,8,-1,-6,7,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0xf,(byte) 0x80,(byte) 0x30,(byte) 0x60,(byte) 0x40,(byte) 0x10,(byte) 0x47,(byte) 0x10,(byte) 0x88,(byte) 0x88,(byte) 0x90,(byte) 0x8,(byte) 0x90,(byte) 0x8,(byte) 0x90,(byte) 0x8, +(byte) 0x88,(byte) 0x88,(byte) 0x47,(byte) 0x10,(byte) 0x40,(byte) 0x10,(byte) 0x30,(byte) 0x60,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(13,13,-1,0,15,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xd8,(byte) 0xd8, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(5,2,0,-11,6,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0xc3,(byte) 0xc3,(byte) 0x7,(byte) 0xe,(byte) 0x3e,(byte) 0x73,(byte) 0xe3,(byte) 0xc3,(byte) 0xc7,(byte) 0x6e,(byte) 0x7c,(byte) 0xf0,(byte) 0xc3,(byte) 0xc3, +(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(8,18,-1,4,10,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(2,17,-1,3,4,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xff,(byte) 0x18,(byte) 0xff,(byte) 0x3c,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xc3,(byte) 0xc3, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(8,13,-1,0,10,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0xc3,(byte) 0xff,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xff,(byte) 0xc3, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(8,7,-1,-3,10,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xdf,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x30,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x7e,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0x60,(byte) 0x0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x3f,(byte) 0x0,(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(9,13,0,0,10,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x10,(byte) 0x10,(byte) 0x3e,(byte) 0x7f,(byte) 0x6b,(byte) 0xc8,(byte) 0xc8,(byte) 0xc8,(byte) 0xc8,(byte) 0x6b,(byte) 0x7f,(byte) 0x3e,(byte) 0x4,(byte) 0x4, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(8,14,-1,2,10,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(2,14,-2,4,6,ch161data); + +/* char: 0xa0 */ + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,5,null); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0xcc,(byte) 0x7e,(byte) 0x33, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(8,3,-1,-4,10,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0xc0,(byte) 0x60,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18,(byte) 0xc,(byte) 0x18,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0x60,(byte) 0xc0, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(6,18,0,4,6,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(2,18,-1,4,4,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0xc,(byte) 0x18,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0x18,(byte) 0xc, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(6,18,0,4,6,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xfe,(byte) 0xfe,(byte) 0xc0,(byte) 0x60,(byte) 0x30,(byte) 0x18,(byte) 0xc,(byte) 0x6,(byte) 0xfe,(byte) 0xfe, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(7,10,-1,0,9,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x70,(byte) 0x70,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x3c,(byte) 0x24,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(8,14,-1,4,10,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0xc3,(byte) 0xe7,(byte) 0x66,(byte) 0x3c,(byte) 0x18,(byte) 0x18,(byte) 0x3c,(byte) 0x66,(byte) 0xe7,(byte) 0xc3, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(8,10,-1,0,10,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0x39,(byte) 0xc0,(byte) 0x29,(byte) 0x40,(byte) 0x69,(byte) 0x60,(byte) 0x66,(byte) 0x60,(byte) 0x66,(byte) 0x60,(byte) 0xc6,(byte) 0x30, +(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(12,10,-1,0,14,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x18,(byte) 0x18,(byte) 0x3c,(byte) 0x24,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(8,10,-1,0,10,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x73,(byte) 0xfb,(byte) 0xc7,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(8,10,-1,0,10,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x18,(byte) 0x38,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0xfc,(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x30, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(6,13,0,0,6,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0x78,(byte) 0xfc,(byte) 0xc6,(byte) 0x6,(byte) 0x3e,(byte) 0xfc,(byte) 0xc0,(byte) 0xc6,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(7,10,-1,0,9,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xe0,(byte) 0xd8,(byte) 0xd8, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(5,10,-1,0,6,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x3d,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0xc1,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x3d,(byte) 0x80, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(9,14,-1,4,11,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xde,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xe3,(byte) 0x0,(byte) 0xc1,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xe3,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xde,(byte) 0x0, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(9,14,-1,4,11,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x0, +(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(9,10,-1,0,11,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xe3,(byte) 0xdf,(byte) 0xce, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(8,10,-1,0,10,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xc6,(byte) 0x30,(byte) 0xe7,(byte) 0x30, +(byte) 0xde,(byte) 0xf0,(byte) 0xcc,(byte) 0x60, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(12,10,-1,0,14,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(2,14,-1,0,4,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0xc7,(byte) 0xc6,(byte) 0xce,(byte) 0xcc,(byte) 0xd8,(byte) 0xf8,(byte) 0xf0,(byte) 0xd8,(byte) 0xcc,(byte) 0xc6,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(8,14,-1,0,9,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0xe0,(byte) 0xf0,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0x0, +(byte) 0x30,(byte) 0x30, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(4,18,1,4,4,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(2,14,-1,0,4,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xe3,(byte) 0xdf,(byte) 0xce,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(8,14,-1,0,10,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x1c,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x3d,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0xc1,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x3d,(byte) 0x80, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(9,14,-1,4,11,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0xfc,(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x3c,(byte) 0x1c, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(6,14,0,0,6,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x3c,(byte) 0x7f,(byte) 0xe3,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(8,10,-1,0,10,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x3d,(byte) 0x80,(byte) 0x7f,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x63,(byte) 0x80, +(byte) 0x7f,(byte) 0x80,(byte) 0x3d,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(9,14,-1,0,11,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x3e,(byte) 0x7f,(byte) 0x63,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x63,(byte) 0x7f,(byte) 0x3e, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(8,10,-1,0,10,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xde,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xe3,(byte) 0x0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xe3,(byte) 0x0, +(byte) 0xff,(byte) 0x0,(byte) 0xde,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(9,14,-1,0,11,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x76,(byte) 0xee,(byte) 0xc6,(byte) 0xc6,(byte) 0xe6,(byte) 0x7e,(byte) 0xe,(byte) 0xc6,(byte) 0xee,(byte) 0x7c, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(7,10,-1,0,9,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x80,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(2,5,-1,-9,4,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(10,2,0,4,10,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x82,(byte) 0xc6,(byte) 0x6c,(byte) 0x38,(byte) 0x10, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(7,5,-1,-8,9,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xf0,(byte) 0xf0,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0xf0,(byte) 0xf0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(4,18,0,4,5,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x18,(byte) 0x18,(byte) 0x10,(byte) 0x10,(byte) 0x30,(byte) 0x30,(byte) 0x20,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(5,14,0,0,5,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xf0,(byte) 0xf0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xf0,(byte) 0xf0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(4,18,-1,4,5,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0xc,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x0,(byte) 0xc0,(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(10,14,-1,0,12,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x19,(byte) 0x80, +(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(12,14,-1,0,14,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0xc0,(byte) 0x60,(byte) 0xe0,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x31,(byte) 0x80,(byte) 0x1b,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x1b,(byte) 0x0,(byte) 0x31,(byte) 0x80,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe0,(byte) 0xe0,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(11,14,-1,0,13,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x1c,(byte) 0x38,(byte) 0x34,(byte) 0x2c,(byte) 0x36,(byte) 0x6c,(byte) 0x36,(byte) 0x6c,(byte) 0x66,(byte) 0x66,(byte) 0x66,(byte) 0x66, +(byte) 0x62,(byte) 0x46,(byte) 0x63,(byte) 0xc6,(byte) 0xc3,(byte) 0xc3,(byte) 0xc1,(byte) 0x83,(byte) 0xc1,(byte) 0x83,(byte) 0xc1,(byte) 0x83, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(16,14,-1,0,18,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x6,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x30,(byte) 0xc0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(12,14,-1,0,14,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x1f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(11,14,-1,0,13,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0, +(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(10,14,-1,0,12,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x3f,(byte) 0x0,(byte) 0x7f,(byte) 0xc0,(byte) 0xe0,(byte) 0xe0,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0xe0,(byte) 0x3,(byte) 0xc0,(byte) 0x1f,(byte) 0x0, +(byte) 0x7c,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x60,(byte) 0xe0,(byte) 0xe0,(byte) 0x7f,(byte) 0xc0,(byte) 0x1f,(byte) 0x0, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(11,14,-1,0,13,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x0, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(10,14,-1,0,12,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x0,(byte) 0x30,(byte) 0xf,(byte) 0xb0,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0xf0,(byte) 0x61,(byte) 0xb0,(byte) 0xe1,(byte) 0xb8,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(13,15,-1,1,15,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x0, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(10,14,-1,0,12,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x38,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0xc0,(byte) 0x18, +(byte) 0xc0,(byte) 0x18,(byte) 0xe0,(byte) 0x38,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(13,14,-1,0,15,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe0,(byte) 0xc1,(byte) 0xe0,(byte) 0xc1,(byte) 0xe0,(byte) 0xc3,(byte) 0x60,(byte) 0xc6,(byte) 0x60,(byte) 0xc6,(byte) 0x60,(byte) 0xcc,(byte) 0x60, +(byte) 0xcc,(byte) 0x60,(byte) 0xd8,(byte) 0x60,(byte) 0xf0,(byte) 0x60,(byte) 0xf0,(byte) 0x60,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(11,14,-1,0,13,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0xc3,(byte) 0xc,(byte) 0xc3,(byte) 0xc,(byte) 0xc7,(byte) 0x8c,(byte) 0xc4,(byte) 0x8c,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0xd8,(byte) 0x6c,(byte) 0xd8,(byte) 0x6c, +(byte) 0xf0,(byte) 0x3c,(byte) 0xf0,(byte) 0x3c,(byte) 0xe0,(byte) 0x1c,(byte) 0xe0,(byte) 0x1c,(byte) 0xc0,(byte) 0xc,(byte) 0xc0,(byte) 0xc, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(14,14,-1,0,16,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xff,(byte) 0xff,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(8,14,-1,0,10,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0xc0,(byte) 0x70,(byte) 0xc0,(byte) 0xe0,(byte) 0xc1,(byte) 0xc0,(byte) 0xc3,(byte) 0x80,(byte) 0xc7,(byte) 0x0,(byte) 0xce,(byte) 0x0,(byte) 0xfc,(byte) 0x0,(byte) 0xf8,(byte) 0x0, +(byte) 0xdc,(byte) 0x0,(byte) 0xce,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x80,(byte) 0xc1,(byte) 0xc0,(byte) 0xc0,(byte) 0xe0, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(12,14,-1,0,13,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0xe7,(byte) 0xc3,(byte) 0xc3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3,(byte) 0x3, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(8,14,-1,0,10,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(2,14,-2,0,6,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xff,(byte) 0xe0,(byte) 0xff,(byte) 0xe0, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(11,14,-1,0,13,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0xf,(byte) 0xb0,(byte) 0x3f,(byte) 0xf0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x30,(byte) 0xc1,(byte) 0xf0,(byte) 0xc1,(byte) 0xf0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xe0,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(12,14,-1,0,14,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(9,14,-1,0,11,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(9,14,-1,0,11,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xff,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xc1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60, +(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x0, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(11,14,-1,0,13,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0xf,(byte) 0x80,(byte) 0x3f,(byte) 0xe0,(byte) 0x70,(byte) 0x70,(byte) 0x60,(byte) 0x30,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0x60,(byte) 0x30,(byte) 0x70,(byte) 0x70,(byte) 0x3f,(byte) 0xe0,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(12,14,-1,0,14,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0xc0,(byte) 0xc0,(byte) 0xe0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe0,(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x0, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(11,14,-1,0,13,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x7f,(byte) 0xe0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0xc0, +(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0xf,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(12,14,0,0,12,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1f,(byte) 0xf0,(byte) 0x38,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x67,(byte) 0x70,(byte) 0xcf,(byte) 0xf8,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0x66, +(byte) 0xcc,(byte) 0x66,(byte) 0xcc,(byte) 0x63,(byte) 0xc6,(byte) 0x33,(byte) 0x67,(byte) 0x73,(byte) 0x63,(byte) 0xb3,(byte) 0x30,(byte) 0x6,(byte) 0x1c,(byte) 0xe,(byte) 0xf,(byte) 0xfc, +(byte) 0x3,(byte) 0xf0, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(16,17,-1,3,18,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x38,(byte) 0x1c,(byte) 0xe,(byte) 0xc6,(byte) 0xc6,(byte) 0xfe,(byte) 0x7c, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(7,14,-1,0,10,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0xc0,(byte) 0xf0,(byte) 0x3c,(byte) 0xe,(byte) 0x3,(byte) 0xe,(byte) 0x3c,(byte) 0xf0,(byte) 0xc0, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(8,9,-1,0,10,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xfe,(byte) 0xfe,(byte) 0x0,(byte) 0x0,(byte) 0xfe,(byte) 0xfe, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(7,6,-2,-2,11,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x3,(byte) 0xf,(byte) 0x3c,(byte) 0x70,(byte) 0xc0,(byte) 0x70,(byte) 0x3c,(byte) 0xf,(byte) 0x3, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(8,9,-1,0,10,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(2,13,-1,3,5,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(2,10,-1,0,5,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0x7c,(byte) 0xfe,(byte) 0xc6,(byte) 0x3,(byte) 0x3,(byte) 0x3b,(byte) 0x7f,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc7,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(8,13,-1,0,10,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0xe7,(byte) 0xc3,(byte) 0xc3,(byte) 0x66,(byte) 0x7e,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xe7,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(8,13,-1,0,10,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x60,(byte) 0x60,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18,(byte) 0x18,(byte) 0xc,(byte) 0xc,(byte) 0x6,(byte) 0x3,(byte) 0xff,(byte) 0xff, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(8,13,-1,0,10,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0xe3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xfe,(byte) 0xdc,(byte) 0xc0,(byte) 0xc0,(byte) 0x63,(byte) 0x7f,(byte) 0x3c, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(8,13,-1,0,10,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x7c,(byte) 0xfe,(byte) 0xc7,(byte) 0xc3,(byte) 0x3,(byte) 0x3,(byte) 0xc7,(byte) 0xfe,(byte) 0xfc,(byte) 0xc0,(byte) 0xc0,(byte) 0xfe,(byte) 0xfe, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(8,13,-1,0,10,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x33,(byte) 0x0, +(byte) 0x33,(byte) 0x0,(byte) 0x1b,(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x7,(byte) 0x0,(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(9,13,-1,0,10,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0xc7,(byte) 0xc3,(byte) 0x3,(byte) 0x7,(byte) 0x1e,(byte) 0x1c,(byte) 0x6,(byte) 0xc3,(byte) 0xc3,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(8,13,-1,0,10,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xff,(byte) 0xff,(byte) 0xc0,(byte) 0xe0,(byte) 0x70,(byte) 0x38,(byte) 0x1c,(byte) 0xe,(byte) 0x7,(byte) 0x3,(byte) 0xc3,(byte) 0xfe,(byte) 0x3c, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(8,13,-1,0,10,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xf8,(byte) 0xf8,(byte) 0x18, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(5,13,-2,0,10,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x3c,(byte) 0x7e,(byte) 0x66,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0xc3,(byte) 0x66,(byte) 0x7e,(byte) 0x3c, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(8,13,-1,0,10,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x40,(byte) 0x40,(byte) 0x60,(byte) 0x60,(byte) 0x20,(byte) 0x20,(byte) 0x30,(byte) 0x30,(byte) 0x10,(byte) 0x10,(byte) 0x18,(byte) 0x18, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(5,14,0,0,5,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(2,2,-1,0,5,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xff,(byte) 0xff, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(8,2,-1,-4,11,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(2,5,-1,3,5,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xff,(byte) 0xff,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(8,10,-1,0,10,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0x88,(byte) 0x70,(byte) 0x70,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(5,6,-1,-8,7,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0xc0,(byte) 0x60,(byte) 0x60,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x60,(byte) 0x60, +(byte) 0xc0,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(4,18,-1,4,6,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x10,(byte) 0x30,(byte) 0x60,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0x60, +(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(4,18,-1,4,6,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(2,5,-1,-9,4,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x3c,(byte) 0x70,(byte) 0x7e,(byte) 0xe0,(byte) 0xe7,(byte) 0xc0,(byte) 0xc3,(byte) 0x80,(byte) 0xc3,(byte) 0xc0,(byte) 0xc6,(byte) 0xc0,(byte) 0xee,(byte) 0xc0,(byte) 0x7c,(byte) 0x0, +(byte) 0x3c,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x7e,(byte) 0x0,(byte) 0x3c,(byte) 0x0, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(12,13,-1,0,13,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x18,(byte) 0x78,(byte) 0x18,(byte) 0xfc,(byte) 0xc,(byte) 0xcc,(byte) 0xc,(byte) 0xcc,(byte) 0x6,(byte) 0xfc,(byte) 0x6,(byte) 0x78,(byte) 0x3,(byte) 0x0,(byte) 0x7b,(byte) 0x0, +(byte) 0xfd,(byte) 0x80,(byte) 0xcd,(byte) 0x80,(byte) 0xcc,(byte) 0xc0,(byte) 0xfc,(byte) 0xc0,(byte) 0x78,(byte) 0x60, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(14,13,-1,0,16,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x8,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0xeb,(byte) 0x80,(byte) 0xc9,(byte) 0x80,(byte) 0x9,(byte) 0x80,(byte) 0xf,(byte) 0x0, +(byte) 0x3e,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0xe8,(byte) 0x0,(byte) 0xc8,(byte) 0x0,(byte) 0xcb,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x8,(byte) 0x0, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(9,16,-1,2,10,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x24,(byte) 0x0,(byte) 0x24,(byte) 0x0,(byte) 0x24,(byte) 0x0,(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0x80,(byte) 0x12,(byte) 0x0,(byte) 0x12,(byte) 0x0,(byte) 0x12,(byte) 0x0, +(byte) 0x7f,(byte) 0xc0,(byte) 0x7f,(byte) 0xc0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(10,13,0,0,10,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0x90,(byte) 0x90,(byte) 0xd8,(byte) 0xd8,(byte) 0xd8, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(5,5,0,-9,5,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(2,14,-2,0,6,ch33data); + +/* char: 0x20 ' ' */ + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,5,null); + +static final BitmapCharRec[] chars = { +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmapHelvetica18 = new BitmapFontRec("-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1", + 224, + 32, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java new file mode 100644 index 000000000..f753b56f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman10.java @@ -0,0 +1,1797 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmapTimesRoman10 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0x80,(byte) 0xc0,(byte) 0x40,(byte) 0x60,(byte) 0xa0,(byte) 0x90,(byte) 0xb8,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(5,9,0,2,5,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0xc0,(byte) 0x80,(byte) 0xe0,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(4,9,0,2,5,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0x80,(byte) 0xc0,(byte) 0x40,(byte) 0x60,(byte) 0xa0,(byte) 0x90,(byte) 0xb8,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(5,10,0,2,5,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(5,7,0,0,5,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(5,8,0,0,5,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(5,8,0,0,5,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(5,8,0,0,5,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0x80,(byte) 0x70,(byte) 0x48,(byte) 0x48,(byte) 0x48,(byte) 0x38,(byte) 0x4, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(6,7,1,1,5,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x20,(byte) 0x0,(byte) 0xf8,(byte) 0x0,(byte) 0x20, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(5,5,0,0,6,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(4,7,0,0,5,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(4,8,0,0,5,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(4,8,0,0,5,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(4,8,0,0,5,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(4,8,0,0,5,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0xd8,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(5,8,0,0,5,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0xa0,(byte) 0x70,(byte) 0x40, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(4,8,0,0,5,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(3,7,0,0,4,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(3,8,0,0,4,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(3,8,0,0,4,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(3,8,0,0,4,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x60,(byte) 0x80,(byte) 0xc0,(byte) 0xa0,(byte) 0x60,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(3,7,0,0,4,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x60,(byte) 0x80,(byte) 0xc0,(byte) 0xa0,(byte) 0x60,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(3,8,0,0,4,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x60,(byte) 0x80,(byte) 0xc0,(byte) 0xa0,(byte) 0x60,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(3,8,0,0,4,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x60,(byte) 0x80,(byte) 0xc0,(byte) 0xa0,(byte) 0x60,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(3,8,0,0,4,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x60,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x60, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(3,8,0,3,4,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0xd8,(byte) 0xa0,(byte) 0x70,(byte) 0x28,(byte) 0xd8, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(5,5,0,0,6,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x40,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(3,8,0,0,4,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(3,7,0,0,4,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(4,8,0,0,4,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(3,8,0,0,4,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(3,8,0,0,4,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(3,8,0,0,4,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0xe0,(byte) 0x50,(byte) 0x50,(byte) 0x60,(byte) 0x50,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(4,7,0,0,5,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x70,(byte) 0x48,(byte) 0x70,(byte) 0x40,(byte) 0xe0, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(5,7,0,0,6,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x38,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0xee,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(7,10,0,0,8,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x38,(byte) 0x6c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0xee,(byte) 0x0,(byte) 0x28, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(7,9,0,0,8,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x38,(byte) 0x6c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0xee,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(7,10,0,0,8,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x38,(byte) 0x6c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0xee,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(7,10,0,0,8,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x38,(byte) 0x6c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0xee,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(7,10,0,0,8,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x80,(byte) 0x7c,(byte) 0x66,(byte) 0x52,(byte) 0x52,(byte) 0x4a,(byte) 0x66,(byte) 0x3e,(byte) 0x1, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(8,9,0,1,8,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x88,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0x88, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(5,5,0,0,6,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(6,9,0,0,7,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(6,10,0,0,7,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(6,10,0,0,7,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(6,10,0,0,7,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(6,10,0,0,7,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0xe4,(byte) 0x4c,(byte) 0x4c,(byte) 0x54,(byte) 0x54,(byte) 0x64,(byte) 0xee,(byte) 0x0,(byte) 0x50,(byte) 0x28, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(7,10,0,0,8,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0xf8,(byte) 0x4c,(byte) 0x44,(byte) 0xe4,(byte) 0x44,(byte) 0x4c,(byte) 0xf8, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(6,7,0,0,7,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x0,(byte) 0xa0, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(3,9,0,0,4,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(3,10,0,0,4,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x0,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(3,10,0,0,4,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x0,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(3,10,0,0,4,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8,(byte) 0x0,(byte) 0x50, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(5,9,0,0,6,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8,(byte) 0x0,(byte) 0x50,(byte) 0x20, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(5,10,0,0,6,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x10, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(5,10,0,0,6,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(5,10,0,0,6,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x60,(byte) 0x10,(byte) 0x20,(byte) 0x78,(byte) 0xc4,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc4,(byte) 0x7c, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(6,10,0,3,7,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0xef,(byte) 0x49,(byte) 0x78,(byte) 0x2e,(byte) 0x28,(byte) 0x39,(byte) 0x1f, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(8,7,0,0,9,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(7,10,0,0,8,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0x28, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(7,9,0,0,8,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x14, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(7,10,0,0,8,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0x28,(byte) 0x10, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(7,10,0,0,8,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x8, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(7,10,0,0,8,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10,(byte) 0x0,(byte) 0x10,(byte) 0x20, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(7,10,0,0,8,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(3,7,0,2,4,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x44,(byte) 0x3e,(byte) 0x2c,(byte) 0xd4,(byte) 0x28,(byte) 0x48,(byte) 0xe4, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(7,7,0,0,8,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x4e,(byte) 0x24,(byte) 0x2a,(byte) 0xf6,(byte) 0x48,(byte) 0xc8,(byte) 0x44, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(7,7,0,0,8,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x44,(byte) 0x3e,(byte) 0x2c,(byte) 0xf4,(byte) 0x48,(byte) 0xc8,(byte) 0x44, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(7,7,0,0,8,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0xa0,(byte) 0x50,(byte) 0x50,(byte) 0xa0, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(4,4,0,-1,5,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xe0,(byte) 0x0,(byte) 0x40,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(3,5,0,-2,4,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0xe0,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(3,4,0,-3,3,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x40, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(3,3,0,3,4,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(1,1,0,-2,2,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x28,(byte) 0x68,(byte) 0xe8,(byte) 0xe8,(byte) 0xe8,(byte) 0x7c, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(6,9,0,2,6,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x80,(byte) 0x80,(byte) 0xe8,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(5,7,0,2,5,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(2,2,0,-5,3,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0xe0, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(3,4,0,-3,3,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xe0,(byte) 0x40,(byte) 0xa0,(byte) 0x60, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(3,4,0,-3,3,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xf8,(byte) 0x0,(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(5,7,0,0,6,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(4,4,0,-3,4,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xe0, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(3,1,0,-6,4,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x38,(byte) 0x44,(byte) 0xaa,(byte) 0xb2,(byte) 0xba,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(7,7,-1,0,9,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xe0, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(3,1,0,-2,4,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x8,(byte) 0x8,(byte) 0xf8, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(5,3,-1,-1,7,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x50,(byte) 0xa0,(byte) 0xa0,(byte) 0x50, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(4,4,0,-1,5,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xa0,(byte) 0x20,(byte) 0xc0, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(3,5,0,-2,4,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x38,(byte) 0x44,(byte) 0x9a,(byte) 0xa2,(byte) 0x9a,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(7,7,-1,0,9,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xa0, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(3,1,-1,-6,5,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0xe0,(byte) 0x90,(byte) 0x20,(byte) 0x50,(byte) 0x90,(byte) 0xa0,(byte) 0x40,(byte) 0x90,(byte) 0x70, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(4,9,0,1,5,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(1,7,0,0,2,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0x70,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0xd8,(byte) 0x50,(byte) 0x88, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(5,7,0,0,5,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0x88,(byte) 0x70,(byte) 0x50,(byte) 0x50,(byte) 0x70,(byte) 0x88, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(5,6,0,-1,5,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xf0,(byte) 0xc8,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x50,(byte) 0x30, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(5,7,0,0,5,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x80,(byte) 0xe0,(byte) 0x90,(byte) 0x80,(byte) 0x90,(byte) 0x70,(byte) 0x10, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(4,7,0,1,5,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(1,7,-1,2,3,ch161data); + +/* char: 0xa0 */ + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,2,null); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x98,(byte) 0x64, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(6,2,0,-2,7,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(3,9,0,2,4,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(1,9,0,2,2,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(3,9,0,2,4,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xf0,(byte) 0x90,(byte) 0x40,(byte) 0x20,(byte) 0xf0, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(4,5,0,0,5,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x30,(byte) 0x50,(byte) 0x48,(byte) 0xdc, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(6,7,1,2,5,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0xd8,(byte) 0x50,(byte) 0x20,(byte) 0x50,(byte) 0xd8, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(5,5,0,0,6,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x28,(byte) 0x6c,(byte) 0x54,(byte) 0x92,(byte) 0xdb, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(8,5,0,0,8,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x20,(byte) 0x60,(byte) 0x50,(byte) 0x90,(byte) 0xd8, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(5,5,0,0,5,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(5,5,0,0,5,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x30,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(4,6,0,0,4,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0xe0,(byte) 0x20,(byte) 0x60,(byte) 0x80,(byte) 0xe0, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(3,5,0,0,4,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x60,(byte) 0xa0, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(3,5,0,0,4,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x38,(byte) 0x10,(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x70, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(5,7,0,2,5,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0xc0,(byte) 0x80,(byte) 0xe0,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(4,7,0,2,5,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(4,5,0,0,5,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0xd8,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(5,5,0,0,5,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0xdb,(byte) 0x92,(byte) 0x92,(byte) 0x92,(byte) 0xec, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(8,5,0,0,8,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(3,7,0,0,4,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0x98,(byte) 0x90,(byte) 0xe0,(byte) 0xa0,(byte) 0x90,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(5,7,0,0,5,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(2,9,0,2,3,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x0,(byte) 0x40, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(2,7,0,0,3,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0xd8,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(5,7,0,0,5,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0xe0,(byte) 0x90,(byte) 0x60,(byte) 0x40,(byte) 0xa0,(byte) 0xa0,(byte) 0x70, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(4,7,0,2,5,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0,(byte) 0x40,(byte) 0x30, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(4,7,0,0,4,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x60,(byte) 0x80,(byte) 0xc0,(byte) 0xa0,(byte) 0x60, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(3,5,0,0,4,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x68,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x70,(byte) 0x10,(byte) 0x30, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(5,7,0,0,5,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x60,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x60, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(3,5,0,0,4,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0xe0,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(4,7,0,0,5,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0xe0,(byte) 0xa0,(byte) 0x60,(byte) 0x20,(byte) 0xc0, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(3,5,0,0,4,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0xc0,(byte) 0x80, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(2,2,0,-5,3,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xf8, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(5,1,0,3,5,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0xa0,(byte) 0xa0,(byte) 0x40, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(3,3,-1,-4,5,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xc0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(2,9,0,2,3,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(3,7,0,0,3,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xc0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc0, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(2,9,0,2,3,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xf8,(byte) 0x88,(byte) 0x40,(byte) 0x20,(byte) 0x10,(byte) 0x88,(byte) 0xf8, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(5,7,0,0,6,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x38,(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x44,(byte) 0xee, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(7,7,0,0,8,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0xee,(byte) 0x44,(byte) 0x28,(byte) 0x10,(byte) 0x28,(byte) 0x44,(byte) 0xee, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(7,7,0,0,8,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0xc9,(byte) 0x80,(byte) 0x88,(byte) 0x80,(byte) 0xdd,(byte) 0xc0, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(10,7,0,0,10,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x10,(byte) 0x10,(byte) 0x28,(byte) 0x28,(byte) 0x6c,(byte) 0x44,(byte) 0xee, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(7,7,0,0,8,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x38,(byte) 0x6c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0xee, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(7,7,0,0,8,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0x70,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xa8,(byte) 0xf8, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(5,7,0,0,6,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0xe0,(byte) 0x90,(byte) 0x10,(byte) 0x60,(byte) 0xc0,(byte) 0x90,(byte) 0x70, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(4,7,0,0,5,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0xec,(byte) 0x48,(byte) 0x50,(byte) 0x70,(byte) 0x48,(byte) 0x48,(byte) 0xf0, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(6,7,0,0,7,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0xc,(byte) 0x18,(byte) 0x70,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(6,9,0,2,7,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x70,(byte) 0x48,(byte) 0x48,(byte) 0xf0, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(5,7,0,0,6,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x78,(byte) 0xcc,(byte) 0x84,(byte) 0x84,(byte) 0x84,(byte) 0xcc,(byte) 0x78, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(6,7,0,0,7,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0xe4,(byte) 0x4c,(byte) 0x4c,(byte) 0x54,(byte) 0x54,(byte) 0x64,(byte) 0xee, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(7,7,0,0,8,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0xeb,(byte) 0x80,(byte) 0x49,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x55,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0xe3,(byte) 0x80, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(9,7,0,0,10,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(5,7,0,0,6,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0xec,(byte) 0x48,(byte) 0x50,(byte) 0x60,(byte) 0x50,(byte) 0x48,(byte) 0xec, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(6,7,0,0,7,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0xc0,(byte) 0xa0,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x70, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(4,7,0,0,4,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xe0, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(3,7,0,0,4,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0xee,(byte) 0x44,(byte) 0x44,(byte) 0x7c,(byte) 0x44,(byte) 0x44,(byte) 0xee, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(7,7,0,0,8,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x78,(byte) 0xc4,(byte) 0x84,(byte) 0x9c,(byte) 0x80,(byte) 0xc4,(byte) 0x7c, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(6,7,0,0,7,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(5,7,0,0,6,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xf8,(byte) 0x48,(byte) 0x40,(byte) 0x70,(byte) 0x40,(byte) 0x48,(byte) 0xf8, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(5,7,0,0,6,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xf8,(byte) 0x4c,(byte) 0x44,(byte) 0x44,(byte) 0x44,(byte) 0x4c,(byte) 0xf8, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(6,7,0,0,7,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x78,(byte) 0xc4,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0xc4,(byte) 0x7c, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(6,7,0,0,7,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xf0,(byte) 0x48,(byte) 0x48,(byte) 0x70,(byte) 0x48,(byte) 0x48,(byte) 0xf0, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(5,7,0,0,6,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0xee,(byte) 0x44,(byte) 0x7c,(byte) 0x28,(byte) 0x28,(byte) 0x38,(byte) 0x10, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(7,7,0,0,8,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x3e,(byte) 0x40,(byte) 0x92,(byte) 0xad,(byte) 0xa5,(byte) 0xa5,(byte) 0x9d,(byte) 0x42,(byte) 0x3c, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(8,9,0,2,9,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0xa0,(byte) 0xe0, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(3,7,0,0,4,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(3,5,0,0,5,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xf8,(byte) 0x0,(byte) 0xf8, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(5,3,0,-1,6,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x20,(byte) 0x40,(byte) 0x80,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(3,5,-1,0,5,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(1,7,-1,2,3,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x80, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(1,5,-1,0,3,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0xc0,(byte) 0x20,(byte) 0x70,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(4,7,0,0,5,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(4,7,0,0,5,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x90,(byte) 0xf0, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(4,7,0,0,5,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0xe0,(byte) 0x40,(byte) 0x30, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(4,7,0,0,5,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0xe0,(byte) 0x90,(byte) 0x10,(byte) 0x10,(byte) 0xe0,(byte) 0x40,(byte) 0x70, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(4,7,0,0,5,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x10,(byte) 0x10,(byte) 0xf8,(byte) 0x90,(byte) 0x50,(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(5,7,0,0,5,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0xe0,(byte) 0x10,(byte) 0x10,(byte) 0x60,(byte) 0x10,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(4,7,0,0,5,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xf0,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x10,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(4,7,0,0,5,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0xe0,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0xc0,(byte) 0x40, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(3,7,-1,0,5,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x60,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x90,(byte) 0x60, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(4,7,0,0,5,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(3,7,0,0,3,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0x80, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(1,1,-1,0,3,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xf0, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(4,1,-1,-2,7,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(1,3,-1,2,3,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x20,(byte) 0x20,(byte) 0xf8,(byte) 0x20,(byte) 0x20, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(5,5,0,0,6,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0xa0,(byte) 0x40,(byte) 0xa0, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(3,3,0,-4,5,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(3,9,0,2,4,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x20,(byte) 0x40,(byte) 0x40,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x40,(byte) 0x40,(byte) 0x20, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(3,9,0,2,4,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0x40,(byte) 0xc0, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(2,2,0,-5,3,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x76,(byte) 0x8d,(byte) 0x98,(byte) 0x74,(byte) 0x6e,(byte) 0x50,(byte) 0x30, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(8,7,0,0,8,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x44,(byte) 0x2a,(byte) 0x2a,(byte) 0x56,(byte) 0xa8,(byte) 0xa4,(byte) 0x7e, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(7,7,0,0,8,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x20,(byte) 0xe0,(byte) 0x90,(byte) 0x10,(byte) 0x60,(byte) 0x80,(byte) 0x90,(byte) 0x70,(byte) 0x20, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(4,9,0,1,5,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x50,(byte) 0x50,(byte) 0xf8,(byte) 0x50,(byte) 0xf8,(byte) 0x50,(byte) 0x50, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(5,7,0,0,5,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0xa0,(byte) 0xa0, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(3,2,0,-5,4,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0x80,(byte) 0x0,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80,(byte) 0x80, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(1,7,-1,0,3,ch33data); + +/* char: 0x20 ' ' */ + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,2,null); + +static final BitmapCharRec[] chars = { +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmapTimesRoman10 = new BitmapFontRec("-adobe-times-medium-r-normal--10-100-75-75-p-54-iso8859-1", + 224, + 32, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java new file mode 100644 index 000000000..073e6e673 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTBitmapTimesRoman24.java @@ -0,0 +1,2080 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTBitmapTimesRoman24 { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 0xff */ + +static final byte[] ch255data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xf0,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x1a,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x31,(byte) 0x0,(byte) 0x30,(byte) 0x80,(byte) 0x30,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x60,(byte) 0xc0, +(byte) 0xf1,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x33,(byte) 0x0, +}; + +static final BitmapCharRec ch255 = new BitmapCharRec(11,21,0,5,11,ch255data); + +/* char: 0xfe */ + +static final byte[] ch254data = { +(byte) 0xf0,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x6e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80, +(byte) 0x6e,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0xe0,(byte) 0x0, +}; + +static final BitmapCharRec ch254 = new BitmapCharRec(10,22,-1,5,12,ch254data); + +/* char: 0xfd */ + +static final byte[] ch253data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xf0,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x1a,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x31,(byte) 0x0,(byte) 0x30,(byte) 0x80,(byte) 0x30,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x60,(byte) 0xc0, +(byte) 0xf1,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x80,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch253 = new BitmapCharRec(11,22,0,5,11,ch253data); + +/* char: 0xfc */ + +static final byte[] ch252data = { +(byte) 0x1c,(byte) 0xe0,(byte) 0x3e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe1,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x33,(byte) 0x0, +}; + +static final BitmapCharRec ch252 = new BitmapCharRec(11,16,-1,0,13,ch252data); + +/* char: 0xfb */ + +static final byte[] ch251data = { +(byte) 0x1c,(byte) 0xe0,(byte) 0x3e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe1,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x21,(byte) 0x0,(byte) 0x12,(byte) 0x0,(byte) 0x1e,(byte) 0x0, +(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch251 = new BitmapCharRec(11,17,-1,0,13,ch251data); + +/* char: 0xfa */ + +static final byte[] ch250data = { +(byte) 0x1c,(byte) 0xe0,(byte) 0x3e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe1,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x80, +(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch250 = new BitmapCharRec(11,17,-1,0,13,ch250data); + +/* char: 0xf9 */ + +static final byte[] ch249data = { +(byte) 0x1c,(byte) 0xe0,(byte) 0x3e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe1,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x2,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x38,(byte) 0x0, +(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch249 = new BitmapCharRec(11,17,-1,0,13,ch249data); + +/* char: 0xf8 */ + +static final byte[] ch248data = { +(byte) 0xc0,(byte) 0x0,(byte) 0xde,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x71,(byte) 0x80,(byte) 0xd0,(byte) 0xc0,(byte) 0xd8,(byte) 0xc0,(byte) 0xc8,(byte) 0xc0,(byte) 0xcc,(byte) 0xc0, +(byte) 0xc4,(byte) 0xc0,(byte) 0xc6,(byte) 0xc0,(byte) 0x63,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0xc0,(byte) 0x0,(byte) 0xc0, +}; + +static final BitmapCharRec ch248 = new BitmapCharRec(10,14,-1,1,12,ch248data); + +/* char: 0xf7 */ + +static final byte[] ch247data = { +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch247 = new BitmapCharRec(12,10,-1,-2,14,ch247data); + +/* char: 0xf6 */ + +static final byte[] ch246data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x33,(byte) 0x0, +}; + +static final BitmapCharRec ch246 = new BitmapCharRec(10,16,-1,0,12,ch246data); + +/* char: 0xf5 */ + +static final byte[] ch245data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x27,(byte) 0x0,(byte) 0x1c,(byte) 0x80, +}; + +static final BitmapCharRec ch245 = new BitmapCharRec(10,16,-1,0,12,ch245data); + +/* char: 0xf4 */ + +static final byte[] ch244data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x21,(byte) 0x0,(byte) 0x12,(byte) 0x0,(byte) 0x1e,(byte) 0x0, +(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch244 = new BitmapCharRec(10,17,-1,0,12,ch244data); + +/* char: 0xf3 */ + +static final byte[] ch243data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x80, +(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch243 = new BitmapCharRec(10,17,-1,0,12,ch243data); + +/* char: 0xf2 */ + +static final byte[] ch242data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x2,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x38,(byte) 0x0, +(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch242 = new BitmapCharRec(10,17,-1,0,12,ch242data); + +/* char: 0xf1 */ + +static final byte[] ch241data = { +(byte) 0xf1,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x6f,(byte) 0x80,(byte) 0xe7,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x27,(byte) 0x0,(byte) 0x1c,(byte) 0x80, +}; + +static final BitmapCharRec ch241 = new BitmapCharRec(11,16,-1,0,13,ch241data); + +/* char: 0xf0 */ + +static final byte[] ch240data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1f,(byte) 0x0,(byte) 0xc6,(byte) 0x0,(byte) 0x3c,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x71,(byte) 0x80, +(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch240 = new BitmapCharRec(10,17,-1,0,12,ch240data); + +/* char: 0xef */ + +static final byte[] ch239data = { +(byte) 0x78,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70,(byte) 0x0,(byte) 0x0,(byte) 0xcc,(byte) 0xcc, +}; + +static final BitmapCharRec ch239 = new BitmapCharRec(6,16,0,0,6,ch239data); + +/* char: 0xee */ + +static final byte[] ch238data = { +(byte) 0x78,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70,(byte) 0x0,(byte) 0x84,(byte) 0x48,(byte) 0x78, +(byte) 0x30, +}; + +static final BitmapCharRec ch238 = new BitmapCharRec(6,17,0,0,6,ch238data); + +/* char: 0xed */ + +static final byte[] ch237data = { +(byte) 0xf0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xe0,(byte) 0x0,(byte) 0x80,(byte) 0x60,(byte) 0x38, +(byte) 0x18, +}; + +static final BitmapCharRec ch237 = new BitmapCharRec(5,17,-1,0,6,ch237data); + +/* char: 0xec */ + +static final byte[] ch236data = { +(byte) 0x78,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70,(byte) 0x0,(byte) 0x8,(byte) 0x30,(byte) 0xe0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch236 = new BitmapCharRec(5,17,0,0,6,ch236data); + +/* char: 0xeb */ + +static final byte[] ch235data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x33,(byte) 0x0, +}; + +static final BitmapCharRec ch235 = new BitmapCharRec(9,16,-1,0,11,ch235data); + +/* char: 0xea */ + +static final byte[] ch234data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x21,(byte) 0x0,(byte) 0x12,(byte) 0x0,(byte) 0x1e,(byte) 0x0, +(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch234 = new BitmapCharRec(9,17,-1,0,11,ch234data); + +/* char: 0xe9 */ + +static final byte[] ch233data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x7,(byte) 0x0, +(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch233 = new BitmapCharRec(9,17,-1,0,11,ch233data); + +/* char: 0xe8 */ + +static final byte[] ch232data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x70,(byte) 0x0, +(byte) 0x60,(byte) 0x0, +}; + +static final BitmapCharRec ch232 = new BitmapCharRec(9,17,-1,0,11,ch232data); + +/* char: 0xe7 */ + +static final byte[] ch231data = { +(byte) 0x3c,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0, +(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x41,(byte) 0x80, +(byte) 0x63,(byte) 0x80,(byte) 0x1f,(byte) 0x0, +}; + +static final BitmapCharRec ch231 = new BitmapCharRec(9,18,-1,6,11,ch231data); + +/* char: 0xe6 */ + +static final byte[] ch230data = { +(byte) 0x70,(byte) 0xf0,(byte) 0xfb,(byte) 0xf8,(byte) 0xc7,(byte) 0x84,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0xfc, +(byte) 0x3,(byte) 0xc,(byte) 0x63,(byte) 0xc,(byte) 0x67,(byte) 0x98,(byte) 0x3c,(byte) 0xf0, +}; + +static final BitmapCharRec ch230 = new BitmapCharRec(14,12,-1,0,16,ch230data); + +/* char: 0xe5 */ + +static final byte[] ch229data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0, +(byte) 0x1c,(byte) 0x0, +}; + +static final BitmapCharRec ch229 = new BitmapCharRec(9,17,-1,0,11,ch229data); + +/* char: 0xe4 */ + +static final byte[] ch228data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x66,(byte) 0x0, +}; + +static final BitmapCharRec ch228 = new BitmapCharRec(9,16,-1,0,11,ch228data); + +/* char: 0xe3 */ + +static final byte[] ch227data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x5c,(byte) 0x0,(byte) 0x3a,(byte) 0x0, +}; + +static final BitmapCharRec ch227 = new BitmapCharRec(9,16,-1,0,11,ch227data); + +/* char: 0xe2 */ + +static final byte[] ch226data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x42,(byte) 0x0,(byte) 0x24,(byte) 0x0,(byte) 0x3c,(byte) 0x0, +(byte) 0x18,(byte) 0x0, +}; + +static final BitmapCharRec ch226 = new BitmapCharRec(9,17,-1,0,11,ch226data); + +/* char: 0xe1 */ + +static final byte[] ch225data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x7,(byte) 0x0, +(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch225 = new BitmapCharRec(9,17,-1,0,11,ch225data); + +/* char: 0xe0 */ + +static final byte[] ch224data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x70,(byte) 0x0, +(byte) 0x60,(byte) 0x0, +}; + +static final BitmapCharRec ch224 = new BitmapCharRec(9,17,-1,0,11,ch224data); + +/* char: 0xdf */ + +static final byte[] ch223data = { +(byte) 0xe7,(byte) 0x0,(byte) 0x6c,(byte) 0x80,(byte) 0x6c,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x61,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x63,(byte) 0x80, +(byte) 0x67,(byte) 0x0,(byte) 0x6c,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0, +(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch223 = new BitmapCharRec(10,17,-1,0,12,ch223data); + +/* char: 0xde */ + +static final byte[] ch222data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18, +(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70,(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0xfc,(byte) 0x0, +}; + +static final BitmapCharRec ch222 = new BitmapCharRec(13,17,-1,0,15,ch222data); + +/* char: 0xdd */ + +static final byte[] ch221data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x3,(byte) 0xc0, +(byte) 0x3,(byte) 0x40,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x20,(byte) 0xc,(byte) 0x30,(byte) 0x1c,(byte) 0x10,(byte) 0x18,(byte) 0x18,(byte) 0x38,(byte) 0x8,(byte) 0x30,(byte) 0xc, +(byte) 0xfc,(byte) 0x3f,(byte) 0x0,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x30, +}; + +static final BitmapCharRec ch221 = new BitmapCharRec(16,22,0,0,16,ch221data); + +/* char: 0xdc */ + +static final byte[] ch220data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x30,(byte) 0x18,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xfc,(byte) 0x1f,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x30,(byte) 0x6,(byte) 0x30, +}; + +static final BitmapCharRec ch220 = new BitmapCharRec(16,21,-1,0,18,ch220data); + +/* char: 0xdb */ + +static final byte[] ch219data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x30,(byte) 0x18,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xfc,(byte) 0x1f,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x10,(byte) 0x6,(byte) 0x60,(byte) 0x3,(byte) 0xc0,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch219 = new BitmapCharRec(16,22,-1,0,18,ch219data); + +/* char: 0xda */ + +static final byte[] ch218data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x30,(byte) 0x18,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xfc,(byte) 0x1f,(byte) 0x0,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x30, +}; + +static final BitmapCharRec ch218 = new BitmapCharRec(16,22,-1,0,18,ch218data); + +/* char: 0xd9 */ + +static final byte[] ch217data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x30,(byte) 0x18,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xfc,(byte) 0x1f,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x40,(byte) 0x1,(byte) 0x80,(byte) 0x7,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch217 = new BitmapCharRec(16,22,-1,0,18,ch217data); + +/* char: 0xd8 */ + +static final byte[] ch216data = { +(byte) 0x20,(byte) 0x0,(byte) 0x27,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x68,(byte) 0x6,(byte) 0x64,(byte) 0x6,(byte) 0xc2,(byte) 0x3,(byte) 0xc2,(byte) 0x3, +(byte) 0xc1,(byte) 0x3,(byte) 0xc1,(byte) 0x3,(byte) 0xc0,(byte) 0x83,(byte) 0xc0,(byte) 0x83,(byte) 0xc0,(byte) 0x43,(byte) 0x60,(byte) 0x46,(byte) 0x60,(byte) 0x26,(byte) 0x38,(byte) 0x1c, +(byte) 0x1c,(byte) 0x38,(byte) 0x7,(byte) 0xe4,(byte) 0x0,(byte) 0x4, +}; + +static final BitmapCharRec ch216 = new BitmapCharRec(16,19,-1,1,18,ch216data); + +/* char: 0xd7 */ + +static final byte[] ch215data = { +(byte) 0x80,(byte) 0x40,(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x33,(byte) 0x0, +(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0x80,(byte) 0x40, +}; + +static final BitmapCharRec ch215 = new BitmapCharRec(10,11,-2,-1,14,ch215data); + +/* char: 0xd6 */ + +static final byte[] ch214data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x60, +}; + +static final BitmapCharRec ch214 = new BitmapCharRec(16,21,-1,0,18,ch214data); + +/* char: 0xd5 */ + +static final byte[] ch213data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0xe0,(byte) 0x3,(byte) 0x90, +}; + +static final BitmapCharRec ch213 = new BitmapCharRec(16,21,-1,0,18,ch213data); + +/* char: 0xd4 */ + +static final byte[] ch212data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x10,(byte) 0x6,(byte) 0x60,(byte) 0x3,(byte) 0xc0,(byte) 0x1,(byte) 0x80, +}; + +static final BitmapCharRec ch212 = new BitmapCharRec(16,22,-1,0,18,ch212data); + +/* char: 0xd3 */ + +static final byte[] ch211data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x30, +}; + +static final BitmapCharRec ch211 = new BitmapCharRec(16,22,-1,0,18,ch211data); + +/* char: 0xd2 */ + +static final byte[] ch210data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x40,(byte) 0x1,(byte) 0x80,(byte) 0x7,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch210 = new BitmapCharRec(16,22,-1,0,18,ch210data); + +/* char: 0xd1 */ + +static final byte[] ch209data = { +(byte) 0xf8,(byte) 0xc,(byte) 0x20,(byte) 0x1c,(byte) 0x20,(byte) 0x1c,(byte) 0x20,(byte) 0x34,(byte) 0x20,(byte) 0x64,(byte) 0x20,(byte) 0x64,(byte) 0x20,(byte) 0xc4,(byte) 0x21,(byte) 0x84, +(byte) 0x21,(byte) 0x84,(byte) 0x23,(byte) 0x4,(byte) 0x26,(byte) 0x4,(byte) 0x26,(byte) 0x4,(byte) 0x2c,(byte) 0x4,(byte) 0x38,(byte) 0x4,(byte) 0x38,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xf0,(byte) 0x1f,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0xe0,(byte) 0x3,(byte) 0x90, +}; + +static final BitmapCharRec ch209 = new BitmapCharRec(16,21,-1,0,18,ch209data); + +/* char: 0xd0 */ + +static final byte[] ch208data = { +(byte) 0x7f,(byte) 0xe0,(byte) 0x18,(byte) 0x38,(byte) 0x18,(byte) 0x1c,(byte) 0x18,(byte) 0x6,(byte) 0x18,(byte) 0x6,(byte) 0x18,(byte) 0x3,(byte) 0x18,(byte) 0x3,(byte) 0x18,(byte) 0x3, +(byte) 0xff,(byte) 0x3,(byte) 0x18,(byte) 0x3,(byte) 0x18,(byte) 0x3,(byte) 0x18,(byte) 0x3,(byte) 0x18,(byte) 0x6,(byte) 0x18,(byte) 0x6,(byte) 0x18,(byte) 0x1c,(byte) 0x18,(byte) 0x38, +(byte) 0x7f,(byte) 0xe0, +}; + +static final BitmapCharRec ch208 = new BitmapCharRec(16,17,0,0,17,ch208data); + +/* char: 0xcf */ + +static final byte[] ch207data = { +(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0xfc,(byte) 0x0,(byte) 0x0,(byte) 0xcc,(byte) 0xcc, +}; + +static final BitmapCharRec ch207 = new BitmapCharRec(6,21,-1,0,8,ch207data); + +/* char: 0xce */ + +static final byte[] ch206data = { +(byte) 0x7e,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18, +(byte) 0x7e,(byte) 0x0,(byte) 0x81,(byte) 0x66,(byte) 0x3c,(byte) 0x18, +}; + +static final BitmapCharRec ch206 = new BitmapCharRec(8,22,-1,0,8,ch206data); + +/* char: 0xcd */ + +static final byte[] ch205data = { +(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0xfc,(byte) 0x0,(byte) 0x40,(byte) 0x30,(byte) 0x1c,(byte) 0xc, +}; + +static final BitmapCharRec ch205 = new BitmapCharRec(6,22,-1,0,8,ch205data); + +/* char: 0xcc */ + +static final byte[] ch204data = { +(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0xfc,(byte) 0x0,(byte) 0x8,(byte) 0x30,(byte) 0xe0,(byte) 0xc0, +}; + +static final BitmapCharRec ch204 = new BitmapCharRec(6,22,-1,0,8,ch204data); + +/* char: 0xcb */ + +static final byte[] ch203data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80, +}; + +static final BitmapCharRec ch203 = new BitmapCharRec(13,21,-1,0,15,ch203data); + +/* char: 0xca */ + +static final byte[] ch202data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x20,(byte) 0xc,(byte) 0xc0,(byte) 0x7,(byte) 0x80,(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch202 = new BitmapCharRec(13,22,-1,0,15,ch202data); + +/* char: 0xc9 */ + +static final byte[] ch201data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0xc0, +}; + +static final BitmapCharRec ch201 = new BitmapCharRec(13,22,-1,0,15,ch201data); + +/* char: 0xc8 */ + +static final byte[] ch200data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0x18,(byte) 0x0, +}; + +static final BitmapCharRec ch200 = new BitmapCharRec(13,22,-1,0,15,ch200data); + +/* char: 0xc7 */ + +static final byte[] ch199data = { +(byte) 0x7,(byte) 0x80,(byte) 0xc,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x7,(byte) 0xe0,(byte) 0x1e,(byte) 0x38, +(byte) 0x38,(byte) 0x8,(byte) 0x60,(byte) 0x4,(byte) 0x60,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x60,(byte) 0x4,(byte) 0x60,(byte) 0x4,(byte) 0x38,(byte) 0xc,(byte) 0x1c,(byte) 0x3c,(byte) 0x7,(byte) 0xe4, +}; + +static final BitmapCharRec ch199 = new BitmapCharRec(14,23,-1,6,16,ch199data); + +/* char: 0xc6 */ + +static final byte[] ch198data = { +(byte) 0xf9,(byte) 0xff,(byte) 0xf0,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0x10,(byte) 0x60,(byte) 0x10,(byte) 0x10,(byte) 0x60,(byte) 0x10,(byte) 0x18,(byte) 0x60,(byte) 0x0,(byte) 0x8, +(byte) 0x60,(byte) 0x0,(byte) 0xf,(byte) 0xe0,(byte) 0x80,(byte) 0xc,(byte) 0x60,(byte) 0x80,(byte) 0x4,(byte) 0x7f,(byte) 0x80,(byte) 0x4,(byte) 0x60,(byte) 0x80,(byte) 0x6,(byte) 0x60, +(byte) 0x80,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x20,(byte) 0x1,(byte) 0x60,(byte) 0x20,(byte) 0x1,(byte) 0xe0,(byte) 0x60, +(byte) 0x3,(byte) 0xff,(byte) 0xe0, +}; + +static final BitmapCharRec ch198 = new BitmapCharRec(20,17,0,0,21,ch198data); + +/* char: 0xc5 */ + +static final byte[] ch197data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x2,(byte) 0x20,(byte) 0x0,(byte) 0x2,(byte) 0x20,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch197 = new BitmapCharRec(17,21,0,0,17,ch197data); + +/* char: 0xc4 */ + +static final byte[] ch196data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch196 = new BitmapCharRec(17,21,0,0,17,ch196data); + +/* char: 0xc3 */ + +static final byte[] ch195data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x7,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x4,(byte) 0xe0,(byte) 0x0,(byte) 0x3,(byte) 0x90,(byte) 0x0, +}; + +static final BitmapCharRec ch195 = new BitmapCharRec(17,21,0,0,17,ch195data); + +/* char: 0xc2 */ + +static final byte[] ch194data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x8,(byte) 0x10,(byte) 0x0,(byte) 0x6,(byte) 0x60,(byte) 0x0,(byte) 0x3,(byte) 0xc0,(byte) 0x0,(byte) 0x1, +(byte) 0x80,(byte) 0x0, +}; + +static final BitmapCharRec ch194 = new BitmapCharRec(17,22,0,0,17,ch194data); + +/* char: 0xc1 */ + +static final byte[] ch193data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x0, +(byte) 0x30,(byte) 0x0, +}; + +static final BitmapCharRec ch193 = new BitmapCharRec(17,22,0,0,17,ch193data); + +/* char: 0xc0 */ + +static final byte[] ch192data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x20,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x3,(byte) 0x80,(byte) 0x0,(byte) 0x3, +(byte) 0x0,(byte) 0x0, +}; + +static final BitmapCharRec ch192 = new BitmapCharRec(17,22,0,0,17,ch192data); + +/* char: 0xbf */ + +static final byte[] ch191data = { +(byte) 0x3e,(byte) 0x63,(byte) 0xc1,(byte) 0xc3,(byte) 0xc3,(byte) 0xe0,(byte) 0x70,(byte) 0x30,(byte) 0x38,(byte) 0x18,(byte) 0x18,(byte) 0x8,(byte) 0x8,(byte) 0x0,(byte) 0x0,(byte) 0xc, +(byte) 0xc, +}; + +static final BitmapCharRec ch191 = new BitmapCharRec(8,17,-1,5,11,ch191data); + +/* char: 0xbe */ + +static final byte[] ch190data = { +(byte) 0x18,(byte) 0x2,(byte) 0x0,(byte) 0x8,(byte) 0x2,(byte) 0x0,(byte) 0xc,(byte) 0x7f,(byte) 0x80,(byte) 0x4,(byte) 0x22,(byte) 0x0,(byte) 0x6,(byte) 0x32,(byte) 0x0,(byte) 0x3, +(byte) 0x12,(byte) 0x0,(byte) 0x1,(byte) 0xa,(byte) 0x0,(byte) 0x71,(byte) 0x8e,(byte) 0x0,(byte) 0x88,(byte) 0x86,(byte) 0x0,(byte) 0x8c,(byte) 0xc2,(byte) 0x0,(byte) 0xc,(byte) 0x60, +(byte) 0x0,(byte) 0x8,(byte) 0x20,(byte) 0x0,(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0x8,(byte) 0x10,(byte) 0x0,(byte) 0x8c,(byte) 0x18,(byte) 0x0,(byte) 0x4c,(byte) 0xc,(byte) 0x0, +(byte) 0x38,(byte) 0x4,(byte) 0x0, +}; + +static final BitmapCharRec ch190 = new BitmapCharRec(17,17,0,0,18,ch190data); + +/* char: 0xbd */ + +static final byte[] ch189data = { +(byte) 0x30,(byte) 0x7e,(byte) 0x10,(byte) 0x22,(byte) 0x18,(byte) 0x10,(byte) 0x8,(byte) 0x18,(byte) 0xc,(byte) 0x8,(byte) 0x6,(byte) 0x4,(byte) 0x2,(byte) 0x6,(byte) 0xfb,(byte) 0x46, +(byte) 0x21,(byte) 0x26,(byte) 0x21,(byte) 0x9c,(byte) 0x20,(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x20,(byte) 0x60,(byte) 0x20,(byte) 0x20,(byte) 0xa0,(byte) 0x30,(byte) 0x60,(byte) 0x18, +(byte) 0x20,(byte) 0x8, +}; + +static final BitmapCharRec ch189 = new BitmapCharRec(15,17,-1,0,18,ch189data); + +/* char: 0xbc */ + +static final byte[] ch188data = { +(byte) 0x30,(byte) 0x4,(byte) 0x10,(byte) 0x4,(byte) 0x18,(byte) 0xff,(byte) 0x8,(byte) 0x44,(byte) 0xc,(byte) 0x64,(byte) 0x6,(byte) 0x24,(byte) 0x2,(byte) 0x14,(byte) 0xfb,(byte) 0x1c, +(byte) 0x21,(byte) 0xc,(byte) 0x21,(byte) 0x84,(byte) 0x20,(byte) 0xc0,(byte) 0x20,(byte) 0x40,(byte) 0x20,(byte) 0x60,(byte) 0x20,(byte) 0x20,(byte) 0xa0,(byte) 0x30,(byte) 0x60,(byte) 0x18, +(byte) 0x20,(byte) 0x8, +}; + +static final BitmapCharRec ch188 = new BitmapCharRec(16,17,-1,0,18,ch188data); + +/* char: 0xbb */ + +static final byte[] ch187data = { +(byte) 0x88,(byte) 0x0,(byte) 0xcc,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x19,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0x33,(byte) 0x0,(byte) 0x66,(byte) 0x0, +(byte) 0xcc,(byte) 0x0,(byte) 0x88,(byte) 0x0, +}; + +static final BitmapCharRec ch187 = new BitmapCharRec(9,10,-2,-1,12,ch187data); + +/* char: 0xba */ + +static final byte[] ch186data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x78,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0x78, +}; + +static final BitmapCharRec ch186 = new BitmapCharRec(6,9,-1,-8,8,ch186data); + +/* char: 0xb9 */ + +static final byte[] ch185data = { +(byte) 0xf8,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0x20,(byte) 0xa0,(byte) 0x60,(byte) 0x20, +}; + +static final BitmapCharRec ch185 = new BitmapCharRec(5,10,-1,-7,7,ch185data); + +/* char: 0xb8 */ + +static final byte[] ch184data = { +(byte) 0x78,(byte) 0xcc,(byte) 0xc,(byte) 0x3c,(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch184 = new BitmapCharRec(6,6,-1,6,8,ch184data); + +/* char: 0xb7 */ + +static final byte[] ch183data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch183 = new BitmapCharRec(2,2,-2,-6,6,ch183data); + +/* char: 0xb6 */ + +static final byte[] ch182data = { +(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0, +(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x9,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x39,(byte) 0x0,(byte) 0x79,(byte) 0x0,(byte) 0x79,(byte) 0x0,(byte) 0xf9,(byte) 0x0, +(byte) 0xf9,(byte) 0x0,(byte) 0xf9,(byte) 0x0,(byte) 0x79,(byte) 0x0,(byte) 0x79,(byte) 0x0,(byte) 0x39,(byte) 0x0,(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch182 = new BitmapCharRec(9,22,-1,5,11,ch182data); + +/* char: 0xb5 */ + +static final byte[] ch181data = { +(byte) 0x40,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x0,(byte) 0x5c,(byte) 0xe0,(byte) 0x7e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0xe1,(byte) 0xc0, +}; + +static final BitmapCharRec ch181 = new BitmapCharRec(11,17,-1,5,13,ch181data); + +/* char: 0xb4 */ + +static final byte[] ch180data = { +(byte) 0x80,(byte) 0x60,(byte) 0x38,(byte) 0x18, +}; + +static final BitmapCharRec ch180 = new BitmapCharRec(5,4,-2,-13,8,ch180data); + +/* char: 0xb3 */ + +static final byte[] ch179data = { +(byte) 0x70,(byte) 0x88,(byte) 0x8c,(byte) 0xc,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x8c,(byte) 0x4c,(byte) 0x38, +}; + +static final BitmapCharRec ch179 = new BitmapCharRec(6,10,0,-7,7,ch179data); + +/* char: 0xb2 */ + +static final byte[] ch178data = { +(byte) 0xfc,(byte) 0x44,(byte) 0x20,(byte) 0x30,(byte) 0x10,(byte) 0x8,(byte) 0xc,(byte) 0x8c,(byte) 0x4c,(byte) 0x38, +}; + +static final BitmapCharRec ch178 = new BitmapCharRec(6,10,0,-7,7,ch178data); + +/* char: 0xb1 */ + +static final byte[] ch177data = { +(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch177 = new BitmapCharRec(12,15,-1,0,14,ch177data); + +/* char: 0xb0 */ + +static final byte[] ch176data = { +(byte) 0x38,(byte) 0x44,(byte) 0x82,(byte) 0x82,(byte) 0x82,(byte) 0x44,(byte) 0x38, +}; + +static final BitmapCharRec ch176 = new BitmapCharRec(7,7,-1,-10,9,ch176data); + +/* char: 0xaf */ + +static final byte[] ch175data = { +(byte) 0xfc,(byte) 0xfc, +}; + +static final BitmapCharRec ch175 = new BitmapCharRec(6,2,-1,-14,8,ch175data); + +/* char: 0xae */ + +static final byte[] ch174data = { +(byte) 0x7,(byte) 0xf0,(byte) 0x0,(byte) 0x1c,(byte) 0x1c,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x60,(byte) 0x3,(byte) 0x0,(byte) 0x47,(byte) 0x19,(byte) 0x0,(byte) 0xc2, +(byte) 0x31,(byte) 0x80,(byte) 0x82,(byte) 0x20,(byte) 0x80,(byte) 0x82,(byte) 0x40,(byte) 0x80,(byte) 0x83,(byte) 0xe0,(byte) 0x80,(byte) 0x82,(byte) 0x30,(byte) 0x80,(byte) 0x82,(byte) 0x10, +(byte) 0x80,(byte) 0xc2,(byte) 0x11,(byte) 0x80,(byte) 0x42,(byte) 0x31,(byte) 0x0,(byte) 0x67,(byte) 0xe3,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x1c,(byte) 0x1c,(byte) 0x0, +(byte) 0x7,(byte) 0xf0,(byte) 0x0, +}; + +static final BitmapCharRec ch174 = new BitmapCharRec(17,17,-1,0,19,ch174data); + +/* char: 0xad */ + +static final byte[] ch173data = { +(byte) 0xfe,(byte) 0xfe, +}; + +static final BitmapCharRec ch173 = new BitmapCharRec(7,2,-1,-5,9,ch173data); + +/* char: 0xac */ + +static final byte[] ch172data = { +(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch172 = new BitmapCharRec(12,7,-1,-3,14,ch172data); + +/* char: 0xab */ + +static final byte[] ch171data = { +(byte) 0x8,(byte) 0x80,(byte) 0x19,(byte) 0x80,(byte) 0x33,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0xcc,(byte) 0x0,(byte) 0xcc,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x33,(byte) 0x0, +(byte) 0x19,(byte) 0x80,(byte) 0x8,(byte) 0x80, +}; + +static final BitmapCharRec ch171 = new BitmapCharRec(9,10,-2,-1,13,ch171data); + +/* char: 0xaa */ + +static final byte[] ch170data = { +(byte) 0x7e,(byte) 0x0,(byte) 0x76,(byte) 0xcc,(byte) 0xcc,(byte) 0x7c,(byte) 0xc,(byte) 0xcc,(byte) 0x78, +}; + +static final BitmapCharRec ch170 = new BitmapCharRec(7,9,0,-8,8,ch170data); + +/* char: 0xa9 */ + +static final byte[] ch169data = { +(byte) 0x7,(byte) 0xf0,(byte) 0x0,(byte) 0x1c,(byte) 0x1c,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x61,(byte) 0xc3,(byte) 0x0,(byte) 0x47,(byte) 0x71,(byte) 0x0,(byte) 0xc4, +(byte) 0x19,(byte) 0x80,(byte) 0x8c,(byte) 0x0,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x80,(byte) 0x88,(byte) 0x0,(byte) 0x80,(byte) 0x8c,(byte) 0x0, +(byte) 0x80,(byte) 0xc4,(byte) 0x19,(byte) 0x80,(byte) 0x47,(byte) 0x31,(byte) 0x0,(byte) 0x61,(byte) 0xe3,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x1c,(byte) 0x1c,(byte) 0x0, +(byte) 0x7,(byte) 0xf0,(byte) 0x0, +}; + +static final BitmapCharRec ch169 = new BitmapCharRec(17,17,-1,0,19,ch169data); + +/* char: 0xa8 */ + +static final byte[] ch168data = { +(byte) 0xcc,(byte) 0xcc, +}; + +static final BitmapCharRec ch168 = new BitmapCharRec(6,2,-1,-14,8,ch168data); + +/* char: 0xa7 */ + +static final byte[] ch167data = { +(byte) 0x38,(byte) 0x64,(byte) 0x62,(byte) 0x6,(byte) 0xe,(byte) 0x1c,(byte) 0x38,(byte) 0x74,(byte) 0xe2,(byte) 0xc3,(byte) 0x83,(byte) 0x87,(byte) 0x4e,(byte) 0x3c,(byte) 0x38,(byte) 0x70, +(byte) 0x60,(byte) 0x46,(byte) 0x26,(byte) 0x1c, +}; + +static final BitmapCharRec ch167 = new BitmapCharRec(8,20,-2,2,12,ch167data); + +/* char: 0xa6 */ + +static final byte[] ch166data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch166 = new BitmapCharRec(2,17,-2,0,6,ch166data); + +/* char: 0xa5 */ + +static final byte[] ch165data = { +(byte) 0xf,(byte) 0xc0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x1f,(byte) 0xe0,(byte) 0x3,(byte) 0x0,(byte) 0x1f,(byte) 0xe0, +(byte) 0x3,(byte) 0x0,(byte) 0x7,(byte) 0x80,(byte) 0xc,(byte) 0x80,(byte) 0xc,(byte) 0xc0,(byte) 0x18,(byte) 0x40,(byte) 0x18,(byte) 0x60,(byte) 0x30,(byte) 0x20,(byte) 0x70,(byte) 0x30, +(byte) 0xf8,(byte) 0x7c, +}; + +static final BitmapCharRec ch165 = new BitmapCharRec(14,17,0,0,14,ch165data); + +/* char: 0xa4 */ + +static final byte[] ch164data = { +(byte) 0xc0,(byte) 0x60,(byte) 0xee,(byte) 0xe0,(byte) 0x7f,(byte) 0xc0,(byte) 0x31,(byte) 0x80,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x31,(byte) 0x80,(byte) 0x7f,(byte) 0xc0,(byte) 0xee,(byte) 0xe0,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch164 = new BitmapCharRec(11,12,-1,-3,13,ch164data); + +/* char: 0xa3 */ + +static final byte[] ch163data = { +(byte) 0xe7,(byte) 0x80,(byte) 0xbe,(byte) 0xc0,(byte) 0x78,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0x30,(byte) 0x0,(byte) 0xfc,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x31,(byte) 0x80,(byte) 0x19,(byte) 0x80, +(byte) 0xf,(byte) 0x0, +}; + +static final BitmapCharRec ch163 = new BitmapCharRec(10,17,-1,0,12,ch163data); + +/* char: 0xa2 */ + +static final byte[] ch162data = { +(byte) 0x40,(byte) 0x0,(byte) 0x40,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xd0,(byte) 0x0,(byte) 0xc8,(byte) 0x0,(byte) 0xc8,(byte) 0x0, +(byte) 0xc8,(byte) 0x0,(byte) 0xc4,(byte) 0x0,(byte) 0xc4,(byte) 0x0,(byte) 0x43,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0x1f,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x1,(byte) 0x0, +}; + +static final BitmapCharRec ch162 = new BitmapCharRec(9,16,-1,2,12,ch162data); + +/* char: 0xa1 */ + +static final byte[] ch161data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch161 = new BitmapCharRec(2,17,-4,5,8,ch161data); + +/* char: 0xa0 */ + +static final BitmapCharRec ch160 = new BitmapCharRec(0,0,0,0,6,null); + +/* char: 0x7e '~' */ + +static final byte[] ch126data = { +(byte) 0x83,(byte) 0x80,(byte) 0xc7,(byte) 0xc0,(byte) 0x7c,(byte) 0x60,(byte) 0x38,(byte) 0x20, +}; + +static final BitmapCharRec ch126 = new BitmapCharRec(11,4,-1,-5,13,ch126data); + +/* char: 0x7d '}' */ + +static final byte[] ch125data = { +(byte) 0xe0,(byte) 0x30,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x8,(byte) 0xc,(byte) 0x4,(byte) 0x3,(byte) 0x4,(byte) 0xc,(byte) 0x8,(byte) 0x18, +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x30,(byte) 0xe0, +}; + +static final BitmapCharRec ch125 = new BitmapCharRec(8,22,-1,5,10,ch125data); + +/* char: 0x7c '|' */ + +static final byte[] ch124data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch124 = new BitmapCharRec(2,17,-2,0,6,ch124data); + +/* char: 0x7b '{' */ + +static final byte[] ch123data = { +(byte) 0x7,(byte) 0xc,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x10,(byte) 0x30,(byte) 0x20,(byte) 0xc0,(byte) 0x20,(byte) 0x30,(byte) 0x10,(byte) 0x18, +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xc,(byte) 0x7, +}; + +static final BitmapCharRec ch123 = new BitmapCharRec(8,22,-1,5,10,ch123data); + +/* char: 0x7a 'z' */ + +static final byte[] ch122data = { +(byte) 0xff,(byte) 0xc3,(byte) 0x61,(byte) 0x70,(byte) 0x30,(byte) 0x38,(byte) 0x18,(byte) 0x1c,(byte) 0xe,(byte) 0x86,(byte) 0xc3,(byte) 0xff, +}; + +static final BitmapCharRec ch122 = new BitmapCharRec(8,12,-1,0,10,ch122data); + +/* char: 0x79 'y' */ + +static final byte[] ch121data = { +(byte) 0xe0,(byte) 0x0,(byte) 0xf0,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x8,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x1a,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x31,(byte) 0x0,(byte) 0x30,(byte) 0x80,(byte) 0x30,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x60,(byte) 0xc0, +(byte) 0xf1,(byte) 0xe0, +}; + +static final BitmapCharRec ch121 = new BitmapCharRec(11,17,0,5,11,ch121data); + +/* char: 0x78 'x' */ + +static final byte[] ch120data = { +(byte) 0xf1,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x21,(byte) 0x80,(byte) 0x33,(byte) 0x80,(byte) 0x1b,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x1a,(byte) 0x0, +(byte) 0x39,(byte) 0x0,(byte) 0x31,(byte) 0x80,(byte) 0x60,(byte) 0xc0,(byte) 0xf1,(byte) 0xe0, +}; + +static final BitmapCharRec ch120 = new BitmapCharRec(11,12,-1,0,13,ch120data); + +/* char: 0x77 'w' */ + +static final byte[] ch119data = { +(byte) 0x4,(byte) 0x10,(byte) 0x0,(byte) 0xe,(byte) 0x38,(byte) 0x0,(byte) 0xe,(byte) 0x38,(byte) 0x0,(byte) 0x1a,(byte) 0x28,(byte) 0x0,(byte) 0x1a,(byte) 0x64,(byte) 0x0,(byte) 0x19, +(byte) 0x64,(byte) 0x0,(byte) 0x31,(byte) 0x64,(byte) 0x0,(byte) 0x30,(byte) 0xc2,(byte) 0x0,(byte) 0x30,(byte) 0xc2,(byte) 0x0,(byte) 0x60,(byte) 0xc2,(byte) 0x0,(byte) 0x60,(byte) 0xc3, +(byte) 0x0,(byte) 0xf1,(byte) 0xe7,(byte) 0x80, +}; + +static final BitmapCharRec ch119 = new BitmapCharRec(17,12,0,0,17,ch119data); + +/* char: 0x76 'v' */ + +static final byte[] ch118data = { +(byte) 0x4,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0xe,(byte) 0x0,(byte) 0x1a,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x19,(byte) 0x0,(byte) 0x31,(byte) 0x0,(byte) 0x30,(byte) 0x80, +(byte) 0x30,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x60,(byte) 0xc0,(byte) 0xf1,(byte) 0xe0, +}; + +static final BitmapCharRec ch118 = new BitmapCharRec(11,12,0,0,11,ch118data); + +/* char: 0x75 'u' */ + +static final byte[] ch117data = { +(byte) 0x1c,(byte) 0xe0,(byte) 0x3e,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0xe1,(byte) 0xc0, +}; + +static final BitmapCharRec ch117 = new BitmapCharRec(11,12,-1,0,13,ch117data); + +/* char: 0x74 't' */ + +static final byte[] ch116data = { +(byte) 0x1c,(byte) 0x32,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0xfe,(byte) 0x70,(byte) 0x30,(byte) 0x10, +}; + +static final BitmapCharRec ch116 = new BitmapCharRec(7,15,0,0,7,ch116data); + +/* char: 0x73 's' */ + +static final byte[] ch115data = { +(byte) 0xf8,(byte) 0xc6,(byte) 0x83,(byte) 0x3,(byte) 0x7,(byte) 0x1e,(byte) 0x7c,(byte) 0x70,(byte) 0xe0,(byte) 0xc2,(byte) 0x66,(byte) 0x3e, +}; + +static final BitmapCharRec ch115 = new BitmapCharRec(8,12,-1,0,10,ch115data); + +/* char: 0x72 'r' */ + +static final byte[] ch114data = { +(byte) 0xf0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x76,(byte) 0x6e,(byte) 0xe6, +}; + +static final BitmapCharRec ch114 = new BitmapCharRec(7,12,-1,0,8,ch114data); + +/* char: 0x71 'q' */ + +static final byte[] ch113data = { +(byte) 0x3,(byte) 0xc0,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1d,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80, +(byte) 0x1d,(byte) 0x80, +}; + +static final BitmapCharRec ch113 = new BitmapCharRec(10,17,-1,5,12,ch113data); + +/* char: 0x70 'p' */ + +static final byte[] ch112data = { +(byte) 0xf0,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x6e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80, +(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80, +(byte) 0xee,(byte) 0x0, +}; + +static final BitmapCharRec ch112 = new BitmapCharRec(10,17,-1,5,12,ch112data); + +/* char: 0x6f 'o' */ + +static final byte[] ch111data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch111 = new BitmapCharRec(10,12,-1,0,12,ch111data); + +/* char: 0x6e 'n' */ + +static final byte[] ch110data = { +(byte) 0xf1,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x6f,(byte) 0x80,(byte) 0xe7,(byte) 0x0, +}; + +static final BitmapCharRec ch110 = new BitmapCharRec(11,12,-1,0,13,ch110data); + +/* char: 0x6d 'm' */ + +static final byte[] ch109data = { +(byte) 0xf1,(byte) 0xe3,(byte) 0xc0,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60, +(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x60,(byte) 0xc1,(byte) 0x80,(byte) 0x71,(byte) 0xe3,(byte) 0x80,(byte) 0x6f,(byte) 0x9f, +(byte) 0x0,(byte) 0xe7,(byte) 0xe,(byte) 0x0, +}; + +static final BitmapCharRec ch109 = new BitmapCharRec(18,12,-1,0,20,ch109data); + +/* char: 0x6c 'l' */ + +static final byte[] ch108data = { +(byte) 0xf0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60, +(byte) 0xe0, +}; + +static final BitmapCharRec ch108 = new BitmapCharRec(4,17,-1,0,6,ch108data); + +/* char: 0x6b 'k' */ + +static final byte[] ch107data = { +(byte) 0xf3,(byte) 0xe0,(byte) 0x61,(byte) 0xc0,(byte) 0x63,(byte) 0x80,(byte) 0x67,(byte) 0x0,(byte) 0x6e,(byte) 0x0,(byte) 0x6c,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0x68,(byte) 0x0, +(byte) 0x64,(byte) 0x0,(byte) 0x66,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0xc0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0, +(byte) 0xe0,(byte) 0x0, +}; + +static final BitmapCharRec ch107 = new BitmapCharRec(11,17,-1,0,12,ch107data); + +/* char: 0x6a 'j' */ + +static final byte[] ch106data = { +(byte) 0xc0,(byte) 0xe0,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0x70,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x30, +}; + +static final BitmapCharRec ch106 = new BitmapCharRec(4,22,0,5,6,ch106data); + +/* char: 0x69 'i' */ + +static final byte[] ch105data = { +(byte) 0xf0,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0x60,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x60, +(byte) 0x60, +}; + +static final BitmapCharRec ch105 = new BitmapCharRec(4,17,-1,0,6,ch105data); + +/* char: 0x68 'h' */ + +static final byte[] ch104data = { +(byte) 0xf1,(byte) 0xe0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x71,(byte) 0xc0,(byte) 0x6f,(byte) 0x80,(byte) 0x67,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0, +(byte) 0xe0,(byte) 0x0, +}; + +static final BitmapCharRec ch104 = new BitmapCharRec(11,17,-1,0,13,ch104data); + +/* char: 0x67 'g' */ + +static final byte[] ch103data = { +(byte) 0x3f,(byte) 0x0,(byte) 0xf1,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0x3f,(byte) 0xc0,(byte) 0x7f,(byte) 0x0,(byte) 0x60,(byte) 0x0, +(byte) 0x30,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0, +(byte) 0x1f,(byte) 0xc0, +}; + +static final BitmapCharRec ch103 = new BitmapCharRec(11,17,-1,5,12,ch103data); + +/* char: 0x66 'f' */ + +static final byte[] ch102data = { +(byte) 0x78,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0xfe,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x16, +(byte) 0xe, +}; + +static final BitmapCharRec ch102 = new BitmapCharRec(7,17,0,0,7,ch102data); + +/* char: 0x65 'e' */ + +static final byte[] ch101data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xff,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x0,(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch101 = new BitmapCharRec(9,12,-1,0,11,ch101data); + +/* char: 0x64 'd' */ + +static final byte[] ch100data = { +(byte) 0x1e,(byte) 0xc0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0xc1,(byte) 0x80, +(byte) 0xc1,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x1d,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80, +(byte) 0x3,(byte) 0x80, +}; + +static final BitmapCharRec ch100 = new BitmapCharRec(10,17,-1,0,12,ch100data); + +/* char: 0x63 'c' */ + +static final byte[] ch99data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7f,(byte) 0x0,(byte) 0x70,(byte) 0x80,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0x41,(byte) 0x80,(byte) 0x63,(byte) 0x80,(byte) 0x1f,(byte) 0x0, +}; + +static final BitmapCharRec ch99 = new BitmapCharRec(9,12,-1,0,11,ch99data); + +/* char: 0x62 'b' */ + +static final byte[] ch98data = { +(byte) 0x5e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0,(byte) 0x60,(byte) 0xc0, +(byte) 0x60,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x73,(byte) 0x80,(byte) 0x6e,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0, +(byte) 0xe0,(byte) 0x0, +}; + +static final BitmapCharRec ch98 = new BitmapCharRec(10,17,-1,0,12,ch98data); + +/* char: 0x61 'a' */ + +static final byte[] ch97data = { +(byte) 0x71,(byte) 0x80,(byte) 0xfb,(byte) 0x0,(byte) 0xc7,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x3b,(byte) 0x0,(byte) 0xf,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x67,(byte) 0x0,(byte) 0x3e,(byte) 0x0, +}; + +static final BitmapCharRec ch97 = new BitmapCharRec(9,12,-1,0,11,ch97data); + +/* char: 0x60 '`' */ + +static final byte[] ch96data = { +(byte) 0x60,(byte) 0xe0,(byte) 0x80,(byte) 0xc0,(byte) 0x60, +}; + +static final BitmapCharRec ch96 = new BitmapCharRec(3,5,-2,-12,7,ch96data); + +/* char: 0x5f '_' */ + +static final byte[] ch95data = { +(byte) 0xff,(byte) 0xf8,(byte) 0xff,(byte) 0xf8, +}; + +static final BitmapCharRec ch95 = new BitmapCharRec(13,2,0,5,13,ch95data); + +/* char: 0x5e '^' */ + +static final byte[] ch94data = { +(byte) 0x80,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x41,(byte) 0x0,(byte) 0x63,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x36,(byte) 0x0,(byte) 0x14,(byte) 0x0,(byte) 0x1c,(byte) 0x0, +(byte) 0x8,(byte) 0x0, +}; + +static final BitmapCharRec ch94 = new BitmapCharRec(9,9,-1,-8,11,ch94data); + +/* char: 0x5d ']' */ + +static final byte[] ch93data = { +(byte) 0xf8,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18, +(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0xf8, +}; + +static final BitmapCharRec ch93 = new BitmapCharRec(5,21,-1,4,8,ch93data); + +/* char: 0x5c '\' */ + +static final byte[] ch92data = { +(byte) 0x6,(byte) 0x6,(byte) 0x4,(byte) 0xc,(byte) 0xc,(byte) 0x8,(byte) 0x18,(byte) 0x18,(byte) 0x10,(byte) 0x30,(byte) 0x30,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0x40,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch92 = new BitmapCharRec(7,17,0,0,7,ch92data); + +/* char: 0x5b '[' */ + +static final byte[] ch91data = { +(byte) 0xf8,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xf8, +}; + +static final BitmapCharRec ch91 = new BitmapCharRec(5,21,-2,4,8,ch91data); + +/* char: 0x5a 'Z' */ + +static final byte[] ch90data = { +(byte) 0xff,(byte) 0xf8,(byte) 0xe0,(byte) 0x18,(byte) 0x70,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x38,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x7,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x80,(byte) 0x1,(byte) 0xc0,(byte) 0x80,(byte) 0xc0,(byte) 0x80,(byte) 0xe0,(byte) 0xc0,(byte) 0x70, +(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch90 = new BitmapCharRec(13,17,-1,0,15,ch90data); + +/* char: 0x59 'Y' */ + +static final byte[] ch89data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x3,(byte) 0xc0, +(byte) 0x3,(byte) 0x40,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x20,(byte) 0xc,(byte) 0x30,(byte) 0x1c,(byte) 0x10,(byte) 0x18,(byte) 0x18,(byte) 0x38,(byte) 0x8,(byte) 0x30,(byte) 0xc, +(byte) 0xfc,(byte) 0x3f, +}; + +static final BitmapCharRec ch89 = new BitmapCharRec(16,17,0,0,16,ch89data); + +/* char: 0x58 'X' */ + +static final byte[] ch88data = { +(byte) 0xfc,(byte) 0xf,(byte) 0xc0,(byte) 0x30,(byte) 0x3,(byte) 0x80,(byte) 0x18,(byte) 0x7,(byte) 0x0,(byte) 0x8,(byte) 0xe,(byte) 0x0,(byte) 0x4,(byte) 0xc,(byte) 0x0,(byte) 0x6, +(byte) 0x18,(byte) 0x0,(byte) 0x2,(byte) 0x38,(byte) 0x0,(byte) 0x1,(byte) 0x70,(byte) 0x0,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0, +(byte) 0x0,(byte) 0x3,(byte) 0xa0,(byte) 0x0,(byte) 0x3,(byte) 0x10,(byte) 0x0,(byte) 0x6,(byte) 0x8,(byte) 0x0,(byte) 0xe,(byte) 0xc,(byte) 0x0,(byte) 0x1c,(byte) 0x6,(byte) 0x0, +(byte) 0x7e,(byte) 0xf,(byte) 0x80, +}; + +static final BitmapCharRec ch88 = new BitmapCharRec(18,17,0,0,18,ch88data); + +/* char: 0x57 'W' */ + +static final byte[] ch87data = { +(byte) 0x1,(byte) 0x83,(byte) 0x0,(byte) 0x1,(byte) 0x83,(byte) 0x0,(byte) 0x1,(byte) 0x83,(byte) 0x80,(byte) 0x3,(byte) 0x87,(byte) 0x80,(byte) 0x3,(byte) 0x46,(byte) 0x80,(byte) 0x3, +(byte) 0x46,(byte) 0xc0,(byte) 0x6,(byte) 0x46,(byte) 0x40,(byte) 0x6,(byte) 0x4c,(byte) 0x40,(byte) 0x6,(byte) 0x4c,(byte) 0x60,(byte) 0xc,(byte) 0x2c,(byte) 0x60,(byte) 0xc,(byte) 0x2c, +(byte) 0x20,(byte) 0x18,(byte) 0x2c,(byte) 0x20,(byte) 0x18,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x18,(byte) 0x10,(byte) 0x30,(byte) 0x18,(byte) 0x10,(byte) 0x30,(byte) 0x18,(byte) 0x18, +(byte) 0xfc,(byte) 0x7e,(byte) 0x7e, +}; + +static final BitmapCharRec ch87 = new BitmapCharRec(23,17,0,0,23,ch87data); + +/* char: 0x56 'V' */ + +static final byte[] ch86data = { +(byte) 0x1,(byte) 0x80,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x0,(byte) 0x3,(byte) 0xc0,(byte) 0x0,(byte) 0x3,(byte) 0x40,(byte) 0x0,(byte) 0x3, +(byte) 0x60,(byte) 0x0,(byte) 0x6,(byte) 0x20,(byte) 0x0,(byte) 0x6,(byte) 0x20,(byte) 0x0,(byte) 0x6,(byte) 0x30,(byte) 0x0,(byte) 0xc,(byte) 0x10,(byte) 0x0,(byte) 0xc,(byte) 0x18, +(byte) 0x0,(byte) 0x18,(byte) 0x8,(byte) 0x0,(byte) 0x18,(byte) 0x8,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x30,(byte) 0x4,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0, +(byte) 0xfc,(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch86 = new BitmapCharRec(17,17,0,0,17,ch86data); + +/* char: 0x55 'U' */ + +static final byte[] ch85data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x30,(byte) 0x18,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xfc,(byte) 0x1f, +}; + +static final BitmapCharRec ch85 = new BitmapCharRec(16,17,-1,0,18,ch85data); + +/* char: 0x54 'T' */ + +static final byte[] ch84data = { +(byte) 0xf,(byte) 0xc0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x83,(byte) 0x4,(byte) 0x83,(byte) 0x4,(byte) 0xc3,(byte) 0xc, +(byte) 0xff,(byte) 0xfc, +}; + +static final BitmapCharRec ch84 = new BitmapCharRec(14,17,-1,0,16,ch84data); + +/* char: 0x53 'S' */ + +static final byte[] ch83data = { +(byte) 0x9e,(byte) 0x0,(byte) 0xf1,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0x80,(byte) 0x60,(byte) 0x80,(byte) 0x60,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0xe0,(byte) 0x3,(byte) 0xc0, +(byte) 0xf,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0xe0,(byte) 0x0,(byte) 0xc0,(byte) 0x40,(byte) 0xc0,(byte) 0x40,(byte) 0xc0,(byte) 0xc0,(byte) 0x63,(byte) 0xc0, +(byte) 0x1e,(byte) 0x40, +}; + +static final BitmapCharRec ch83 = new BitmapCharRec(11,17,-1,0,13,ch83data); + +/* char: 0x52 'R' */ + +static final byte[] ch82data = { +(byte) 0xfc,(byte) 0x1e,(byte) 0x30,(byte) 0x1c,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0xc0,(byte) 0x31,(byte) 0xc0,(byte) 0x33,(byte) 0x80, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70, +(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch82 = new BitmapCharRec(15,17,-1,0,16,ch82data); + +/* char: 0x51 'Q' */ + +static final byte[] ch81data = { +(byte) 0x0,(byte) 0xf,(byte) 0x0,(byte) 0x38,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0xe0,(byte) 0x1,(byte) 0xc0,(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c, +(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38,(byte) 0x7,(byte) 0xe0, +}; + +static final BitmapCharRec ch81 = new BitmapCharRec(16,22,-1,5,18,ch81data); + +/* char: 0x50 'P' */ + +static final byte[] ch80data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70, +(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch80 = new BitmapCharRec(13,17,-1,0,15,ch80data); + +/* char: 0x4f 'O' */ + +static final byte[] ch79data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1c,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3, +(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0xc0,(byte) 0x3,(byte) 0x60,(byte) 0x6,(byte) 0x60,(byte) 0x6,(byte) 0x38,(byte) 0x1c,(byte) 0x1c,(byte) 0x38, +(byte) 0x7,(byte) 0xe0, +}; + +static final BitmapCharRec ch79 = new BitmapCharRec(16,17,-1,0,18,ch79data); + +/* char: 0x4e 'N' */ + +static final byte[] ch78data = { +(byte) 0xf8,(byte) 0xc,(byte) 0x20,(byte) 0x1c,(byte) 0x20,(byte) 0x1c,(byte) 0x20,(byte) 0x34,(byte) 0x20,(byte) 0x64,(byte) 0x20,(byte) 0x64,(byte) 0x20,(byte) 0xc4,(byte) 0x21,(byte) 0x84, +(byte) 0x21,(byte) 0x84,(byte) 0x23,(byte) 0x4,(byte) 0x26,(byte) 0x4,(byte) 0x26,(byte) 0x4,(byte) 0x2c,(byte) 0x4,(byte) 0x38,(byte) 0x4,(byte) 0x38,(byte) 0x4,(byte) 0x30,(byte) 0x4, +(byte) 0xf0,(byte) 0x1f, +}; + +static final BitmapCharRec ch78 = new BitmapCharRec(16,17,-1,0,18,ch78data); + +/* char: 0x4d 'M' */ + +static final byte[] ch77data = { +(byte) 0xf8,(byte) 0x21,(byte) 0xf8,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0x20,(byte) 0xd0,(byte) 0x60,(byte) 0x20,(byte) 0xd0,(byte) 0x60,(byte) 0x21, +(byte) 0x88,(byte) 0x60,(byte) 0x21,(byte) 0x88,(byte) 0x60,(byte) 0x23,(byte) 0x8,(byte) 0x60,(byte) 0x23,(byte) 0x4,(byte) 0x60,(byte) 0x26,(byte) 0x4,(byte) 0x60,(byte) 0x26,(byte) 0x2, +(byte) 0x60,(byte) 0x2c,(byte) 0x2,(byte) 0x60,(byte) 0x2c,(byte) 0x2,(byte) 0x60,(byte) 0x38,(byte) 0x1,(byte) 0x60,(byte) 0x38,(byte) 0x1,(byte) 0x60,(byte) 0x30,(byte) 0x0,(byte) 0xe0, +(byte) 0xf0,(byte) 0x0,(byte) 0xf8, +}; + +static final BitmapCharRec ch77 = new BitmapCharRec(21,17,-1,0,22,ch77data); + +/* char: 0x4c 'L' */ + +static final byte[] ch76data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0, +(byte) 0xfc,(byte) 0x0, +}; + +static final BitmapCharRec ch76 = new BitmapCharRec(13,17,-1,0,14,ch76data); + +/* char: 0x4b 'K' */ + +static final byte[] ch75data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x30,(byte) 0xe,(byte) 0x30,(byte) 0x1c,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0xe0,(byte) 0x31,(byte) 0xc0,(byte) 0x33,(byte) 0x80, +(byte) 0x3f,(byte) 0x0,(byte) 0x3e,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x31,(byte) 0x80,(byte) 0x30,(byte) 0xc0,(byte) 0x30,(byte) 0x60,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18, +(byte) 0xfc,(byte) 0x7e, +}; + +static final BitmapCharRec ch75 = new BitmapCharRec(16,17,-1,0,17,ch75data); + +/* char: 0x4a 'J' */ + +static final byte[] ch74data = { +(byte) 0x78,(byte) 0x0,(byte) 0xcc,(byte) 0x0,(byte) 0xc6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch74 = new BitmapCharRec(9,17,-1,0,11,ch74data); + +/* char: 0x49 'I' */ + +static final byte[] ch73data = { +(byte) 0xfc,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x30, +(byte) 0xfc, +}; + +static final BitmapCharRec ch73 = new BitmapCharRec(6,17,-1,0,8,ch73data); + +/* char: 0x48 'H' */ + +static final byte[] ch72data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30, +(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x3f,(byte) 0xfe,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6, +(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x30,(byte) 0x6,(byte) 0x0, +(byte) 0xfc,(byte) 0x1f,(byte) 0x80, +}; + +static final BitmapCharRec ch72 = new BitmapCharRec(17,17,-1,0,19,ch72data); + +/* char: 0x47 'G' */ + +static final byte[] ch71data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1e,(byte) 0x38,(byte) 0x38,(byte) 0x1c,(byte) 0x60,(byte) 0xc,(byte) 0x60,(byte) 0xc,(byte) 0xc0,(byte) 0xc,(byte) 0xc0,(byte) 0xc,(byte) 0xc0,(byte) 0x3f, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x60,(byte) 0x4,(byte) 0x60,(byte) 0x4,(byte) 0x38,(byte) 0xc,(byte) 0x1c,(byte) 0x3c, +(byte) 0x7,(byte) 0xe4, +}; + +static final BitmapCharRec ch71 = new BitmapCharRec(16,17,-1,0,18,ch71data); + +/* char: 0x46 'F' */ + +static final byte[] ch70data = { +(byte) 0xfc,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x20,(byte) 0x30,(byte) 0x20, +(byte) 0x3f,(byte) 0xe0,(byte) 0x30,(byte) 0x20,(byte) 0x30,(byte) 0x20,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch70 = new BitmapCharRec(12,17,-1,0,14,ch70data); + +/* char: 0x45 'E' */ + +static final byte[] ch69data = { +(byte) 0xff,(byte) 0xf8,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x8,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40, +(byte) 0x3f,(byte) 0xc0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x10,(byte) 0x30,(byte) 0x30, +(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch69 = new BitmapCharRec(13,17,-1,0,15,ch69data); + +/* char: 0x44 'D' */ + +static final byte[] ch68data = { +(byte) 0xff,(byte) 0xc0,(byte) 0x30,(byte) 0x70,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0x6, +(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0x6,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0x38,(byte) 0x30,(byte) 0x70, +(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch68 = new BitmapCharRec(15,17,-1,0,17,ch68data); + +/* char: 0x43 'C' */ + +static final byte[] ch67data = { +(byte) 0x7,(byte) 0xe0,(byte) 0x1e,(byte) 0x38,(byte) 0x38,(byte) 0x8,(byte) 0x60,(byte) 0x4,(byte) 0x60,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x60,(byte) 0x4,(byte) 0x60,(byte) 0x4,(byte) 0x38,(byte) 0xc,(byte) 0x1c,(byte) 0x3c, +(byte) 0x7,(byte) 0xe4, +}; + +static final BitmapCharRec ch67 = new BitmapCharRec(14,17,-1,0,16,ch67data); + +/* char: 0x42 'B' */ + +static final byte[] ch66data = { +(byte) 0xff,(byte) 0xe0,(byte) 0x30,(byte) 0x78,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0xc,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x38, +(byte) 0x3f,(byte) 0xe0,(byte) 0x30,(byte) 0x40,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x18,(byte) 0x30,(byte) 0x30,(byte) 0x30,(byte) 0x70, +(byte) 0xff,(byte) 0xc0, +}; + +static final BitmapCharRec ch66 = new BitmapCharRec(14,17,-1,0,16,ch66data); + +/* char: 0x41 'A' */ + +static final byte[] ch65data = { +(byte) 0xfc,(byte) 0x1f,(byte) 0x80,(byte) 0x30,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0x6,(byte) 0x0,(byte) 0x10,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0xc,(byte) 0x0,(byte) 0x8, +(byte) 0xc,(byte) 0x0,(byte) 0xf,(byte) 0xf8,(byte) 0x0,(byte) 0xc,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x18,(byte) 0x0,(byte) 0x4,(byte) 0x30,(byte) 0x0,(byte) 0x6,(byte) 0x30, +(byte) 0x0,(byte) 0x2,(byte) 0x30,(byte) 0x0,(byte) 0x2,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0x60,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0, +(byte) 0x0,(byte) 0x80,(byte) 0x0, +}; + +static final BitmapCharRec ch65 = new BitmapCharRec(17,17,0,0,17,ch65data); + +/* char: 0x40 '@' */ + +static final byte[] ch64data = { +(byte) 0x3,(byte) 0xf0,(byte) 0x0,(byte) 0xe,(byte) 0xc,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x0,(byte) 0x61,(byte) 0xde,(byte) 0x0,(byte) 0x63, +(byte) 0x7b,(byte) 0x0,(byte) 0xc6,(byte) 0x39,(byte) 0x80,(byte) 0xc6,(byte) 0x18,(byte) 0x80,(byte) 0xc6,(byte) 0x18,(byte) 0xc0,(byte) 0xc6,(byte) 0x18,(byte) 0x40,(byte) 0xc6,(byte) 0xc, +(byte) 0x40,(byte) 0xc3,(byte) 0xc,(byte) 0x40,(byte) 0xc3,(byte) 0x8c,(byte) 0x40,(byte) 0xe1,(byte) 0xfc,(byte) 0x40,(byte) 0x60,(byte) 0xec,(byte) 0xc0,(byte) 0x70,(byte) 0x0,(byte) 0x80, +(byte) 0x38,(byte) 0x1,(byte) 0x80,(byte) 0x1c,(byte) 0x3,(byte) 0x0,(byte) 0xf,(byte) 0xe,(byte) 0x0,(byte) 0x3,(byte) 0xf8,(byte) 0x0, +}; + +static final BitmapCharRec ch64 = new BitmapCharRec(18,20,-2,3,22,ch64data); + +/* char: 0x3f '?' */ + +static final byte[] ch63data = { +(byte) 0x30,(byte) 0x30,(byte) 0x0,(byte) 0x0,(byte) 0x10,(byte) 0x10,(byte) 0x10,(byte) 0x18,(byte) 0x18,(byte) 0xc,(byte) 0xe,(byte) 0x7,(byte) 0xc3,(byte) 0xc3,(byte) 0x83,(byte) 0xc6, +(byte) 0x7c, +}; + +static final BitmapCharRec ch63 = new BitmapCharRec(8,17,-2,0,11,ch63data); + +/* char: 0x3e '>' */ + +static final byte[] ch62data = { +(byte) 0xc0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0x7,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x60,(byte) 0x1,(byte) 0xc0,(byte) 0x7,(byte) 0x0, +(byte) 0x1c,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0xc0,(byte) 0x0, +}; + +static final BitmapCharRec ch62 = new BitmapCharRec(11,11,-1,-1,13,ch62data); + +/* char: 0x3d '=' */ + +static final byte[] ch61data = { +(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch61 = new BitmapCharRec(12,6,-1,-4,14,ch61data); + +/* char: 0x3c '<' */ + +static final byte[] ch60data = { +(byte) 0x0,(byte) 0x60,(byte) 0x1,(byte) 0xc0,(byte) 0x7,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x1c,(byte) 0x0, +(byte) 0x7,(byte) 0x0,(byte) 0x1,(byte) 0xc0,(byte) 0x0,(byte) 0x60, +}; + +static final BitmapCharRec ch60 = new BitmapCharRec(11,11,-1,-1,13,ch60data); + +/* char: 0x3b ';' */ + +static final byte[] ch59data = { +(byte) 0xc0,(byte) 0x60,(byte) 0x20,(byte) 0xe0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch59 = new BitmapCharRec(3,14,-2,3,7,ch59data); + +/* char: 0x3a ':' */ + +static final byte[] ch58data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch58 = new BitmapCharRec(2,11,-2,0,6,ch58data); + +/* char: 0x39 '9' */ + +static final byte[] ch57data = { +(byte) 0xf0,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1d,(byte) 0x80,(byte) 0x73,(byte) 0xc0, +(byte) 0x61,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x77,(byte) 0x80, +(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch57 = new BitmapCharRec(10,17,-1,0,12,ch57data); + +/* char: 0x38 '8' */ + +static final byte[] ch56data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x73,(byte) 0x80,(byte) 0xe1,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x41,(byte) 0xc0,(byte) 0x61,(byte) 0x80, +(byte) 0x37,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0, +(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch56 = new BitmapCharRec(10,17,-1,0,12,ch56data); + +/* char: 0x37 '7' */ + +static final byte[] ch55data = { +(byte) 0x18,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x2,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x81,(byte) 0x80,(byte) 0xc0,(byte) 0xc0,(byte) 0xff,(byte) 0xc0, +(byte) 0x7f,(byte) 0xc0, +}; + +static final BitmapCharRec ch55 = new BitmapCharRec(10,17,-1,0,12,ch55data); + +/* char: 0x36 '6' */ + +static final byte[] ch54data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x7b,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xe0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc1,(byte) 0x80,(byte) 0xf3,(byte) 0x80,(byte) 0xee,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x70,(byte) 0x0,(byte) 0x30,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0xe,(byte) 0x0, +(byte) 0x3,(byte) 0xc0, +}; + +static final BitmapCharRec ch54 = new BitmapCharRec(10,17,-1,0,12,ch54data); + +/* char: 0x35 '5' */ + +static final byte[] ch53data = { +(byte) 0x7e,(byte) 0x0,(byte) 0xe3,(byte) 0x80,(byte) 0xc1,(byte) 0x80,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x0,(byte) 0xc0,(byte) 0x1,(byte) 0xc0, +(byte) 0x3,(byte) 0x80,(byte) 0xf,(byte) 0x80,(byte) 0x7e,(byte) 0x0,(byte) 0x78,(byte) 0x0,(byte) 0x60,(byte) 0x0,(byte) 0x20,(byte) 0x0,(byte) 0x20,(byte) 0x0,(byte) 0x1f,(byte) 0x80, +(byte) 0x1f,(byte) 0xc0, +}; + +static final BitmapCharRec ch53 = new BitmapCharRec(10,17,-1,0,12,ch53data); + +/* char: 0x34 '4' */ + +static final byte[] ch52data = { +(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0,(byte) 0xc3,(byte) 0x0,(byte) 0x43,(byte) 0x0, +(byte) 0x63,(byte) 0x0,(byte) 0x23,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x13,(byte) 0x0,(byte) 0x1b,(byte) 0x0,(byte) 0xb,(byte) 0x0,(byte) 0x7,(byte) 0x0,(byte) 0x7,(byte) 0x0, +(byte) 0x3,(byte) 0x0, +}; + +static final BitmapCharRec ch52 = new BitmapCharRec(10,17,-1,0,12,ch52data); + +/* char: 0x33 '3' */ + +static final byte[] ch51data = { +(byte) 0x78,(byte) 0x0,(byte) 0xe6,(byte) 0x0,(byte) 0xc3,(byte) 0x0,(byte) 0x1,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x3,(byte) 0x80, +(byte) 0x7,(byte) 0x0,(byte) 0x1e,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x83,(byte) 0x0,(byte) 0x83,(byte) 0x0,(byte) 0x47,(byte) 0x0,(byte) 0x7e,(byte) 0x0, +(byte) 0x1c,(byte) 0x0, +}; + +static final BitmapCharRec ch51 = new BitmapCharRec(9,17,-1,0,12,ch51data); + +/* char: 0x32 '2' */ + +static final byte[] ch50data = { +(byte) 0xff,(byte) 0x80,(byte) 0xff,(byte) 0xc0,(byte) 0x60,(byte) 0x40,(byte) 0x30,(byte) 0x0,(byte) 0x18,(byte) 0x0,(byte) 0xc,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x6,(byte) 0x0, +(byte) 0x3,(byte) 0x0,(byte) 0x3,(byte) 0x0,(byte) 0x1,(byte) 0x80,(byte) 0x1,(byte) 0x80,(byte) 0x81,(byte) 0x80,(byte) 0x81,(byte) 0x80,(byte) 0x43,(byte) 0x80,(byte) 0x7f,(byte) 0x0, +(byte) 0x1c,(byte) 0x0, +}; + +static final BitmapCharRec ch50 = new BitmapCharRec(10,17,-1,0,12,ch50data); + +/* char: 0x31 '1' */ + +static final byte[] ch49data = { +(byte) 0xff,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x18,(byte) 0x78,(byte) 0x18, +(byte) 0x8, +}; + +static final BitmapCharRec ch49 = new BitmapCharRec(8,17,-2,0,12,ch49data); + +/* char: 0x30 '0' */ + +static final byte[] ch48data = { +(byte) 0x1e,(byte) 0x0,(byte) 0x33,(byte) 0x0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0xe1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x61,(byte) 0x80,(byte) 0x61,(byte) 0x80,(byte) 0x33,(byte) 0x0, +(byte) 0x1e,(byte) 0x0, +}; + +static final BitmapCharRec ch48 = new BitmapCharRec(10,17,-1,0,12,ch48data); + +/* char: 0x2f '/' */ + +static final byte[] ch47data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x60,(byte) 0x60,(byte) 0x20,(byte) 0x30,(byte) 0x30,(byte) 0x10,(byte) 0x18,(byte) 0x18,(byte) 0x8,(byte) 0xc,(byte) 0xc,(byte) 0x4,(byte) 0x6, +(byte) 0x6,(byte) 0x3,(byte) 0x3,(byte) 0x3, +}; + +static final BitmapCharRec ch47 = new BitmapCharRec(8,20,1,3,7,ch47data); + +/* char: 0x2e '.' */ + +static final byte[] ch46data = { +(byte) 0xc0,(byte) 0xc0, +}; + +static final BitmapCharRec ch46 = new BitmapCharRec(2,2,-2,0,6,ch46data); + +/* char: 0x2d '-' */ + +static final byte[] ch45data = { +(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0, +}; + +static final BitmapCharRec ch45 = new BitmapCharRec(12,2,-1,-6,14,ch45data); + +/* char: 0x2c ',' */ + +static final byte[] ch44data = { +(byte) 0xc0,(byte) 0x60,(byte) 0x20,(byte) 0xe0,(byte) 0xc0, +}; + +static final BitmapCharRec ch44 = new BitmapCharRec(3,5,-2,3,7,ch44data); + +/* char: 0x2b '+' */ + +static final byte[] ch43data = { +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0xff,(byte) 0xf0,(byte) 0xff,(byte) 0xf0,(byte) 0x6,(byte) 0x0, +(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0,(byte) 0x6,(byte) 0x0, +}; + +static final BitmapCharRec ch43 = new BitmapCharRec(12,12,-1,-1,14,ch43data); + +/* char: 0x2a '*' */ + +static final byte[] ch42data = { +(byte) 0x8,(byte) 0x0,(byte) 0x1c,(byte) 0x0,(byte) 0xc9,(byte) 0x80,(byte) 0xeb,(byte) 0x80,(byte) 0x1c,(byte) 0x0,(byte) 0xeb,(byte) 0x80,(byte) 0xc9,(byte) 0x80,(byte) 0x1c,(byte) 0x0, +(byte) 0x8,(byte) 0x0, +}; + +static final BitmapCharRec ch42 = new BitmapCharRec(9,9,-2,-8,12,ch42data); + +/* char: 0x29 ')' */ + +static final byte[] ch41data = { +(byte) 0x80,(byte) 0x40,(byte) 0x20,(byte) 0x30,(byte) 0x10,(byte) 0x18,(byte) 0x18,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0xc,(byte) 0x18, +(byte) 0x18,(byte) 0x10,(byte) 0x30,(byte) 0x20,(byte) 0x40,(byte) 0x80, +}; + +static final BitmapCharRec ch41 = new BitmapCharRec(6,22,-1,5,8,ch41data); + +/* char: 0x28 '(' */ + +static final byte[] ch40data = { +(byte) 0x4,(byte) 0x8,(byte) 0x10,(byte) 0x30,(byte) 0x20,(byte) 0x60,(byte) 0x60,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0x60, +(byte) 0x60,(byte) 0x20,(byte) 0x30,(byte) 0x10,(byte) 0x8,(byte) 0x4, +}; + +static final BitmapCharRec ch40 = new BitmapCharRec(6,22,-1,5,8,ch40data); + +/* char: 0x27 ''' */ + +static final byte[] ch39data = { +(byte) 0xc0,(byte) 0x60,(byte) 0x20,(byte) 0xe0,(byte) 0xc0, +}; + +static final BitmapCharRec ch39 = new BitmapCharRec(3,5,-3,-12,8,ch39data); + +/* char: 0x26 '&' */ + +static final byte[] ch38data = { +(byte) 0x3c,(byte) 0x3c,(byte) 0x7f,(byte) 0x7e,(byte) 0xe1,(byte) 0xe1,(byte) 0xc0,(byte) 0xc0,(byte) 0xc1,(byte) 0xc0,(byte) 0xc1,(byte) 0xa0,(byte) 0x63,(byte) 0x20,(byte) 0x37,(byte) 0x10, +(byte) 0x1e,(byte) 0x18,(byte) 0xe,(byte) 0x3e,(byte) 0xf,(byte) 0x0,(byte) 0x1d,(byte) 0x80,(byte) 0x18,(byte) 0xc0,(byte) 0x18,(byte) 0x40,(byte) 0x18,(byte) 0x40,(byte) 0xc,(byte) 0xc0, +(byte) 0x7,(byte) 0x80, +}; + +static final BitmapCharRec ch38 = new BitmapCharRec(16,17,-1,0,18,ch38data); + +/* char: 0x25 '%' */ + +static final byte[] ch37data = { +(byte) 0x30,(byte) 0x3c,(byte) 0x0,(byte) 0x18,(byte) 0x72,(byte) 0x0,(byte) 0xc,(byte) 0x61,(byte) 0x0,(byte) 0x4,(byte) 0x60,(byte) 0x80,(byte) 0x6,(byte) 0x60,(byte) 0x80,(byte) 0x3, +(byte) 0x30,(byte) 0x80,(byte) 0x1,(byte) 0x19,(byte) 0x80,(byte) 0x1,(byte) 0x8f,(byte) 0x0,(byte) 0x78,(byte) 0xc0,(byte) 0x0,(byte) 0xe4,(byte) 0x40,(byte) 0x0,(byte) 0xc2,(byte) 0x60, +(byte) 0x0,(byte) 0xc1,(byte) 0x30,(byte) 0x0,(byte) 0xc1,(byte) 0x10,(byte) 0x0,(byte) 0x61,(byte) 0x18,(byte) 0x0,(byte) 0x33,(byte) 0xfc,(byte) 0x0,(byte) 0x1e,(byte) 0xc,(byte) 0x0, +}; + +static final BitmapCharRec ch37 = new BitmapCharRec(17,16,-1,0,19,ch37data); + +/* char: 0x24 '$' */ + +static final byte[] ch36data = { +(byte) 0x4,(byte) 0x0,(byte) 0x4,(byte) 0x0,(byte) 0x3f,(byte) 0x0,(byte) 0xe5,(byte) 0xc0,(byte) 0xc4,(byte) 0xc0,(byte) 0x84,(byte) 0x60,(byte) 0x84,(byte) 0x60,(byte) 0x4,(byte) 0x60, +(byte) 0x4,(byte) 0xe0,(byte) 0x7,(byte) 0xc0,(byte) 0x7,(byte) 0x80,(byte) 0x1e,(byte) 0x0,(byte) 0x3c,(byte) 0x0,(byte) 0x74,(byte) 0x0,(byte) 0x64,(byte) 0x0,(byte) 0x64,(byte) 0x20, +(byte) 0x64,(byte) 0x60,(byte) 0x34,(byte) 0xe0,(byte) 0x1f,(byte) 0x80,(byte) 0x4,(byte) 0x0,(byte) 0x4,(byte) 0x0, +}; + +static final BitmapCharRec ch36 = new BitmapCharRec(11,21,0,2,12,ch36data); + +/* char: 0x23 '#' */ + +static final byte[] ch35data = { +(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0x22,(byte) 0x0,(byte) 0xff,(byte) 0xc0,(byte) 0xff,(byte) 0xc0,(byte) 0x11,(byte) 0x0, +(byte) 0x11,(byte) 0x0,(byte) 0x11,(byte) 0x0,(byte) 0x7f,(byte) 0xe0,(byte) 0x7f,(byte) 0xe0,(byte) 0x8,(byte) 0x80,(byte) 0x8,(byte) 0x80,(byte) 0x8,(byte) 0x80,(byte) 0x8,(byte) 0x80, +(byte) 0x8,(byte) 0x80, +}; + +static final BitmapCharRec ch35 = new BitmapCharRec(11,17,-1,0,13,ch35data); + +/* char: 0x22 '"' */ + +static final byte[] ch34data = { +(byte) 0x88,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc,(byte) 0xcc, +}; + +static final BitmapCharRec ch34 = new BitmapCharRec(6,5,-1,-12,10,ch34data); + +/* char: 0x21 '!' */ + +static final byte[] ch33data = { +(byte) 0xc0,(byte) 0xc0,(byte) 0x0,(byte) 0x0,(byte) 0x0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0,(byte) 0xc0, +(byte) 0xc0, +}; + +static final BitmapCharRec ch33 = new BitmapCharRec(2,17,-3,0,8,ch33data); + +/* char: 0x20 ' ' */ + +static final BitmapCharRec ch32 = new BitmapCharRec(0,0,0,0,6,null); + +static final BitmapCharRec[] chars = { +ch32, +ch33, +ch34, +ch35, +ch36, +ch37, +ch38, +ch39, +ch40, +ch41, +ch42, +ch43, +ch44, +ch45, +ch46, +ch47, +ch48, +ch49, +ch50, +ch51, +ch52, +ch53, +ch54, +ch55, +ch56, +ch57, +ch58, +ch59, +ch60, +ch61, +ch62, +ch63, +ch64, +ch65, +ch66, +ch67, +ch68, +ch69, +ch70, +ch71, +ch72, +ch73, +ch74, +ch75, +ch76, +ch77, +ch78, +ch79, +ch80, +ch81, +ch82, +ch83, +ch84, +ch85, +ch86, +ch87, +ch88, +ch89, +ch90, +ch91, +ch92, +ch93, +ch94, +ch95, +ch96, +ch97, +ch98, +ch99, +ch100, +ch101, +ch102, +ch103, +ch104, +ch105, +ch106, +ch107, +ch108, +ch109, +ch110, +ch111, +ch112, +ch113, +ch114, +ch115, +ch116, +ch117, +ch118, +ch119, +ch120, +ch121, +ch122, +ch123, +ch124, +ch125, +ch126, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +null, +ch160, +ch161, +ch162, +ch163, +ch164, +ch165, +ch166, +ch167, +ch168, +ch169, +ch170, +ch171, +ch172, +ch173, +ch174, +ch175, +ch176, +ch177, +ch178, +ch179, +ch180, +ch181, +ch182, +ch183, +ch184, +ch185, +ch186, +ch187, +ch188, +ch189, +ch190, +ch191, +ch192, +ch193, +ch194, +ch195, +ch196, +ch197, +ch198, +ch199, +ch200, +ch201, +ch202, +ch203, +ch204, +ch205, +ch206, +ch207, +ch208, +ch209, +ch210, +ch211, +ch212, +ch213, +ch214, +ch215, +ch216, +ch217, +ch218, +ch219, +ch220, +ch221, +ch222, +ch223, +ch224, +ch225, +ch226, +ch227, +ch228, +ch229, +ch230, +ch231, +ch232, +ch233, +ch234, +ch235, +ch236, +ch237, +ch238, +ch239, +ch240, +ch241, +ch242, +ch243, +ch244, +ch245, +ch246, +ch247, +ch248, +ch249, +ch250, +ch251, +ch252, +ch253, +ch254, +ch255, +}; + + public static final BitmapFontRec glutBitmapTimesRoman24 = new BitmapFontRec("-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1", + 224, + 32, + chars); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java new file mode 100644 index 000000000..b8296924e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeMonoRoman.java @@ -0,0 +1,2491 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTStrokeMonoRoman { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 33 '!' */ + +static final CoordRec char33_stroke0[] = { + new CoordRec((float) 52.381, (float) 100 ), + new CoordRec((float) 52.381, (float) 33.3333 ), +}; + +static final CoordRec char33_stroke1[] = { + new CoordRec((float) 52.381, (float) 9.5238 ), + new CoordRec((float) 47.6191, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 0 ), + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 9.5238 ), +}; + +static final StrokeRec char33[] = { + new StrokeRec( 2, char33_stroke0 ), + new StrokeRec( 5, char33_stroke1 ), +}; + +/* char: 34 '"' */ + +static final CoordRec char34_stroke0[] = { + new CoordRec((float) 33.3334, (float) 100 ), + new CoordRec((float) 33.3334, (float) 66.6667 ), +}; + +static final CoordRec char34_stroke1[] = { + new CoordRec((float) 71.4286, (float) 100 ), + new CoordRec((float) 71.4286, (float) 66.6667 ), +}; + +static final StrokeRec char34[] = { + new StrokeRec( 2, char34_stroke0 ), + new StrokeRec( 2, char34_stroke1 ), +}; + +/* char: 35 '#' */ + +static final CoordRec char35_stroke0[] = { + new CoordRec((float) 54.7619, (float) 119.048 ), + new CoordRec((float) 21.4286, (float) -33.3333 ), +}; + +static final CoordRec char35_stroke1[] = { + new CoordRec((float) 83.3334, (float) 119.048 ), + new CoordRec((float) 50, (float) -33.3333 ), +}; + +static final CoordRec char35_stroke2[] = { + new CoordRec((float) 21.4286, (float) 57.1429 ), + new CoordRec((float) 88.0952, (float) 57.1429 ), +}; + +static final CoordRec char35_stroke3[] = { + new CoordRec((float) 16.6667, (float) 28.5714 ), + new CoordRec((float) 83.3334, (float) 28.5714 ), +}; + +static final StrokeRec char35[] = { + new StrokeRec( 2, char35_stroke0 ), + new StrokeRec( 2, char35_stroke1 ), + new StrokeRec( 2, char35_stroke2 ), + new StrokeRec( 2, char35_stroke3 ), +}; + +/* char: 36 '$' */ + +static final CoordRec char36_stroke0[] = { + new CoordRec((float) 42.8571, (float) 119.048 ), + new CoordRec((float) 42.8571, (float) -19.0476 ), +}; + +static final CoordRec char36_stroke1[] = { + new CoordRec((float) 61.9047, (float) 119.048 ), + new CoordRec((float) 61.9047, (float) -19.0476 ), +}; + +static final CoordRec char36_stroke2[] = { + new CoordRec((float) 85.7143, (float) 85.7143 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 28.5714, (float) 95.2381 ), + new CoordRec((float) 19.0476, (float) 85.7143 ), + new CoordRec((float) 19.0476, (float) 76.1905 ), + new CoordRec((float) 23.8095, (float) 66.6667 ), + new CoordRec((float) 28.5714, (float) 61.9048 ), + new CoordRec((float) 38.0952, (float) 57.1429 ), + new CoordRec((float) 66.6666, (float) 47.619 ), + new CoordRec((float) 76.1905, (float) 42.8571 ), + new CoordRec((float) 80.9524, (float) 38.0952 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 85.7143, (float) 14.2857 ), + new CoordRec((float) 76.1905, (float) 4.7619 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 28.5714, (float) 4.7619 ), + new CoordRec((float) 19.0476, (float) 14.2857 ), +}; + +static final StrokeRec char36[] = { + new StrokeRec( 2, char36_stroke0 ), + new StrokeRec( 2, char36_stroke1 ), + new StrokeRec( 20, char36_stroke2 ), +}; + +/* char: 37 '%' */ + +static final CoordRec char37_stroke0[] = { + new CoordRec((float) 95.2381, (float) 100 ), + new CoordRec((float) 9.5238, (float) 0 ), +}; + +static final CoordRec char37_stroke1[] = { + new CoordRec((float) 33.3333, (float) 100 ), + new CoordRec((float) 42.8571, (float) 90.4762 ), + new CoordRec((float) 42.8571, (float) 80.9524 ), + new CoordRec((float) 38.0952, (float) 71.4286 ), + new CoordRec((float) 28.5714, (float) 66.6667 ), + new CoordRec((float) 19.0476, (float) 66.6667 ), + new CoordRec((float) 9.5238, (float) 76.1905 ), + new CoordRec((float) 9.5238, (float) 85.7143 ), + new CoordRec((float) 14.2857, (float) 95.2381 ), + new CoordRec((float) 23.8095, (float) 100 ), + new CoordRec((float) 33.3333, (float) 100 ), + new CoordRec((float) 42.8571, (float) 95.2381 ), + new CoordRec((float) 57.1428, (float) 90.4762 ), + new CoordRec((float) 71.4286, (float) 90.4762 ), + new CoordRec((float) 85.7143, (float) 95.2381 ), + new CoordRec((float) 95.2381, (float) 100 ), +}; + +static final CoordRec char37_stroke2[] = { + new CoordRec((float) 76.1905, (float) 33.3333 ), + new CoordRec((float) 66.6667, (float) 28.5714 ), + new CoordRec((float) 61.9048, (float) 19.0476 ), + new CoordRec((float) 61.9048, (float) 9.5238 ), + new CoordRec((float) 71.4286, (float) 0 ), + new CoordRec((float) 80.9524, (float) 0 ), + new CoordRec((float) 90.4762, (float) 4.7619 ), + new CoordRec((float) 95.2381, (float) 14.2857 ), + new CoordRec((float) 95.2381, (float) 23.8095 ), + new CoordRec((float) 85.7143, (float) 33.3333 ), + new CoordRec((float) 76.1905, (float) 33.3333 ), +}; + +static final StrokeRec char37[] = { + new StrokeRec( 2, char37_stroke0 ), + new StrokeRec( 16, char37_stroke1 ), + new StrokeRec( 11, char37_stroke2 ), +}; + +/* char: 38 '&' */ + +static final CoordRec char38_stroke0[] = { + new CoordRec((float) 100, (float) 57.1429 ), + new CoordRec((float) 100, (float) 61.9048 ), + new CoordRec((float) 95.2381, (float) 66.6667 ), + new CoordRec((float) 90.4762, (float) 66.6667 ), + new CoordRec((float) 85.7143, (float) 61.9048 ), + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4286, (float) 28.5714 ), + new CoordRec((float) 61.9048, (float) 14.2857 ), + new CoordRec((float) 52.3809, (float) 4.7619 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 23.8095, (float) 0 ), + new CoordRec((float) 14.2857, (float) 4.7619 ), + new CoordRec((float) 9.5238, (float) 9.5238 ), + new CoordRec((float) 4.7619, (float) 19.0476 ), + new CoordRec((float) 4.7619, (float) 28.5714 ), + new CoordRec((float) 9.5238, (float) 38.0952 ), + new CoordRec((float) 14.2857, (float) 42.8571 ), + new CoordRec((float) 47.619, (float) 61.9048 ), + new CoordRec((float) 52.3809, (float) 66.6667 ), + new CoordRec((float) 57.1429, (float) 76.1905 ), + new CoordRec((float) 57.1429, (float) 85.7143 ), + new CoordRec((float) 52.3809, (float) 95.2381 ), + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 28.5714, (float) 85.7143 ), + new CoordRec((float) 28.5714, (float) 76.1905 ), + new CoordRec((float) 33.3333, (float) 61.9048 ), + new CoordRec((float) 42.8571, (float) 47.619 ), + new CoordRec((float) 66.6667, (float) 14.2857 ), + new CoordRec((float) 76.1905, (float) 4.7619 ), + new CoordRec((float) 85.7143, (float) 0 ), + new CoordRec((float) 95.2381, (float) 0 ), + new CoordRec((float) 100, (float) 4.7619 ), + new CoordRec((float) 100, (float) 9.5238 ), +}; + +static final StrokeRec char38[] = { + new StrokeRec( 34, char38_stroke0 ), +}; + +/* char: 39 ''' */ + +static final CoordRec char39_stroke0[] = { + new CoordRec((float) 52.381, (float) 100 ), + new CoordRec((float) 52.381, (float) 66.6667 ), +}; + +static final StrokeRec char39[] = { + new StrokeRec( 2, char39_stroke0 ), +}; + +/* char: 40 '(' */ + +static final CoordRec char40_stroke0[] = { + new CoordRec((float) 69.0476, (float) 119.048 ), + new CoordRec((float) 59.5238, (float) 109.524 ), + new CoordRec((float) 50, (float) 95.2381 ), + new CoordRec((float) 40.4762, (float) 76.1905 ), + new CoordRec((float) 35.7143, (float) 52.381 ), + new CoordRec((float) 35.7143, (float) 33.3333 ), + new CoordRec((float) 40.4762, (float) 9.5238 ), + new CoordRec((float) 50, (float) -9.5238 ), + new CoordRec((float) 59.5238, (float) -23.8095 ), + new CoordRec((float) 69.0476, (float) -33.3333 ), +}; + +static final StrokeRec char40[] = { + new StrokeRec( 10, char40_stroke0 ), +}; + +/* char: 41 ')' */ + +static final CoordRec char41_stroke0[] = { + new CoordRec((float) 35.7143, (float) 119.048 ), + new CoordRec((float) 45.2381, (float) 109.524 ), + new CoordRec((float) 54.7619, (float) 95.2381 ), + new CoordRec((float) 64.2857, (float) 76.1905 ), + new CoordRec((float) 69.0476, (float) 52.381 ), + new CoordRec((float) 69.0476, (float) 33.3333 ), + new CoordRec((float) 64.2857, (float) 9.5238 ), + new CoordRec((float) 54.7619, (float) -9.5238 ), + new CoordRec((float) 45.2381, (float) -23.8095 ), + new CoordRec((float) 35.7143, (float) -33.3333 ), +}; + +static final StrokeRec char41[] = { + new StrokeRec( 10, char41_stroke0 ), +}; + +/* char: 42 '*' */ + +static final CoordRec char42_stroke0[] = { + new CoordRec((float) 52.381, (float) 71.4286 ), + new CoordRec((float) 52.381, (float) 14.2857 ), +}; + +static final CoordRec char42_stroke1[] = { + new CoordRec((float) 28.5715, (float) 57.1429 ), + new CoordRec((float) 76.1905, (float) 28.5714 ), +}; + +static final CoordRec char42_stroke2[] = { + new CoordRec((float) 76.1905, (float) 57.1429 ), + new CoordRec((float) 28.5715, (float) 28.5714 ), +}; + +static final StrokeRec char42[] = { + new StrokeRec( 2, char42_stroke0 ), + new StrokeRec( 2, char42_stroke1 ), + new StrokeRec( 2, char42_stroke2 ), +}; + +/* char: 43 '+' */ + +static final CoordRec char43_stroke0[] = { + new CoordRec((float) 52.3809, (float) 85.7143 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char43_stroke1[] = { + new CoordRec((float) 9.5238, (float) 42.8571 ), + new CoordRec((float) 95.2381, (float) 42.8571 ), +}; + +static final StrokeRec char43[] = { + new StrokeRec( 2, char43_stroke0 ), + new StrokeRec( 2, char43_stroke1 ), +}; + +/* char: 44 ',' */ + +static final CoordRec char44_stroke0[] = { + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 0 ), + new CoordRec((float) 47.6191, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 9.5238 ), + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 57.1429, (float) -4.7619 ), + new CoordRec((float) 52.381, (float) -14.2857 ), + new CoordRec((float) 47.6191, (float) -19.0476 ), +}; + +static final StrokeRec char44[] = { + new StrokeRec( 8, char44_stroke0 ), +}; + +/* char: 45 '-' */ + +static final CoordRec char45_stroke0[] = { + new CoordRec((float) 9.5238, (float) 42.8571 ), + new CoordRec((float) 95.2381, (float) 42.8571 ), +}; + +static final StrokeRec char45[] = { + new StrokeRec( 2, char45_stroke0 ), +}; + +/* char: 46 '.' */ + +static final CoordRec char46_stroke0[] = { + new CoordRec((float) 52.381, (float) 9.5238 ), + new CoordRec((float) 47.6191, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 0 ), + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 9.5238 ), +}; + +static final StrokeRec char46[] = { + new StrokeRec( 5, char46_stroke0 ), +}; + +/* char: 47 '/' */ + +static final CoordRec char47_stroke0[] = { + new CoordRec((float) 19.0476, (float) -14.2857 ), + new CoordRec((float) 85.7143, (float) 100 ), +}; + +static final StrokeRec char47[] = { + new StrokeRec( 2, char47_stroke0 ), +}; + +/* char: 48 '0' */ + +static final CoordRec char48_stroke0[] = { + new CoordRec((float) 47.619, (float) 100 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 23.8095, (float) 80.9524 ), + new CoordRec((float) 19.0476, (float) 57.1429 ), + new CoordRec((float) 19.0476, (float) 42.8571 ), + new CoordRec((float) 23.8095, (float) 19.0476 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 19.0476 ), + new CoordRec((float) 85.7143, (float) 42.8571 ), + new CoordRec((float) 85.7143, (float) 57.1429 ), + new CoordRec((float) 80.9524, (float) 80.9524 ), + new CoordRec((float) 71.4286, (float) 95.2381 ), + new CoordRec((float) 57.1428, (float) 100 ), + new CoordRec((float) 47.619, (float) 100 ), +}; + +static final StrokeRec char48[] = { + new StrokeRec( 17, char48_stroke0 ), +}; + +/* char: 49 '1' */ + +static final CoordRec char49_stroke0[] = { + new CoordRec((float) 40.4762, (float) 80.9524 ), + new CoordRec((float) 50, (float) 85.7143 ), + new CoordRec((float) 64.2857, (float) 100 ), + new CoordRec((float) 64.2857, (float) 0 ), +}; + +static final StrokeRec char49[] = { + new StrokeRec( 4, char49_stroke0 ), +}; + +/* char: 50 '2' */ + +static final CoordRec char50_stroke0[] = { + new CoordRec((float) 23.8095, (float) 76.1905 ), + new CoordRec((float) 23.8095, (float) 80.9524 ), + new CoordRec((float) 28.5714, (float) 90.4762 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 71.4286, (float) 95.2381 ), + new CoordRec((float) 76.1905, (float) 90.4762 ), + new CoordRec((float) 80.9524, (float) 80.9524 ), + new CoordRec((float) 80.9524, (float) 71.4286 ), + new CoordRec((float) 76.1905, (float) 61.9048 ), + new CoordRec((float) 66.6666, (float) 47.619 ), + new CoordRec((float) 19.0476, (float) 0 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final StrokeRec char50[] = { + new StrokeRec( 14, char50_stroke0 ), +}; + +/* char: 51 '3' */ + +static final CoordRec char51_stroke0[] = { + new CoordRec((float) 28.5714, (float) 100 ), + new CoordRec((float) 80.9524, (float) 100 ), + new CoordRec((float) 52.3809, (float) 61.9048 ), + new CoordRec((float) 66.6666, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 57.1429 ), + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 85.7143, (float) 38.0952 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 28.5714, (float) 4.7619 ), + new CoordRec((float) 23.8095, (float) 9.5238 ), + new CoordRec((float) 19.0476, (float) 19.0476 ), +}; + +static final StrokeRec char51[] = { + new StrokeRec( 15, char51_stroke0 ), +}; + +/* char: 52 '4' */ + +static final CoordRec char52_stroke0[] = { + new CoordRec((float) 64.2857, (float) 100 ), + new CoordRec((float) 16.6667, (float) 33.3333 ), + new CoordRec((float) 88.0952, (float) 33.3333 ), +}; + +static final CoordRec char52_stroke1[] = { + new CoordRec((float) 64.2857, (float) 100 ), + new CoordRec((float) 64.2857, (float) 0 ), +}; + +static final StrokeRec char52[] = { + new StrokeRec( 3, char52_stroke0 ), + new StrokeRec( 2, char52_stroke1 ), +}; + +/* char: 53 '5' */ + +static final CoordRec char53_stroke0[] = { + new CoordRec((float) 76.1905, (float) 100 ), + new CoordRec((float) 28.5714, (float) 100 ), + new CoordRec((float) 23.8095, (float) 57.1429 ), + new CoordRec((float) 28.5714, (float) 61.9048 ), + new CoordRec((float) 42.8571, (float) 66.6667 ), + new CoordRec((float) 57.1428, (float) 66.6667 ), + new CoordRec((float) 71.4286, (float) 61.9048 ), + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 85.7143, (float) 38.0952 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 28.5714, (float) 4.7619 ), + new CoordRec((float) 23.8095, (float) 9.5238 ), + new CoordRec((float) 19.0476, (float) 19.0476 ), +}; + +static final StrokeRec char53[] = { + new StrokeRec( 17, char53_stroke0 ), +}; + +/* char: 54 '6' */ + +static final CoordRec char54_stroke0[] = { + new CoordRec((float) 78.5714, (float) 85.7143 ), + new CoordRec((float) 73.8096, (float) 95.2381 ), + new CoordRec((float) 59.5238, (float) 100 ), + new CoordRec((float) 50, (float) 100 ), + new CoordRec((float) 35.7143, (float) 95.2381 ), + new CoordRec((float) 26.1905, (float) 80.9524 ), + new CoordRec((float) 21.4286, (float) 57.1429 ), + new CoordRec((float) 21.4286, (float) 33.3333 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), + new CoordRec((float) 35.7143, (float) 4.7619 ), + new CoordRec((float) 50, (float) 0 ), + new CoordRec((float) 54.7619, (float) 0 ), + new CoordRec((float) 69.0476, (float) 4.7619 ), + new CoordRec((float) 78.5714, (float) 14.2857 ), + new CoordRec((float) 83.3334, (float) 28.5714 ), + new CoordRec((float) 83.3334, (float) 33.3333 ), + new CoordRec((float) 78.5714, (float) 47.619 ), + new CoordRec((float) 69.0476, (float) 57.1429 ), + new CoordRec((float) 54.7619, (float) 61.9048 ), + new CoordRec((float) 50, (float) 61.9048 ), + new CoordRec((float) 35.7143, (float) 57.1429 ), + new CoordRec((float) 26.1905, (float) 47.619 ), + new CoordRec((float) 21.4286, (float) 33.3333 ), +}; + +static final StrokeRec char54[] = { + new StrokeRec( 23, char54_stroke0 ), +}; + +/* char: 55 '7' */ + +static final CoordRec char55_stroke0[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 38.0952, (float) 0 ), +}; + +static final CoordRec char55_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) 100 ), +}; + +static final StrokeRec char55[] = { + new StrokeRec( 2, char55_stroke0 ), + new StrokeRec( 2, char55_stroke1 ), +}; + +/* char: 56 '8' */ + +static final CoordRec char56_stroke0[] = { + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 28.5714, (float) 95.2381 ), + new CoordRec((float) 23.8095, (float) 85.7143 ), + new CoordRec((float) 23.8095, (float) 76.1905 ), + new CoordRec((float) 28.5714, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 57.1428, (float) 57.1429 ), + new CoordRec((float) 71.4286, (float) 52.381 ), + new CoordRec((float) 80.9524, (float) 42.8571 ), + new CoordRec((float) 85.7143, (float) 33.3333 ), + new CoordRec((float) 85.7143, (float) 19.0476 ), + new CoordRec((float) 80.9524, (float) 9.5238 ), + new CoordRec((float) 76.1905, (float) 4.7619 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 28.5714, (float) 4.7619 ), + new CoordRec((float) 23.8095, (float) 9.5238 ), + new CoordRec((float) 19.0476, (float) 19.0476 ), + new CoordRec((float) 19.0476, (float) 33.3333 ), + new CoordRec((float) 23.8095, (float) 42.8571 ), + new CoordRec((float) 33.3333, (float) 52.381 ), + new CoordRec((float) 47.619, (float) 57.1429 ), + new CoordRec((float) 66.6666, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 66.6667 ), + new CoordRec((float) 80.9524, (float) 76.1905 ), + new CoordRec((float) 80.9524, (float) 85.7143 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 42.8571, (float) 100 ), +}; + +static final StrokeRec char56[] = { + new StrokeRec( 29, char56_stroke0 ), +}; + +/* char: 57 '9' */ + +static final CoordRec char57_stroke0[] = { + new CoordRec((float) 83.3334, (float) 66.6667 ), + new CoordRec((float) 78.5714, (float) 52.381 ), + new CoordRec((float) 69.0476, (float) 42.8571 ), + new CoordRec((float) 54.7619, (float) 38.0952 ), + new CoordRec((float) 50, (float) 38.0952 ), + new CoordRec((float) 35.7143, (float) 42.8571 ), + new CoordRec((float) 26.1905, (float) 52.381 ), + new CoordRec((float) 21.4286, (float) 66.6667 ), + new CoordRec((float) 21.4286, (float) 71.4286 ), + new CoordRec((float) 26.1905, (float) 85.7143 ), + new CoordRec((float) 35.7143, (float) 95.2381 ), + new CoordRec((float) 50, (float) 100 ), + new CoordRec((float) 54.7619, (float) 100 ), + new CoordRec((float) 69.0476, (float) 95.2381 ), + new CoordRec((float) 78.5714, (float) 85.7143 ), + new CoordRec((float) 83.3334, (float) 66.6667 ), + new CoordRec((float) 83.3334, (float) 42.8571 ), + new CoordRec((float) 78.5714, (float) 19.0476 ), + new CoordRec((float) 69.0476, (float) 4.7619 ), + new CoordRec((float) 54.7619, (float) 0 ), + new CoordRec((float) 45.2381, (float) 0 ), + new CoordRec((float) 30.9524, (float) 4.7619 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), +}; + +static final StrokeRec char57[] = { + new StrokeRec( 23, char57_stroke0 ), +}; + +/* char: 58 ':' */ + +static final CoordRec char58_stroke0[] = { + new CoordRec((float) 52.381, (float) 66.6667 ), + new CoordRec((float) 47.6191, (float) 61.9048 ), + new CoordRec((float) 52.381, (float) 57.1429 ), + new CoordRec((float) 57.1429, (float) 61.9048 ), + new CoordRec((float) 52.381, (float) 66.6667 ), +}; + +static final CoordRec char58_stroke1[] = { + new CoordRec((float) 52.381, (float) 9.5238 ), + new CoordRec((float) 47.6191, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 0 ), + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 9.5238 ), +}; + +static final StrokeRec char58[] = { + new StrokeRec( 5, char58_stroke0 ), + new StrokeRec( 5, char58_stroke1 ), +}; + +/* char: 59 ';' */ + +static final CoordRec char59_stroke0[] = { + new CoordRec((float) 52.381, (float) 66.6667 ), + new CoordRec((float) 47.6191, (float) 61.9048 ), + new CoordRec((float) 52.381, (float) 57.1429 ), + new CoordRec((float) 57.1429, (float) 61.9048 ), + new CoordRec((float) 52.381, (float) 66.6667 ), +}; + +static final CoordRec char59_stroke1[] = { + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 0 ), + new CoordRec((float) 47.6191, (float) 4.7619 ), + new CoordRec((float) 52.381, (float) 9.5238 ), + new CoordRec((float) 57.1429, (float) 4.7619 ), + new CoordRec((float) 57.1429, (float) -4.7619 ), + new CoordRec((float) 52.381, (float) -14.2857 ), + new CoordRec((float) 47.6191, (float) -19.0476 ), +}; + +static final StrokeRec char59[] = { + new StrokeRec( 5, char59_stroke0 ), + new StrokeRec( 8, char59_stroke1 ), +}; + +/* char: 60 '<' */ + +static final CoordRec char60_stroke0[] = { + new CoordRec((float) 90.4762, (float) 85.7143 ), + new CoordRec((float) 14.2857, (float) 42.8571 ), + new CoordRec((float) 90.4762, (float) 0 ), +}; + +static final StrokeRec char60[] = { + new StrokeRec( 3, char60_stroke0 ), +}; + +/* char: 61 '=' */ + +static final CoordRec char61_stroke0[] = { + new CoordRec((float) 9.5238, (float) 57.1429 ), + new CoordRec((float) 95.2381, (float) 57.1429 ), +}; + +static final CoordRec char61_stroke1[] = { + new CoordRec((float) 9.5238, (float) 28.5714 ), + new CoordRec((float) 95.2381, (float) 28.5714 ), +}; + +static final StrokeRec char61[] = { + new StrokeRec( 2, char61_stroke0 ), + new StrokeRec( 2, char61_stroke1 ), +}; + +/* char: 62 '>' */ + +static final CoordRec char62_stroke0[] = { + new CoordRec((float) 14.2857, (float) 85.7143 ), + new CoordRec((float) 90.4762, (float) 42.8571 ), + new CoordRec((float) 14.2857, (float) 0 ), +}; + +static final StrokeRec char62[] = { + new StrokeRec( 3, char62_stroke0 ), +}; + +/* char: 63 '?' */ + +static final CoordRec char63_stroke0[] = { + new CoordRec((float) 23.8095, (float) 76.1905 ), + new CoordRec((float) 23.8095, (float) 80.9524 ), + new CoordRec((float) 28.5714, (float) 90.4762 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 71.4285, (float) 95.2381 ), + new CoordRec((float) 76.1905, (float) 90.4762 ), + new CoordRec((float) 80.9524, (float) 80.9524 ), + new CoordRec((float) 80.9524, (float) 71.4286 ), + new CoordRec((float) 76.1905, (float) 61.9048 ), + new CoordRec((float) 71.4285, (float) 57.1429 ), + new CoordRec((float) 52.3809, (float) 47.619 ), + new CoordRec((float) 52.3809, (float) 33.3333 ), +}; + +static final CoordRec char63_stroke1[] = { + new CoordRec((float) 52.3809, (float) 9.5238 ), + new CoordRec((float) 47.619, (float) 4.7619 ), + new CoordRec((float) 52.3809, (float) 0 ), + new CoordRec((float) 57.1428, (float) 4.7619 ), + new CoordRec((float) 52.3809, (float) 9.5238 ), +}; + +static final StrokeRec char63[] = { + new StrokeRec( 14, char63_stroke0 ), + new StrokeRec( 5, char63_stroke1 ), +}; + +/* char: 64 '@' */ + +static final CoordRec char64_stroke0[] = { + new CoordRec((float) 64.2857, (float) 52.381 ), + new CoordRec((float) 54.7619, (float) 57.1429 ), + new CoordRec((float) 45.2381, (float) 57.1429 ), + new CoordRec((float) 40.4762, (float) 47.619 ), + new CoordRec((float) 40.4762, (float) 42.8571 ), + new CoordRec((float) 45.2381, (float) 33.3333 ), + new CoordRec((float) 54.7619, (float) 33.3333 ), + new CoordRec((float) 64.2857, (float) 38.0952 ), +}; + +static final CoordRec char64_stroke1[] = { + new CoordRec((float) 64.2857, (float) 57.1429 ), + new CoordRec((float) 64.2857, (float) 38.0952 ), + new CoordRec((float) 69.0476, (float) 33.3333 ), + new CoordRec((float) 78.5714, (float) 33.3333 ), + new CoordRec((float) 83.3334, (float) 42.8571 ), + new CoordRec((float) 83.3334, (float) 47.619 ), + new CoordRec((float) 78.5714, (float) 61.9048 ), + new CoordRec((float) 69.0476, (float) 71.4286 ), + new CoordRec((float) 54.7619, (float) 76.1905 ), + new CoordRec((float) 50, (float) 76.1905 ), + new CoordRec((float) 35.7143, (float) 71.4286 ), + new CoordRec((float) 26.1905, (float) 61.9048 ), + new CoordRec((float) 21.4286, (float) 47.619 ), + new CoordRec((float) 21.4286, (float) 42.8571 ), + new CoordRec((float) 26.1905, (float) 28.5714 ), + new CoordRec((float) 35.7143, (float) 19.0476 ), + new CoordRec((float) 50, (float) 14.2857 ), + new CoordRec((float) 54.7619, (float) 14.2857 ), + new CoordRec((float) 69.0476, (float) 19.0476 ), +}; + +static final StrokeRec char64[] = { + new StrokeRec( 8, char64_stroke0 ), + new StrokeRec( 19, char64_stroke1 ), +}; + +/* char: 65 'A' */ + +static final CoordRec char65_stroke0[] = { + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 14.2857, (float) 0 ), +}; + +static final CoordRec char65_stroke1[] = { + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 90.4762, (float) 0 ), +}; + +static final CoordRec char65_stroke2[] = { + new CoordRec((float) 28.5714, (float) 33.3333 ), + new CoordRec((float) 76.1905, (float) 33.3333 ), +}; + +static final StrokeRec char65[] = { + new StrokeRec( 2, char65_stroke0 ), + new StrokeRec( 2, char65_stroke1 ), + new StrokeRec( 2, char65_stroke2 ), +}; + +/* char: 66 'B' */ + +static final CoordRec char66_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char66_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 80.9524, (float) 90.4762 ), + new CoordRec((float) 85.7143, (float) 80.9524 ), + new CoordRec((float) 85.7143, (float) 71.4286 ), + new CoordRec((float) 80.9524, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 57.1429 ), + new CoordRec((float) 61.9047, (float) 52.381 ), +}; + +static final CoordRec char66_stroke2[] = { + new CoordRec((float) 19.0476, (float) 52.381 ), + new CoordRec((float) 61.9047, (float) 52.381 ), + new CoordRec((float) 76.1905, (float) 47.619 ), + new CoordRec((float) 80.9524, (float) 42.8571 ), + new CoordRec((float) 85.7143, (float) 33.3333 ), + new CoordRec((float) 85.7143, (float) 19.0476 ), + new CoordRec((float) 80.9524, (float) 9.5238 ), + new CoordRec((float) 76.1905, (float) 4.7619 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final StrokeRec char66[] = { + new StrokeRec( 2, char66_stroke0 ), + new StrokeRec( 9, char66_stroke1 ), + new StrokeRec( 10, char66_stroke2 ), +}; + +/* char: 67 'C' */ + +static final CoordRec char67_stroke0[] = { + new CoordRec((float) 88.0952, (float) 76.1905 ), + new CoordRec((float) 83.3334, (float) 85.7143 ), + new CoordRec((float) 73.8096, (float) 95.2381 ), + new CoordRec((float) 64.2857, (float) 100 ), + new CoordRec((float) 45.2381, (float) 100 ), + new CoordRec((float) 35.7143, (float) 95.2381 ), + new CoordRec((float) 26.1905, (float) 85.7143 ), + new CoordRec((float) 21.4286, (float) 76.1905 ), + new CoordRec((float) 16.6667, (float) 61.9048 ), + new CoordRec((float) 16.6667, (float) 38.0952 ), + new CoordRec((float) 21.4286, (float) 23.8095 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), + new CoordRec((float) 35.7143, (float) 4.7619 ), + new CoordRec((float) 45.2381, (float) 0 ), + new CoordRec((float) 64.2857, (float) 0 ), + new CoordRec((float) 73.8096, (float) 4.7619 ), + new CoordRec((float) 83.3334, (float) 14.2857 ), + new CoordRec((float) 88.0952, (float) 23.8095 ), +}; + +static final StrokeRec char67[] = { + new StrokeRec( 18, char67_stroke0 ), +}; + +/* char: 68 'D' */ + +static final CoordRec char68_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char68_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 66.6666, (float) 95.2381 ), + new CoordRec((float) 76.1905, (float) 85.7143 ), + new CoordRec((float) 80.9524, (float) 76.1905 ), + new CoordRec((float) 85.7143, (float) 61.9048 ), + new CoordRec((float) 85.7143, (float) 38.0952 ), + new CoordRec((float) 80.9524, (float) 23.8095 ), + new CoordRec((float) 76.1905, (float) 14.2857 ), + new CoordRec((float) 66.6666, (float) 4.7619 ), + new CoordRec((float) 52.3809, (float) 0 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final StrokeRec char68[] = { + new StrokeRec( 2, char68_stroke0 ), + new StrokeRec( 12, char68_stroke1 ), +}; + +/* char: 69 'E' */ + +static final CoordRec char69_stroke0[] = { + new CoordRec((float) 21.4286, (float) 100 ), + new CoordRec((float) 21.4286, (float) 0 ), +}; + +static final CoordRec char69_stroke1[] = { + new CoordRec((float) 21.4286, (float) 100 ), + new CoordRec((float) 83.3334, (float) 100 ), +}; + +static final CoordRec char69_stroke2[] = { + new CoordRec((float) 21.4286, (float) 52.381 ), + new CoordRec((float) 59.5238, (float) 52.381 ), +}; + +static final CoordRec char69_stroke3[] = { + new CoordRec((float) 21.4286, (float) 0 ), + new CoordRec((float) 83.3334, (float) 0 ), +}; + +static final StrokeRec char69[] = { + new StrokeRec( 2, char69_stroke0 ), + new StrokeRec( 2, char69_stroke1 ), + new StrokeRec( 2, char69_stroke2 ), + new StrokeRec( 2, char69_stroke3 ), +}; + +/* char: 70 'F' */ + +static final CoordRec char70_stroke0[] = { + new CoordRec((float) 21.4286, (float) 100 ), + new CoordRec((float) 21.4286, (float) 0 ), +}; + +static final CoordRec char70_stroke1[] = { + new CoordRec((float) 21.4286, (float) 100 ), + new CoordRec((float) 83.3334, (float) 100 ), +}; + +static final CoordRec char70_stroke2[] = { + new CoordRec((float) 21.4286, (float) 52.381 ), + new CoordRec((float) 59.5238, (float) 52.381 ), +}; + +static final StrokeRec char70[] = { + new StrokeRec( 2, char70_stroke0 ), + new StrokeRec( 2, char70_stroke1 ), + new StrokeRec( 2, char70_stroke2 ), +}; + +/* char: 71 'G' */ + +static final CoordRec char71_stroke0[] = { + new CoordRec((float) 88.0952, (float) 76.1905 ), + new CoordRec((float) 83.3334, (float) 85.7143 ), + new CoordRec((float) 73.8096, (float) 95.2381 ), + new CoordRec((float) 64.2857, (float) 100 ), + new CoordRec((float) 45.2381, (float) 100 ), + new CoordRec((float) 35.7143, (float) 95.2381 ), + new CoordRec((float) 26.1905, (float) 85.7143 ), + new CoordRec((float) 21.4286, (float) 76.1905 ), + new CoordRec((float) 16.6667, (float) 61.9048 ), + new CoordRec((float) 16.6667, (float) 38.0952 ), + new CoordRec((float) 21.4286, (float) 23.8095 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), + new CoordRec((float) 35.7143, (float) 4.7619 ), + new CoordRec((float) 45.2381, (float) 0 ), + new CoordRec((float) 64.2857, (float) 0 ), + new CoordRec((float) 73.8096, (float) 4.7619 ), + new CoordRec((float) 83.3334, (float) 14.2857 ), + new CoordRec((float) 88.0952, (float) 23.8095 ), + new CoordRec((float) 88.0952, (float) 38.0952 ), +}; + +static final CoordRec char71_stroke1[] = { + new CoordRec((float) 64.2857, (float) 38.0952 ), + new CoordRec((float) 88.0952, (float) 38.0952 ), +}; + +static final StrokeRec char71[] = { + new StrokeRec( 19, char71_stroke0 ), + new StrokeRec( 2, char71_stroke1 ), +}; + +/* char: 72 'H' */ + +static final CoordRec char72_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char72_stroke1[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final CoordRec char72_stroke2[] = { + new CoordRec((float) 19.0476, (float) 52.381 ), + new CoordRec((float) 85.7143, (float) 52.381 ), +}; + +static final StrokeRec char72[] = { + new StrokeRec( 2, char72_stroke0 ), + new StrokeRec( 2, char72_stroke1 ), + new StrokeRec( 2, char72_stroke2 ), +}; + +/* char: 73 'I' */ + +static final CoordRec char73_stroke0[] = { + new CoordRec((float) 52.381, (float) 100 ), + new CoordRec((float) 52.381, (float) 0 ), +}; + +static final StrokeRec char73[] = { + new StrokeRec( 2, char73_stroke0 ), +}; + +/* char: 74 'J' */ + +static final CoordRec char74_stroke0[] = { + new CoordRec((float) 76.1905, (float) 100 ), + new CoordRec((float) 76.1905, (float) 23.8095 ), + new CoordRec((float) 71.4286, (float) 9.5238 ), + new CoordRec((float) 66.6667, (float) 4.7619 ), + new CoordRec((float) 57.1429, (float) 0 ), + new CoordRec((float) 47.6191, (float) 0 ), + new CoordRec((float) 38.0953, (float) 4.7619 ), + new CoordRec((float) 33.3334, (float) 9.5238 ), + new CoordRec((float) 28.5715, (float) 23.8095 ), + new CoordRec((float) 28.5715, (float) 33.3333 ), +}; + +static final StrokeRec char74[] = { + new StrokeRec( 10, char74_stroke0 ), +}; + +/* char: 75 'K' */ + +static final CoordRec char75_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char75_stroke1[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 19.0476, (float) 33.3333 ), +}; + +static final CoordRec char75_stroke2[] = { + new CoordRec((float) 42.8571, (float) 57.1429 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final StrokeRec char75[] = { + new StrokeRec( 2, char75_stroke0 ), + new StrokeRec( 2, char75_stroke1 ), + new StrokeRec( 2, char75_stroke2 ), +}; + +/* char: 76 'L' */ + +static final CoordRec char76_stroke0[] = { + new CoordRec((float) 23.8095, (float) 100 ), + new CoordRec((float) 23.8095, (float) 0 ), +}; + +static final CoordRec char76_stroke1[] = { + new CoordRec((float) 23.8095, (float) 0 ), + new CoordRec((float) 80.9524, (float) 0 ), +}; + +static final StrokeRec char76[] = { + new StrokeRec( 2, char76_stroke0 ), + new StrokeRec( 2, char76_stroke1 ), +}; + +/* char: 77 'M' */ + +static final CoordRec char77_stroke0[] = { + new CoordRec((float) 14.2857, (float) 100 ), + new CoordRec((float) 14.2857, (float) 0 ), +}; + +static final CoordRec char77_stroke1[] = { + new CoordRec((float) 14.2857, (float) 100 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char77_stroke2[] = { + new CoordRec((float) 90.4762, (float) 100 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char77_stroke3[] = { + new CoordRec((float) 90.4762, (float) 100 ), + new CoordRec((float) 90.4762, (float) 0 ), +}; + +static final StrokeRec char77[] = { + new StrokeRec( 2, char77_stroke0 ), + new StrokeRec( 2, char77_stroke1 ), + new StrokeRec( 2, char77_stroke2 ), + new StrokeRec( 2, char77_stroke3 ), +}; + +/* char: 78 'N' */ + +static final CoordRec char78_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char78_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final CoordRec char78_stroke2[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final StrokeRec char78[] = { + new StrokeRec( 2, char78_stroke0 ), + new StrokeRec( 2, char78_stroke1 ), + new StrokeRec( 2, char78_stroke2 ), +}; + +/* char: 79 'O' */ + +static final CoordRec char79_stroke0[] = { + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 23.8095, (float) 85.7143 ), + new CoordRec((float) 19.0476, (float) 76.1905 ), + new CoordRec((float) 14.2857, (float) 61.9048 ), + new CoordRec((float) 14.2857, (float) 38.0952 ), + new CoordRec((float) 19.0476, (float) 23.8095 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 85.7143, (float) 23.8095 ), + new CoordRec((float) 90.4762, (float) 38.0952 ), + new CoordRec((float) 90.4762, (float) 61.9048 ), + new CoordRec((float) 85.7143, (float) 76.1905 ), + new CoordRec((float) 80.9524, (float) 85.7143 ), + new CoordRec((float) 71.4286, (float) 95.2381 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 42.8571, (float) 100 ), +}; + +static final StrokeRec char79[] = { + new StrokeRec( 21, char79_stroke0 ), +}; + +/* char: 80 'P' */ + +static final CoordRec char80_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char80_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 80.9524, (float) 90.4762 ), + new CoordRec((float) 85.7143, (float) 80.9524 ), + new CoordRec((float) 85.7143, (float) 66.6667 ), + new CoordRec((float) 80.9524, (float) 57.1429 ), + new CoordRec((float) 76.1905, (float) 52.381 ), + new CoordRec((float) 61.9047, (float) 47.619 ), + new CoordRec((float) 19.0476, (float) 47.619 ), +}; + +static final StrokeRec char80[] = { + new StrokeRec( 2, char80_stroke0 ), + new StrokeRec( 10, char80_stroke1 ), +}; + +/* char: 81 'Q' */ + +static final CoordRec char81_stroke0[] = { + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 33.3333, (float) 95.2381 ), + new CoordRec((float) 23.8095, (float) 85.7143 ), + new CoordRec((float) 19.0476, (float) 76.1905 ), + new CoordRec((float) 14.2857, (float) 61.9048 ), + new CoordRec((float) 14.2857, (float) 38.0952 ), + new CoordRec((float) 19.0476, (float) 23.8095 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 85.7143, (float) 23.8095 ), + new CoordRec((float) 90.4762, (float) 38.0952 ), + new CoordRec((float) 90.4762, (float) 61.9048 ), + new CoordRec((float) 85.7143, (float) 76.1905 ), + new CoordRec((float) 80.9524, (float) 85.7143 ), + new CoordRec((float) 71.4286, (float) 95.2381 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 42.8571, (float) 100 ), +}; + +static final CoordRec char81_stroke1[] = { + new CoordRec((float) 57.1428, (float) 19.0476 ), + new CoordRec((float) 85.7143, (float) -9.5238 ), +}; + +static final StrokeRec char81[] = { + new StrokeRec( 21, char81_stroke0 ), + new StrokeRec( 2, char81_stroke1 ), +}; + +/* char: 82 'R' */ + +static final CoordRec char82_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char82_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 80.9524, (float) 90.4762 ), + new CoordRec((float) 85.7143, (float) 80.9524 ), + new CoordRec((float) 85.7143, (float) 71.4286 ), + new CoordRec((float) 80.9524, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 57.1429 ), + new CoordRec((float) 61.9047, (float) 52.381 ), + new CoordRec((float) 19.0476, (float) 52.381 ), +}; + +static final CoordRec char82_stroke2[] = { + new CoordRec((float) 52.3809, (float) 52.381 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final StrokeRec char82[] = { + new StrokeRec( 2, char82_stroke0 ), + new StrokeRec( 10, char82_stroke1 ), + new StrokeRec( 2, char82_stroke2 ), +}; + +/* char: 83 'S' */ + +static final CoordRec char83_stroke0[] = { + new CoordRec((float) 85.7143, (float) 85.7143 ), + new CoordRec((float) 76.1905, (float) 95.2381 ), + new CoordRec((float) 61.9047, (float) 100 ), + new CoordRec((float) 42.8571, (float) 100 ), + new CoordRec((float) 28.5714, (float) 95.2381 ), + new CoordRec((float) 19.0476, (float) 85.7143 ), + new CoordRec((float) 19.0476, (float) 76.1905 ), + new CoordRec((float) 23.8095, (float) 66.6667 ), + new CoordRec((float) 28.5714, (float) 61.9048 ), + new CoordRec((float) 38.0952, (float) 57.1429 ), + new CoordRec((float) 66.6666, (float) 47.619 ), + new CoordRec((float) 76.1905, (float) 42.8571 ), + new CoordRec((float) 80.9524, (float) 38.0952 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 85.7143, (float) 14.2857 ), + new CoordRec((float) 76.1905, (float) 4.7619 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 28.5714, (float) 4.7619 ), + new CoordRec((float) 19.0476, (float) 14.2857 ), +}; + +static final StrokeRec char83[] = { + new StrokeRec( 20, char83_stroke0 ), +}; + +/* char: 84 'T' */ + +static final CoordRec char84_stroke0[] = { + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char84_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) 100 ), +}; + +static final StrokeRec char84[] = { + new StrokeRec( 2, char84_stroke0 ), + new StrokeRec( 2, char84_stroke1 ), +}; + +/* char: 85 'U' */ + +static final CoordRec char85_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 19.0476, (float) 28.5714 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 85.7143, (float) 100 ), +}; + +static final StrokeRec char85[] = { + new StrokeRec( 10, char85_stroke0 ), +}; + +/* char: 86 'V' */ + +static final CoordRec char86_stroke0[] = { + new CoordRec((float) 14.2857, (float) 100 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char86_stroke1[] = { + new CoordRec((float) 90.4762, (float) 100 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final StrokeRec char86[] = { + new StrokeRec( 2, char86_stroke0 ), + new StrokeRec( 2, char86_stroke1 ), +}; + +/* char: 87 'W' */ + +static final CoordRec char87_stroke0[] = { + new CoordRec((float) 4.7619, (float) 100 ), + new CoordRec((float) 28.5714, (float) 0 ), +}; + +static final CoordRec char87_stroke1[] = { + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 28.5714, (float) 0 ), +}; + +static final CoordRec char87_stroke2[] = { + new CoordRec((float) 52.3809, (float) 100 ), + new CoordRec((float) 76.1905, (float) 0 ), +}; + +static final CoordRec char87_stroke3[] = { + new CoordRec((float) 100, (float) 100 ), + new CoordRec((float) 76.1905, (float) 0 ), +}; + +static final StrokeRec char87[] = { + new StrokeRec( 2, char87_stroke0 ), + new StrokeRec( 2, char87_stroke1 ), + new StrokeRec( 2, char87_stroke2 ), + new StrokeRec( 2, char87_stroke3 ), +}; + +/* char: 88 'X' */ + +static final CoordRec char88_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final CoordRec char88_stroke1[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final StrokeRec char88[] = { + new StrokeRec( 2, char88_stroke0 ), + new StrokeRec( 2, char88_stroke1 ), +}; + +/* char: 89 'Y' */ + +static final CoordRec char89_stroke0[] = { + new CoordRec((float) 14.2857, (float) 100 ), + new CoordRec((float) 52.3809, (float) 52.381 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char89_stroke1[] = { + new CoordRec((float) 90.4762, (float) 100 ), + new CoordRec((float) 52.3809, (float) 52.381 ), +}; + +static final StrokeRec char89[] = { + new StrokeRec( 3, char89_stroke0 ), + new StrokeRec( 2, char89_stroke1 ), +}; + +/* char: 90 'Z' */ + +static final CoordRec char90_stroke0[] = { + new CoordRec((float) 85.7143, (float) 100 ), + new CoordRec((float) 19.0476, (float) 0 ), +}; + +static final CoordRec char90_stroke1[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) 100 ), +}; + +static final CoordRec char90_stroke2[] = { + new CoordRec((float) 19.0476, (float) 0 ), + new CoordRec((float) 85.7143, (float) 0 ), +}; + +static final StrokeRec char90[] = { + new StrokeRec( 2, char90_stroke0 ), + new StrokeRec( 2, char90_stroke1 ), + new StrokeRec( 2, char90_stroke2 ), +}; + +/* char: 91 '[' */ + +static final CoordRec char91_stroke0[] = { + new CoordRec((float) 35.7143, (float) 119.048 ), + new CoordRec((float) 35.7143, (float) -33.3333 ), +}; + +static final CoordRec char91_stroke1[] = { + new CoordRec((float) 40.4762, (float) 119.048 ), + new CoordRec((float) 40.4762, (float) -33.3333 ), +}; + +static final CoordRec char91_stroke2[] = { + new CoordRec((float) 35.7143, (float) 119.048 ), + new CoordRec((float) 69.0476, (float) 119.048 ), +}; + +static final CoordRec char91_stroke3[] = { + new CoordRec((float) 35.7143, (float) -33.3333 ), + new CoordRec((float) 69.0476, (float) -33.3333 ), +}; + +static final StrokeRec char91[] = { + new StrokeRec( 2, char91_stroke0 ), + new StrokeRec( 2, char91_stroke1 ), + new StrokeRec( 2, char91_stroke2 ), + new StrokeRec( 2, char91_stroke3 ), +}; + +/* char: 92 '\' */ + +static final CoordRec char92_stroke0[] = { + new CoordRec((float) 19.0476, (float) 100 ), + new CoordRec((float) 85.7143, (float) -14.2857 ), +}; + +static final StrokeRec char92[] = { + new StrokeRec( 2, char92_stroke0 ), +}; + +/* char: 93 ']' */ + +static final CoordRec char93_stroke0[] = { + new CoordRec((float) 64.2857, (float) 119.048 ), + new CoordRec((float) 64.2857, (float) -33.3333 ), +}; + +static final CoordRec char93_stroke1[] = { + new CoordRec((float) 69.0476, (float) 119.048 ), + new CoordRec((float) 69.0476, (float) -33.3333 ), +}; + +static final CoordRec char93_stroke2[] = { + new CoordRec((float) 35.7143, (float) 119.048 ), + new CoordRec((float) 69.0476, (float) 119.048 ), +}; + +static final CoordRec char93_stroke3[] = { + new CoordRec((float) 35.7143, (float) -33.3333 ), + new CoordRec((float) 69.0476, (float) -33.3333 ), +}; + +static final StrokeRec char93[] = { + new StrokeRec( 2, char93_stroke0 ), + new StrokeRec( 2, char93_stroke1 ), + new StrokeRec( 2, char93_stroke2 ), + new StrokeRec( 2, char93_stroke3 ), +}; + +/* char: 94 '^' */ + +static final CoordRec char94_stroke0[] = { + new CoordRec((float) 52.3809, (float) 109.524 ), + new CoordRec((float) 14.2857, (float) 42.8571 ), +}; + +static final CoordRec char94_stroke1[] = { + new CoordRec((float) 52.3809, (float) 109.524 ), + new CoordRec((float) 90.4762, (float) 42.8571 ), +}; + +static final StrokeRec char94[] = { + new StrokeRec( 2, char94_stroke0 ), + new StrokeRec( 2, char94_stroke1 ), +}; + +/* char: 95 '_' */ + +static final CoordRec char95_stroke0[] = { + new CoordRec((float) 0, (float) -33.3333 ), + new CoordRec((float) 104.762, (float) -33.3333 ), + new CoordRec((float) 104.762, (float) -28.5714 ), + new CoordRec((float) 0, (float) -28.5714 ), + new CoordRec((float) 0, (float) -33.3333 ), +}; + +static final StrokeRec char95[] = { + new StrokeRec( 5, char95_stroke0 ), +}; + +/* char: 96 '`' */ + +static final CoordRec char96_stroke0[] = { + new CoordRec((float) 42.8572, (float) 100 ), + new CoordRec((float) 66.6667, (float) 71.4286 ), +}; + +static final CoordRec char96_stroke1[] = { + new CoordRec((float) 42.8572, (float) 100 ), + new CoordRec((float) 38.0953, (float) 95.2381 ), + new CoordRec((float) 66.6667, (float) 71.4286 ), +}; + +static final StrokeRec char96[] = { + new StrokeRec( 2, char96_stroke0 ), + new StrokeRec( 3, char96_stroke1 ), +}; + +/* char: 97 'a' */ + +static final CoordRec char97_stroke0[] = { + new CoordRec((float) 80.9524, (float) 66.6667 ), + new CoordRec((float) 80.9524, (float) 0 ), +}; + +static final CoordRec char97_stroke1[] = { + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char97[] = { + new StrokeRec( 2, char97_stroke0 ), + new StrokeRec( 14, char97_stroke1 ), +}; + +/* char: 98 'b' */ + +static final CoordRec char98_stroke0[] = { + new CoordRec((float) 23.8095, (float) 100 ), + new CoordRec((float) 23.8095, (float) 0 ), +}; + +static final CoordRec char98_stroke1[] = { + new CoordRec((float) 23.8095, (float) 52.381 ), + new CoordRec((float) 33.3333, (float) 61.9048 ), + new CoordRec((float) 42.8571, (float) 66.6667 ), + new CoordRec((float) 57.1428, (float) 66.6667 ), + new CoordRec((float) 66.6666, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 52.381 ), + new CoordRec((float) 80.9524, (float) 38.0952 ), + new CoordRec((float) 80.9524, (float) 28.5714 ), + new CoordRec((float) 76.1905, (float) 14.2857 ), + new CoordRec((float) 66.6666, (float) 4.7619 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), +}; + +static final StrokeRec char98[] = { + new StrokeRec( 2, char98_stroke0 ), + new StrokeRec( 14, char98_stroke1 ), +}; + +/* char: 99 'c' */ + +static final CoordRec char99_stroke0[] = { + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char99[] = { + new StrokeRec( 14, char99_stroke0 ), +}; + +/* char: 100 'd' */ + +static final CoordRec char100_stroke0[] = { + new CoordRec((float) 80.9524, (float) 100 ), + new CoordRec((float) 80.9524, (float) 0 ), +}; + +static final CoordRec char100_stroke1[] = { + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char100[] = { + new StrokeRec( 2, char100_stroke0 ), + new StrokeRec( 14, char100_stroke1 ), +}; + +/* char: 101 'e' */ + +static final CoordRec char101_stroke0[] = { + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 80.9524, (float) 38.0952 ), + new CoordRec((float) 80.9524, (float) 47.619 ), + new CoordRec((float) 76.1905, (float) 57.1429 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char101[] = { + new StrokeRec( 17, char101_stroke0 ), +}; + +/* char: 102 'f' */ + +static final CoordRec char102_stroke0[] = { + new CoordRec((float) 71.4286, (float) 100 ), + new CoordRec((float) 61.9048, (float) 100 ), + new CoordRec((float) 52.381, (float) 95.2381 ), + new CoordRec((float) 47.6191, (float) 80.9524 ), + new CoordRec((float) 47.6191, (float) 0 ), +}; + +static final CoordRec char102_stroke1[] = { + new CoordRec((float) 33.3334, (float) 66.6667 ), + new CoordRec((float) 66.6667, (float) 66.6667 ), +}; + +static final StrokeRec char102[] = { + new StrokeRec( 5, char102_stroke0 ), + new StrokeRec( 2, char102_stroke1 ), +}; + +/* char: 103 'g' */ + +static final CoordRec char103_stroke0[] = { + new CoordRec((float) 80.9524, (float) 66.6667 ), + new CoordRec((float) 80.9524, (float) -9.5238 ), + new CoordRec((float) 76.1905, (float) -23.8095 ), + new CoordRec((float) 71.4285, (float) -28.5714 ), + new CoordRec((float) 61.9047, (float) -33.3333 ), + new CoordRec((float) 47.619, (float) -33.3333 ), + new CoordRec((float) 38.0952, (float) -28.5714 ), +}; + +static final CoordRec char103_stroke1[] = { + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char103[] = { + new StrokeRec( 7, char103_stroke0 ), + new StrokeRec( 14, char103_stroke1 ), +}; + +/* char: 104 'h' */ + +static final CoordRec char104_stroke0[] = { + new CoordRec((float) 26.1905, (float) 100 ), + new CoordRec((float) 26.1905, (float) 0 ), +}; + +static final CoordRec char104_stroke1[] = { + new CoordRec((float) 26.1905, (float) 47.619 ), + new CoordRec((float) 40.4762, (float) 61.9048 ), + new CoordRec((float) 50, (float) 66.6667 ), + new CoordRec((float) 64.2857, (float) 66.6667 ), + new CoordRec((float) 73.8095, (float) 61.9048 ), + new CoordRec((float) 78.5715, (float) 47.619 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final StrokeRec char104[] = { + new StrokeRec( 2, char104_stroke0 ), + new StrokeRec( 7, char104_stroke1 ), +}; + +/* char: 105 'i' */ + +static final CoordRec char105_stroke0[] = { + new CoordRec((float) 47.6191, (float) 100 ), + new CoordRec((float) 52.381, (float) 95.2381 ), + new CoordRec((float) 57.1429, (float) 100 ), + new CoordRec((float) 52.381, (float) 104.762 ), + new CoordRec((float) 47.6191, (float) 100 ), +}; + +static final CoordRec char105_stroke1[] = { + new CoordRec((float) 52.381, (float) 66.6667 ), + new CoordRec((float) 52.381, (float) 0 ), +}; + +static final StrokeRec char105[] = { + new StrokeRec( 5, char105_stroke0 ), + new StrokeRec( 2, char105_stroke1 ), +}; + +/* char: 106 'j' */ + +static final CoordRec char106_stroke0[] = { + new CoordRec((float) 57.1429, (float) 100 ), + new CoordRec((float) 61.9048, (float) 95.2381 ), + new CoordRec((float) 66.6667, (float) 100 ), + new CoordRec((float) 61.9048, (float) 104.762 ), + new CoordRec((float) 57.1429, (float) 100 ), +}; + +static final CoordRec char106_stroke1[] = { + new CoordRec((float) 61.9048, (float) 66.6667 ), + new CoordRec((float) 61.9048, (float) -14.2857 ), + new CoordRec((float) 57.1429, (float) -28.5714 ), + new CoordRec((float) 47.6191, (float) -33.3333 ), + new CoordRec((float) 38.0953, (float) -33.3333 ), +}; + +static final StrokeRec char106[] = { + new StrokeRec( 5, char106_stroke0 ), + new StrokeRec( 5, char106_stroke1 ), +}; + +/* char: 107 'k' */ + +static final CoordRec char107_stroke0[] = { + new CoordRec((float) 26.1905, (float) 100 ), + new CoordRec((float) 26.1905, (float) 0 ), +}; + +static final CoordRec char107_stroke1[] = { + new CoordRec((float) 73.8095, (float) 66.6667 ), + new CoordRec((float) 26.1905, (float) 19.0476 ), +}; + +static final CoordRec char107_stroke2[] = { + new CoordRec((float) 45.2381, (float) 38.0952 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final StrokeRec char107[] = { + new StrokeRec( 2, char107_stroke0 ), + new StrokeRec( 2, char107_stroke1 ), + new StrokeRec( 2, char107_stroke2 ), +}; + +/* char: 108 'l' */ + +static final CoordRec char108_stroke0[] = { + new CoordRec((float) 52.381, (float) 100 ), + new CoordRec((float) 52.381, (float) 0 ), +}; + +static final StrokeRec char108[] = { + new StrokeRec( 2, char108_stroke0 ), +}; + +/* char: 109 'm' */ + +static final CoordRec char109_stroke0[] = { + new CoordRec((float) 0, (float) 66.6667 ), + new CoordRec((float) 0, (float) 0 ), +}; + +static final CoordRec char109_stroke1[] = { + new CoordRec((float) 0, (float) 47.619 ), + new CoordRec((float) 14.2857, (float) 61.9048 ), + new CoordRec((float) 23.8095, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 61.9048 ), + new CoordRec((float) 52.381, (float) 47.619 ), + new CoordRec((float) 52.381, (float) 0 ), +}; + +static final CoordRec char109_stroke2[] = { + new CoordRec((float) 52.381, (float) 47.619 ), + new CoordRec((float) 66.6667, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 66.6667 ), + new CoordRec((float) 90.4762, (float) 66.6667 ), + new CoordRec((float) 100, (float) 61.9048 ), + new CoordRec((float) 104.762, (float) 47.619 ), + new CoordRec((float) 104.762, (float) 0 ), +}; + +static final StrokeRec char109[] = { + new StrokeRec( 2, char109_stroke0 ), + new StrokeRec( 7, char109_stroke1 ), + new StrokeRec( 7, char109_stroke2 ), +}; + +/* char: 110 'n' */ + +static final CoordRec char110_stroke0[] = { + new CoordRec((float) 26.1905, (float) 66.6667 ), + new CoordRec((float) 26.1905, (float) 0 ), +}; + +static final CoordRec char110_stroke1[] = { + new CoordRec((float) 26.1905, (float) 47.619 ), + new CoordRec((float) 40.4762, (float) 61.9048 ), + new CoordRec((float) 50, (float) 66.6667 ), + new CoordRec((float) 64.2857, (float) 66.6667 ), + new CoordRec((float) 73.8095, (float) 61.9048 ), + new CoordRec((float) 78.5715, (float) 47.619 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final StrokeRec char110[] = { + new StrokeRec( 2, char110_stroke0 ), + new StrokeRec( 7, char110_stroke1 ), +}; + +/* char: 111 'o' */ + +static final CoordRec char111_stroke0[] = { + new CoordRec((float) 45.2381, (float) 66.6667 ), + new CoordRec((float) 35.7143, (float) 61.9048 ), + new CoordRec((float) 26.1905, (float) 52.381 ), + new CoordRec((float) 21.4286, (float) 38.0952 ), + new CoordRec((float) 21.4286, (float) 28.5714 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), + new CoordRec((float) 35.7143, (float) 4.7619 ), + new CoordRec((float) 45.2381, (float) 0 ), + new CoordRec((float) 59.5238, (float) 0 ), + new CoordRec((float) 69.0476, (float) 4.7619 ), + new CoordRec((float) 78.5714, (float) 14.2857 ), + new CoordRec((float) 83.3334, (float) 28.5714 ), + new CoordRec((float) 83.3334, (float) 38.0952 ), + new CoordRec((float) 78.5714, (float) 52.381 ), + new CoordRec((float) 69.0476, (float) 61.9048 ), + new CoordRec((float) 59.5238, (float) 66.6667 ), + new CoordRec((float) 45.2381, (float) 66.6667 ), +}; + +static final StrokeRec char111[] = { + new StrokeRec( 17, char111_stroke0 ), +}; + +/* char: 112 'p' */ + +static final CoordRec char112_stroke0[] = { + new CoordRec((float) 23.8095, (float) 66.6667 ), + new CoordRec((float) 23.8095, (float) -33.3333 ), +}; + +static final CoordRec char112_stroke1[] = { + new CoordRec((float) 23.8095, (float) 52.381 ), + new CoordRec((float) 33.3333, (float) 61.9048 ), + new CoordRec((float) 42.8571, (float) 66.6667 ), + new CoordRec((float) 57.1428, (float) 66.6667 ), + new CoordRec((float) 66.6666, (float) 61.9048 ), + new CoordRec((float) 76.1905, (float) 52.381 ), + new CoordRec((float) 80.9524, (float) 38.0952 ), + new CoordRec((float) 80.9524, (float) 28.5714 ), + new CoordRec((float) 76.1905, (float) 14.2857 ), + new CoordRec((float) 66.6666, (float) 4.7619 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 42.8571, (float) 0 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), +}; + +static final StrokeRec char112[] = { + new StrokeRec( 2, char112_stroke0 ), + new StrokeRec( 14, char112_stroke1 ), +}; + +/* char: 113 'q' */ + +static final CoordRec char113_stroke0[] = { + new CoordRec((float) 80.9524, (float) 66.6667 ), + new CoordRec((float) 80.9524, (float) -33.3333 ), +}; + +static final CoordRec char113_stroke1[] = { + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4285, (float) 61.9048 ), + new CoordRec((float) 61.9047, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 38.0952, (float) 61.9048 ), + new CoordRec((float) 28.5714, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 38.0952 ), + new CoordRec((float) 23.8095, (float) 28.5714 ), + new CoordRec((float) 28.5714, (float) 14.2857 ), + new CoordRec((float) 38.0952, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 61.9047, (float) 0 ), + new CoordRec((float) 71.4285, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), +}; + +static final StrokeRec char113[] = { + new StrokeRec( 2, char113_stroke0 ), + new StrokeRec( 14, char113_stroke1 ), +}; + +/* char: 114 'r' */ + +static final CoordRec char114_stroke0[] = { + new CoordRec((float) 33.3334, (float) 66.6667 ), + new CoordRec((float) 33.3334, (float) 0 ), +}; + +static final CoordRec char114_stroke1[] = { + new CoordRec((float) 33.3334, (float) 38.0952 ), + new CoordRec((float) 38.0953, (float) 52.381 ), + new CoordRec((float) 47.6191, (float) 61.9048 ), + new CoordRec((float) 57.1429, (float) 66.6667 ), + new CoordRec((float) 71.4286, (float) 66.6667 ), +}; + +static final StrokeRec char114[] = { + new StrokeRec( 2, char114_stroke0 ), + new StrokeRec( 5, char114_stroke1 ), +}; + +/* char: 115 's' */ + +static final CoordRec char115_stroke0[] = { + new CoordRec((float) 78.5715, (float) 52.381 ), + new CoordRec((float) 73.8095, (float) 61.9048 ), + new CoordRec((float) 59.5238, (float) 66.6667 ), + new CoordRec((float) 45.2381, (float) 66.6667 ), + new CoordRec((float) 30.9524, (float) 61.9048 ), + new CoordRec((float) 26.1905, (float) 52.381 ), + new CoordRec((float) 30.9524, (float) 42.8571 ), + new CoordRec((float) 40.4762, (float) 38.0952 ), + new CoordRec((float) 64.2857, (float) 33.3333 ), + new CoordRec((float) 73.8095, (float) 28.5714 ), + new CoordRec((float) 78.5715, (float) 19.0476 ), + new CoordRec((float) 78.5715, (float) 14.2857 ), + new CoordRec((float) 73.8095, (float) 4.7619 ), + new CoordRec((float) 59.5238, (float) 0 ), + new CoordRec((float) 45.2381, (float) 0 ), + new CoordRec((float) 30.9524, (float) 4.7619 ), + new CoordRec((float) 26.1905, (float) 14.2857 ), +}; + +static final StrokeRec char115[] = { + new StrokeRec( 17, char115_stroke0 ), +}; + +/* char: 116 't' */ + +static final CoordRec char116_stroke0[] = { + new CoordRec((float) 47.6191, (float) 100 ), + new CoordRec((float) 47.6191, (float) 19.0476 ), + new CoordRec((float) 52.381, (float) 4.7619 ), + new CoordRec((float) 61.9048, (float) 0 ), + new CoordRec((float) 71.4286, (float) 0 ), +}; + +static final CoordRec char116_stroke1[] = { + new CoordRec((float) 33.3334, (float) 66.6667 ), + new CoordRec((float) 66.6667, (float) 66.6667 ), +}; + +static final StrokeRec char116[] = { + new StrokeRec( 5, char116_stroke0 ), + new StrokeRec( 2, char116_stroke1 ), +}; + +/* char: 117 'u' */ + +static final CoordRec char117_stroke0[] = { + new CoordRec((float) 26.1905, (float) 66.6667 ), + new CoordRec((float) 26.1905, (float) 19.0476 ), + new CoordRec((float) 30.9524, (float) 4.7619 ), + new CoordRec((float) 40.4762, (float) 0 ), + new CoordRec((float) 54.7619, (float) 0 ), + new CoordRec((float) 64.2857, (float) 4.7619 ), + new CoordRec((float) 78.5715, (float) 19.0476 ), +}; + +static final CoordRec char117_stroke1[] = { + new CoordRec((float) 78.5715, (float) 66.6667 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final StrokeRec char117[] = { + new StrokeRec( 7, char117_stroke0 ), + new StrokeRec( 2, char117_stroke1 ), +}; + +/* char: 118 'v' */ + +static final CoordRec char118_stroke0[] = { + new CoordRec((float) 23.8095, (float) 66.6667 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final CoordRec char118_stroke1[] = { + new CoordRec((float) 80.9524, (float) 66.6667 ), + new CoordRec((float) 52.3809, (float) 0 ), +}; + +static final StrokeRec char118[] = { + new StrokeRec( 2, char118_stroke0 ), + new StrokeRec( 2, char118_stroke1 ), +}; + +/* char: 119 'w' */ + +static final CoordRec char119_stroke0[] = { + new CoordRec((float) 14.2857, (float) 66.6667 ), + new CoordRec((float) 33.3333, (float) 0 ), +}; + +static final CoordRec char119_stroke1[] = { + new CoordRec((float) 52.3809, (float) 66.6667 ), + new CoordRec((float) 33.3333, (float) 0 ), +}; + +static final CoordRec char119_stroke2[] = { + new CoordRec((float) 52.3809, (float) 66.6667 ), + new CoordRec((float) 71.4286, (float) 0 ), +}; + +static final CoordRec char119_stroke3[] = { + new CoordRec((float) 90.4762, (float) 66.6667 ), + new CoordRec((float) 71.4286, (float) 0 ), +}; + +static final StrokeRec char119[] = { + new StrokeRec( 2, char119_stroke0 ), + new StrokeRec( 2, char119_stroke1 ), + new StrokeRec( 2, char119_stroke2 ), + new StrokeRec( 2, char119_stroke3 ), +}; + +/* char: 120 'x' */ + +static final CoordRec char120_stroke0[] = { + new CoordRec((float) 26.1905, (float) 66.6667 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final CoordRec char120_stroke1[] = { + new CoordRec((float) 78.5715, (float) 66.6667 ), + new CoordRec((float) 26.1905, (float) 0 ), +}; + +static final StrokeRec char120[] = { + new StrokeRec( 2, char120_stroke0 ), + new StrokeRec( 2, char120_stroke1 ), +}; + +/* char: 121 'y' */ + +static final CoordRec char121_stroke0[] = { + new CoordRec((float) 26.1905, (float) 66.6667 ), + new CoordRec((float) 54.7619, (float) 0 ), +}; + +static final CoordRec char121_stroke1[] = { + new CoordRec((float) 83.3334, (float) 66.6667 ), + new CoordRec((float) 54.7619, (float) 0 ), + new CoordRec((float) 45.2381, (float) -19.0476 ), + new CoordRec((float) 35.7143, (float) -28.5714 ), + new CoordRec((float) 26.1905, (float) -33.3333 ), + new CoordRec((float) 21.4286, (float) -33.3333 ), +}; + +static final StrokeRec char121[] = { + new StrokeRec( 2, char121_stroke0 ), + new StrokeRec( 6, char121_stroke1 ), +}; + +/* char: 122 'z' */ + +static final CoordRec char122_stroke0[] = { + new CoordRec((float) 78.5715, (float) 66.6667 ), + new CoordRec((float) 26.1905, (float) 0 ), +}; + +static final CoordRec char122_stroke1[] = { + new CoordRec((float) 26.1905, (float) 66.6667 ), + new CoordRec((float) 78.5715, (float) 66.6667 ), +}; + +static final CoordRec char122_stroke2[] = { + new CoordRec((float) 26.1905, (float) 0 ), + new CoordRec((float) 78.5715, (float) 0 ), +}; + +static final StrokeRec char122[] = { + new StrokeRec( 2, char122_stroke0 ), + new StrokeRec( 2, char122_stroke1 ), + new StrokeRec( 2, char122_stroke2 ), +}; + +/* char: 123 '{' */ + +static final CoordRec char123_stroke0[] = { + new CoordRec((float) 64.2857, (float) 119.048 ), + new CoordRec((float) 54.7619, (float) 114.286 ), + new CoordRec((float) 50, (float) 109.524 ), + new CoordRec((float) 45.2381, (float) 100 ), + new CoordRec((float) 45.2381, (float) 90.4762 ), + new CoordRec((float) 50, (float) 80.9524 ), + new CoordRec((float) 54.7619, (float) 76.1905 ), + new CoordRec((float) 59.5238, (float) 66.6667 ), + new CoordRec((float) 59.5238, (float) 57.1429 ), + new CoordRec((float) 50, (float) 47.619 ), +}; + +static final CoordRec char123_stroke1[] = { + new CoordRec((float) 54.7619, (float) 114.286 ), + new CoordRec((float) 50, (float) 104.762 ), + new CoordRec((float) 50, (float) 95.2381 ), + new CoordRec((float) 54.7619, (float) 85.7143 ), + new CoordRec((float) 59.5238, (float) 80.9524 ), + new CoordRec((float) 64.2857, (float) 71.4286 ), + new CoordRec((float) 64.2857, (float) 61.9048 ), + new CoordRec((float) 59.5238, (float) 52.381 ), + new CoordRec((float) 40.4762, (float) 42.8571 ), + new CoordRec((float) 59.5238, (float) 33.3333 ), + new CoordRec((float) 64.2857, (float) 23.8095 ), + new CoordRec((float) 64.2857, (float) 14.2857 ), + new CoordRec((float) 59.5238, (float) 4.7619 ), + new CoordRec((float) 54.7619, (float) 0 ), + new CoordRec((float) 50, (float) -9.5238 ), + new CoordRec((float) 50, (float) -19.0476 ), + new CoordRec((float) 54.7619, (float) -28.5714 ), +}; + +static final CoordRec char123_stroke2[] = { + new CoordRec((float) 50, (float) 38.0952 ), + new CoordRec((float) 59.5238, (float) 28.5714 ), + new CoordRec((float) 59.5238, (float) 19.0476 ), + new CoordRec((float) 54.7619, (float) 9.5238 ), + new CoordRec((float) 50, (float) 4.7619 ), + new CoordRec((float) 45.2381, (float) -4.7619 ), + new CoordRec((float) 45.2381, (float) -14.2857 ), + new CoordRec((float) 50, (float) -23.8095 ), + new CoordRec((float) 54.7619, (float) -28.5714 ), + new CoordRec((float) 64.2857, (float) -33.3333 ), +}; + +static final StrokeRec char123[] = { + new StrokeRec( 10, char123_stroke0 ), + new StrokeRec( 17, char123_stroke1 ), + new StrokeRec( 10, char123_stroke2 ), +}; + +/* char: 124 '|' */ + +static final CoordRec char124_stroke0[] = { + new CoordRec((float) 52.381, (float) 119.048 ), + new CoordRec((float) 52.381, (float) -33.3333 ), +}; + +static final StrokeRec char124[] = { + new StrokeRec( 2, char124_stroke0 ), +}; + +/* char: 125 '}' */ + +static final CoordRec char125_stroke0[] = { + new CoordRec((float) 40.4762, (float) 119.048 ), + new CoordRec((float) 50, (float) 114.286 ), + new CoordRec((float) 54.7619, (float) 109.524 ), + new CoordRec((float) 59.5238, (float) 100 ), + new CoordRec((float) 59.5238, (float) 90.4762 ), + new CoordRec((float) 54.7619, (float) 80.9524 ), + new CoordRec((float) 50, (float) 76.1905 ), + new CoordRec((float) 45.2381, (float) 66.6667 ), + new CoordRec((float) 45.2381, (float) 57.1429 ), + new CoordRec((float) 54.7619, (float) 47.619 ), +}; + +static final CoordRec char125_stroke1[] = { + new CoordRec((float) 50, (float) 114.286 ), + new CoordRec((float) 54.7619, (float) 104.762 ), + new CoordRec((float) 54.7619, (float) 95.2381 ), + new CoordRec((float) 50, (float) 85.7143 ), + new CoordRec((float) 45.2381, (float) 80.9524 ), + new CoordRec((float) 40.4762, (float) 71.4286 ), + new CoordRec((float) 40.4762, (float) 61.9048 ), + new CoordRec((float) 45.2381, (float) 52.381 ), + new CoordRec((float) 64.2857, (float) 42.8571 ), + new CoordRec((float) 45.2381, (float) 33.3333 ), + new CoordRec((float) 40.4762, (float) 23.8095 ), + new CoordRec((float) 40.4762, (float) 14.2857 ), + new CoordRec((float) 45.2381, (float) 4.7619 ), + new CoordRec((float) 50, (float) 0 ), + new CoordRec((float) 54.7619, (float) -9.5238 ), + new CoordRec((float) 54.7619, (float) -19.0476 ), + new CoordRec((float) 50, (float) -28.5714 ), +}; + +static final CoordRec char125_stroke2[] = { + new CoordRec((float) 54.7619, (float) 38.0952 ), + new CoordRec((float) 45.2381, (float) 28.5714 ), + new CoordRec((float) 45.2381, (float) 19.0476 ), + new CoordRec((float) 50, (float) 9.5238 ), + new CoordRec((float) 54.7619, (float) 4.7619 ), + new CoordRec((float) 59.5238, (float) -4.7619 ), + new CoordRec((float) 59.5238, (float) -14.2857 ), + new CoordRec((float) 54.7619, (float) -23.8095 ), + new CoordRec((float) 50, (float) -28.5714 ), + new CoordRec((float) 40.4762, (float) -33.3333 ), +}; + +static final StrokeRec char125[] = { + new StrokeRec( 10, char125_stroke0 ), + new StrokeRec( 17, char125_stroke1 ), + new StrokeRec( 10, char125_stroke2 ), +}; + +/* char: 126 '~' */ + +static final CoordRec char126_stroke0[] = { + new CoordRec((float) 9.5238, (float) 28.5714 ), + new CoordRec((float) 9.5238, (float) 38.0952 ), + new CoordRec((float) 14.2857, (float) 52.381 ), + new CoordRec((float) 23.8095, (float) 57.1429 ), + new CoordRec((float) 33.3333, (float) 57.1429 ), + new CoordRec((float) 42.8571, (float) 52.381 ), + new CoordRec((float) 61.9048, (float) 38.0952 ), + new CoordRec((float) 71.4286, (float) 33.3333 ), + new CoordRec((float) 80.9524, (float) 33.3333 ), + new CoordRec((float) 90.4762, (float) 38.0952 ), + new CoordRec((float) 95.2381, (float) 47.619 ), +}; + +static final CoordRec char126_stroke1[] = { + new CoordRec((float) 9.5238, (float) 38.0952 ), + new CoordRec((float) 14.2857, (float) 47.619 ), + new CoordRec((float) 23.8095, (float) 52.381 ), + new CoordRec((float) 33.3333, (float) 52.381 ), + new CoordRec((float) 42.8571, (float) 47.619 ), + new CoordRec((float) 61.9048, (float) 33.3333 ), + new CoordRec((float) 71.4286, (float) 28.5714 ), + new CoordRec((float) 80.9524, (float) 28.5714 ), + new CoordRec((float) 90.4762, (float) 33.3333 ), + new CoordRec((float) 95.2381, (float) 47.619 ), + new CoordRec((float) 95.2381, (float) 57.1429 ), +}; + +static final StrokeRec char126[] = { + new StrokeRec( 11, char126_stroke0 ), + new StrokeRec( 11, char126_stroke1 ), +}; + +/* char: 127 */ + +static final CoordRec char127_stroke0[] = { + new CoordRec((float) 71.4286, (float) 100 ), + new CoordRec((float) 33.3333, (float) -33.3333 ), +}; + +static final CoordRec char127_stroke1[] = { + new CoordRec((float) 47.619, (float) 66.6667 ), + new CoordRec((float) 33.3333, (float) 61.9048 ), + new CoordRec((float) 23.8095, (float) 52.381 ), + new CoordRec((float) 19.0476, (float) 38.0952 ), + new CoordRec((float) 19.0476, (float) 23.8095 ), + new CoordRec((float) 23.8095, (float) 14.2857 ), + new CoordRec((float) 33.3333, (float) 4.7619 ), + new CoordRec((float) 47.619, (float) 0 ), + new CoordRec((float) 57.1428, (float) 0 ), + new CoordRec((float) 71.4286, (float) 4.7619 ), + new CoordRec((float) 80.9524, (float) 14.2857 ), + new CoordRec((float) 85.7143, (float) 28.5714 ), + new CoordRec((float) 85.7143, (float) 42.8571 ), + new CoordRec((float) 80.9524, (float) 52.381 ), + new CoordRec((float) 71.4286, (float) 61.9048 ), + new CoordRec((float) 57.1428, (float) 66.6667 ), + new CoordRec((float) 47.619, (float) 66.6667 ), +}; + +static final StrokeRec char127[] = { + new StrokeRec( 2, char127_stroke0 ), + new StrokeRec( 17, char127_stroke1 ), +}; + +static final StrokeCharRec chars[] = { + new StrokeCharRec(0, /* char0 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char1 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char2 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char3 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char4 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char5 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char6 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char7 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char8 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char9 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char10 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char11 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char12 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char13 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char14 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char15 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char16 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char17 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char18 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char19 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char20 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char21 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char22 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char23 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char24 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char25 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char26 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char27 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char28 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char29 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char30 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char31 */ null, (float) 0, (float) 0 ), + new StrokeCharRec(0, /* char32 */ null, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char33, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char34, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char35, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char36, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char37, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char38, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char39, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char40, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char41, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char42, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char43, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char44, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char45, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char46, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char47, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char48, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char49, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char50, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char51, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char52, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char53, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char54, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char55, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char56, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char57, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char58, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char59, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char60, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char61, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char62, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char63, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char64, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char65, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char66, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char67, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char68, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char69, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char70, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char71, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char72, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char73, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char74, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char75, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char76, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char77, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char78, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char79, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char80, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char81, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char82, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char83, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char84, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char85, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char86, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char87, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char88, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char89, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char90, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char91, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char92, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char93, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char94, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char95, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char96, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char97, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char98, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char99, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char100, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char101, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char102, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char103, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char104, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char105, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char106, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char107, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char108, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char109, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char110, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char111, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char112, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char113, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char114, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char115, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char116, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char117, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char118, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(4, char119, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char120, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char121, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char122, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char123, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(1, char124, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(3, char125, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char126, (float) 52.381, (float) 104.762 ), + new StrokeCharRec(2, char127, (float) 52.381, (float) 104.762 ), +}; + +public static final StrokeFontRec glutStrokeMonoRoman = new StrokeFontRec( "Roman", 128, chars, (float) 119.048, (float) -33.3333 ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java new file mode 100644 index 000000000..94fa1c4fd --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/GLUTStrokeRoman.java @@ -0,0 +1,2491 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +class GLUTStrokeRoman { + +/* GENERATED FILE -- DO NOT MODIFY */ + +/* char: 33 '!' */ + +static final CoordRec char33_stroke0[] = { + new CoordRec((float) 13.3819, (float) 100), + new CoordRec((float) 13.3819, (float) 33.3333), +}; + +static final CoordRec char33_stroke1[] = { + new CoordRec((float) 13.3819, (float) 9.5238), + new CoordRec((float) 8.62, (float) 4.7619), + new CoordRec((float) 13.3819, (float) 0), + new CoordRec((float) 18.1438, (float) 4.7619), + new CoordRec((float) 13.3819, (float) 9.5238), +}; + +static final StrokeRec char33[] = { + new StrokeRec(2, char33_stroke0), + new StrokeRec(5, char33_stroke1), +}; + +/* char: 34 '"' */ + +static final CoordRec char34_stroke0[] = { + new CoordRec((float) 4.02, (float) 100), + new CoordRec((float) 4.02, (float) 66.6667), +}; + +static final CoordRec char34_stroke1[] = { + new CoordRec((float) 42.1152, (float) 100), + new CoordRec((float) 42.1152, (float) 66.6667), +}; + +static final StrokeRec char34[] = { + new StrokeRec(2, char34_stroke0), + new StrokeRec(2, char34_stroke1), +}; + +/* char: 35 '#' */ + +static final CoordRec char35_stroke0[] = { + new CoordRec((float) 41.2952, (float) 119.048), + new CoordRec((float) 7.9619, (float) -33.3333), +}; + +static final CoordRec char35_stroke1[] = { + new CoordRec((float) 69.8667, (float) 119.048), + new CoordRec((float) 36.5333, (float) -33.3333), +}; + +static final CoordRec char35_stroke2[] = { + new CoordRec((float) 7.9619, (float) 57.1429), + new CoordRec((float) 74.6286, (float) 57.1429), +}; + +static final CoordRec char35_stroke3[] = { + new CoordRec((float) 3.2, (float) 28.5714), + new CoordRec((float) 69.8667, (float) 28.5714), +}; + +static final StrokeRec char35[] = { + new StrokeRec(2, char35_stroke0), + new StrokeRec(2, char35_stroke1), + new StrokeRec(2, char35_stroke2), + new StrokeRec(2, char35_stroke3), +}; + +/* char: 36 '$' */ + +static final CoordRec char36_stroke0[] = { + new CoordRec((float) 28.6295, (float) 119.048), + new CoordRec((float) 28.6295, (float) -19.0476), +}; + +static final CoordRec char36_stroke1[] = { + new CoordRec((float) 47.6771, (float) 119.048), + new CoordRec((float) 47.6771, (float) -19.0476), +}; + +static final CoordRec char36_stroke2[] = { + new CoordRec((float) 71.4867, (float) 85.7143), + new CoordRec((float) 61.9629, (float) 95.2381), + new CoordRec((float) 47.6771, (float) 100), + new CoordRec((float) 28.6295, (float) 100), + new CoordRec((float) 14.3438, (float) 95.2381), + new CoordRec((float) 4.82, (float) 85.7143), + new CoordRec((float) 4.82, (float) 76.1905), + new CoordRec((float) 9.5819, (float) 66.6667), + new CoordRec((float) 14.3438, (float) 61.9048), + new CoordRec((float) 23.8676, (float) 57.1429), + new CoordRec((float) 52.439, (float) 47.619), + new CoordRec((float) 61.9629, (float) 42.8571), + new CoordRec((float) 66.7248, (float) 38.0952), + new CoordRec((float) 71.4867, (float) 28.5714), + new CoordRec((float) 71.4867, (float) 14.2857), + new CoordRec((float) 61.9629, (float) 4.7619), + new CoordRec((float) 47.6771, (float) 0), + new CoordRec((float) 28.6295, (float) 0), + new CoordRec((float) 14.3438, (float) 4.7619), + new CoordRec((float) 4.82, (float) 14.2857), +}; + +static final StrokeRec char36[] = { + new StrokeRec(2, char36_stroke0), + new StrokeRec(2, char36_stroke1), + new StrokeRec(20, char36_stroke2), +}; + +/* char: 37 '%' */ + +static final CoordRec char37_stroke0[] = { + new CoordRec((float) 92.0743, (float) 100), + new CoordRec((float) 6.36, (float) 0), +}; + +static final CoordRec char37_stroke1[] = { + new CoordRec((float) 30.1695, (float) 100), + new CoordRec((float) 39.6933, (float) 90.4762), + new CoordRec((float) 39.6933, (float) 80.9524), + new CoordRec((float) 34.9314, (float) 71.4286), + new CoordRec((float) 25.4076, (float) 66.6667), + new CoordRec((float) 15.8838, (float) 66.6667), + new CoordRec((float) 6.36, (float) 76.1905), + new CoordRec((float) 6.36, (float) 85.7143), + new CoordRec((float) 11.1219, (float) 95.2381), + new CoordRec((float) 20.6457, (float) 100), + new CoordRec((float) 30.1695, (float) 100), + new CoordRec((float) 39.6933, (float) 95.2381), + new CoordRec((float) 53.979, (float) 90.4762), + new CoordRec((float) 68.2648, (float) 90.4762), + new CoordRec((float) 82.5505, (float) 95.2381), + new CoordRec((float) 92.0743, (float) 100), +}; + +static final CoordRec char37_stroke2[] = { + new CoordRec((float) 73.0267, (float) 33.3333), + new CoordRec((float) 63.5029, (float) 28.5714), + new CoordRec((float) 58.741, (float) 19.0476), + new CoordRec((float) 58.741, (float) 9.5238), + new CoordRec((float) 68.2648, (float) 0), + new CoordRec((float) 77.7886, (float) 0), + new CoordRec((float) 87.3124, (float) 4.7619), + new CoordRec((float) 92.0743, (float) 14.2857), + new CoordRec((float) 92.0743, (float) 23.8095), + new CoordRec((float) 82.5505, (float) 33.3333), + new CoordRec((float) 73.0267, (float) 33.3333), +}; + +static final StrokeRec char37[] = { + new StrokeRec(2, char37_stroke0), + new StrokeRec(16, char37_stroke1), + new StrokeRec(11, char37_stroke2), +}; + +/* char: 38 '&' */ + +static final CoordRec char38_stroke0[] = { + new CoordRec((float) 101.218, (float) 57.1429), + new CoordRec((float) 101.218, (float) 61.9048), + new CoordRec((float) 96.4562, (float) 66.6667), + new CoordRec((float) 91.6943, (float) 66.6667), + new CoordRec((float) 86.9324, (float) 61.9048), + new CoordRec((float) 82.1705, (float) 52.381), + new CoordRec((float) 72.6467, (float) 28.5714), + new CoordRec((float) 63.1229, (float) 14.2857), + new CoordRec((float) 53.599, (float) 4.7619), + new CoordRec((float) 44.0752, (float) 0), + new CoordRec((float) 25.0276, (float) 0), + new CoordRec((float) 15.5038, (float) 4.7619), + new CoordRec((float) 10.7419, (float) 9.5238), + new CoordRec((float) 5.98, (float) 19.0476), + new CoordRec((float) 5.98, (float) 28.5714), + new CoordRec((float) 10.7419, (float) 38.0952), + new CoordRec((float) 15.5038, (float) 42.8571), + new CoordRec((float) 48.8371, (float) 61.9048), + new CoordRec((float) 53.599, (float) 66.6667), + new CoordRec((float) 58.361, (float) 76.1905), + new CoordRec((float) 58.361, (float) 85.7143), + new CoordRec((float) 53.599, (float) 95.2381), + new CoordRec((float) 44.0752, (float) 100), + new CoordRec((float) 34.5514, (float) 95.2381), + new CoordRec((float) 29.7895, (float) 85.7143), + new CoordRec((float) 29.7895, (float) 76.1905), + new CoordRec((float) 34.5514, (float) 61.9048), + new CoordRec((float) 44.0752, (float) 47.619), + new CoordRec((float) 67.8848, (float) 14.2857), + new CoordRec((float) 77.4086, (float) 4.7619), + new CoordRec((float) 86.9324, (float) 0), + new CoordRec((float) 96.4562, (float) 0), + new CoordRec((float) 101.218, (float) 4.7619), + new CoordRec((float) 101.218, (float) 9.5238), +}; + +static final StrokeRec char38[] = { + new StrokeRec(34, char38_stroke0), +}; + +/* char: 39 ''' */ + +static final CoordRec char39_stroke0[] = { + new CoordRec((float) 4.44, (float) 100), + new CoordRec((float) 4.44, (float) 66.6667), +}; + +static final StrokeRec char39[] = { + new StrokeRec(2, char39_stroke0), +}; + +/* char: 40 '(' */ + +static final CoordRec char40_stroke0[] = { + new CoordRec((float) 40.9133, (float) 119.048), + new CoordRec((float) 31.3895, (float) 109.524), + new CoordRec((float) 21.8657, (float) 95.2381), + new CoordRec((float) 12.3419, (float) 76.1905), + new CoordRec((float) 7.58, (float) 52.381), + new CoordRec((float) 7.58, (float) 33.3333), + new CoordRec((float) 12.3419, (float) 9.5238), + new CoordRec((float) 21.8657, (float) -9.5238), + new CoordRec((float) 31.3895, (float) -23.8095), + new CoordRec((float) 40.9133, (float) -33.3333), +}; + +static final StrokeRec char40[] = { + new StrokeRec(10, char40_stroke0), +}; + +/* char: 41 ')' */ + +static final CoordRec char41_stroke0[] = { + new CoordRec((float) 5.28, (float) 119.048), + new CoordRec((float) 14.8038, (float) 109.524), + new CoordRec((float) 24.3276, (float) 95.2381), + new CoordRec((float) 33.8514, (float) 76.1905), + new CoordRec((float) 38.6133, (float) 52.381), + new CoordRec((float) 38.6133, (float) 33.3333), + new CoordRec((float) 33.8514, (float) 9.5238), + new CoordRec((float) 24.3276, (float) -9.5238), + new CoordRec((float) 14.8038, (float) -23.8095), + new CoordRec((float) 5.28, (float) -33.3333), +}; + +static final StrokeRec char41[] = { + new StrokeRec(10, char41_stroke0), +}; + +/* char: 42 '*' */ + +static final CoordRec char42_stroke0[] = { + new CoordRec((float) 30.7695, (float) 71.4286), + new CoordRec((float) 30.7695, (float) 14.2857), +}; + +static final CoordRec char42_stroke1[] = { + new CoordRec((float) 6.96, (float) 57.1429), + new CoordRec((float) 54.579, (float) 28.5714), +}; + +static final CoordRec char42_stroke2[] = { + new CoordRec((float) 54.579, (float) 57.1429), + new CoordRec((float) 6.96, (float) 28.5714), +}; + +static final StrokeRec char42[] = { + new StrokeRec(2, char42_stroke0), + new StrokeRec(2, char42_stroke1), + new StrokeRec(2, char42_stroke2), +}; + +/* char: 43 '+' */ + +static final CoordRec char43_stroke0[] = { + new CoordRec((float) 48.8371, (float) 85.7143), + new CoordRec((float) 48.8371, (float) 0), +}; + +static final CoordRec char43_stroke1[] = { + new CoordRec((float) 5.98, (float) 42.8571), + new CoordRec((float) 91.6943, (float) 42.8571), +}; + +static final StrokeRec char43[] = { + new StrokeRec(2, char43_stroke0), + new StrokeRec(2, char43_stroke1), +}; + +/* char: 44 ',' */ + +static final CoordRec char44_stroke0[] = { + new CoordRec((float) 18.2838, (float) 4.7619), + new CoordRec((float) 13.5219, (float) 0), + new CoordRec((float) 8.76, (float) 4.7619), + new CoordRec((float) 13.5219, (float) 9.5238), + new CoordRec((float) 18.2838, (float) 4.7619), + new CoordRec((float) 18.2838, (float) -4.7619), + new CoordRec((float) 13.5219, (float) -14.2857), + new CoordRec((float) 8.76, (float) -19.0476), +}; + +static final StrokeRec char44[] = { + new StrokeRec(8, char44_stroke0), +}; + +/* char: 45 '-' */ + +static final CoordRec char45_stroke0[] = { + new CoordRec((float) 7.38, (float) 42.8571), + new CoordRec((float) 93.0943, (float) 42.8571), +}; + +static final StrokeRec char45[] = { + new StrokeRec(2, char45_stroke0), +}; + +/* char: 46 '.' */ + +static final CoordRec char46_stroke0[] = { + new CoordRec((float) 13.1019, (float) 9.5238), + new CoordRec((float) 8.34, (float) 4.7619), + new CoordRec((float) 13.1019, (float) 0), + new CoordRec((float) 17.8638, (float) 4.7619), + new CoordRec((float) 13.1019, (float) 9.5238), +}; + +static final StrokeRec char46[] = { + new StrokeRec(5, char46_stroke0), +}; + +/* char: 47 '/' */ + +static final CoordRec char47_stroke0[] = { + new CoordRec((float) 7.24, (float) -14.2857), + new CoordRec((float) 73.9067, (float) 100), +}; + +static final StrokeRec char47[] = { + new StrokeRec(2, char47_stroke0), +}; + +/* char: 48 '0' */ + +static final CoordRec char48_stroke0[] = { + new CoordRec((float) 33.5514, (float) 100), + new CoordRec((float) 19.2657, (float) 95.2381), + new CoordRec((float) 9.7419, (float) 80.9524), + new CoordRec((float) 4.98, (float) 57.1429), + new CoordRec((float) 4.98, (float) 42.8571), + new CoordRec((float) 9.7419, (float) 19.0476), + new CoordRec((float) 19.2657, (float) 4.7619), + new CoordRec((float) 33.5514, (float) 0), + new CoordRec((float) 43.0752, (float) 0), + new CoordRec((float) 57.361, (float) 4.7619), + new CoordRec((float) 66.8848, (float) 19.0476), + new CoordRec((float) 71.6467, (float) 42.8571), + new CoordRec((float) 71.6467, (float) 57.1429), + new CoordRec((float) 66.8848, (float) 80.9524), + new CoordRec((float) 57.361, (float) 95.2381), + new CoordRec((float) 43.0752, (float) 100), + new CoordRec((float) 33.5514, (float) 100), +}; + +static final StrokeRec char48[] = { + new StrokeRec(17, char48_stroke0), +}; + +/* char: 49 '1' */ + +static final CoordRec char49_stroke0[] = { + new CoordRec((float) 11.82, (float) 80.9524), + new CoordRec((float) 21.3438, (float) 85.7143), + new CoordRec((float) 35.6295, (float) 100), + new CoordRec((float) 35.6295, (float) 0), +}; + +static final StrokeRec char49[] = { + new StrokeRec(4, char49_stroke0), +}; + +/* char: 50 '2' */ + +static final CoordRec char50_stroke0[] = { + new CoordRec((float) 10.1819, (float) 76.1905), + new CoordRec((float) 10.1819, (float) 80.9524), + new CoordRec((float) 14.9438, (float) 90.4762), + new CoordRec((float) 19.7057, (float) 95.2381), + new CoordRec((float) 29.2295, (float) 100), + new CoordRec((float) 48.2771, (float) 100), + new CoordRec((float) 57.801, (float) 95.2381), + new CoordRec((float) 62.5629, (float) 90.4762), + new CoordRec((float) 67.3248, (float) 80.9524), + new CoordRec((float) 67.3248, (float) 71.4286), + new CoordRec((float) 62.5629, (float) 61.9048), + new CoordRec((float) 53.039, (float) 47.619), + new CoordRec((float) 5.42, (float) 0), + new CoordRec((float) 72.0867, (float) 0), +}; + +static final StrokeRec char50[] = { + new StrokeRec(14, char50_stroke0), +}; + +/* char: 51 '3' */ + +static final CoordRec char51_stroke0[] = { + new CoordRec((float) 14.5238, (float) 100), + new CoordRec((float) 66.9048, (float) 100), + new CoordRec((float) 38.3333, (float) 61.9048), + new CoordRec((float) 52.619, (float) 61.9048), + new CoordRec((float) 62.1429, (float) 57.1429), + new CoordRec((float) 66.9048, (float) 52.381), + new CoordRec((float) 71.6667, (float) 38.0952), + new CoordRec((float) 71.6667, (float) 28.5714), + new CoordRec((float) 66.9048, (float) 14.2857), + new CoordRec((float) 57.381, (float) 4.7619), + new CoordRec((float) 43.0952, (float) 0), + new CoordRec((float) 28.8095, (float) 0), + new CoordRec((float) 14.5238, (float) 4.7619), + new CoordRec((float) 9.7619, (float) 9.5238), + new CoordRec((float) 5, (float) 19.0476), +}; + +static final StrokeRec char51[] = { + new StrokeRec(15, char51_stroke0), +}; + +/* char: 52 '4' */ + +static final CoordRec char52_stroke0[] = { + new CoordRec((float) 51.499, (float) 100), + new CoordRec((float) 3.88, (float) 33.3333), + new CoordRec((float) 75.3086, (float) 33.3333), +}; + +static final CoordRec char52_stroke1[] = { + new CoordRec((float) 51.499, (float) 100), + new CoordRec((float) 51.499, (float) 0), +}; + +static final StrokeRec char52[] = { + new StrokeRec(3, char52_stroke0), + new StrokeRec(2, char52_stroke1), +}; + +/* char: 53 '5' */ + +static final CoordRec char53_stroke0[] = { + new CoordRec((float) 62.0029, (float) 100), + new CoordRec((float) 14.3838, (float) 100), + new CoordRec((float) 9.6219, (float) 57.1429), + new CoordRec((float) 14.3838, (float) 61.9048), + new CoordRec((float) 28.6695, (float) 66.6667), + new CoordRec((float) 42.9552, (float) 66.6667), + new CoordRec((float) 57.241, (float) 61.9048), + new CoordRec((float) 66.7648, (float) 52.381), + new CoordRec((float) 71.5267, (float) 38.0952), + new CoordRec((float) 71.5267, (float) 28.5714), + new CoordRec((float) 66.7648, (float) 14.2857), + new CoordRec((float) 57.241, (float) 4.7619), + new CoordRec((float) 42.9552, (float) 0), + new CoordRec((float) 28.6695, (float) 0), + new CoordRec((float) 14.3838, (float) 4.7619), + new CoordRec((float) 9.6219, (float) 9.5238), + new CoordRec((float) 4.86, (float) 19.0476), +}; + +static final StrokeRec char53[] = { + new StrokeRec(17, char53_stroke0), +}; + +/* char: 54 '6' */ + +static final CoordRec char54_stroke0[] = { + new CoordRec((float) 62.7229, (float) 85.7143), + new CoordRec((float) 57.961, (float) 95.2381), + new CoordRec((float) 43.6752, (float) 100), + new CoordRec((float) 34.1514, (float) 100), + new CoordRec((float) 19.8657, (float) 95.2381), + new CoordRec((float) 10.3419, (float) 80.9524), + new CoordRec((float) 5.58, (float) 57.1429), + new CoordRec((float) 5.58, (float) 33.3333), + new CoordRec((float) 10.3419, (float) 14.2857), + new CoordRec((float) 19.8657, (float) 4.7619), + new CoordRec((float) 34.1514, (float) 0), + new CoordRec((float) 38.9133, (float) 0), + new CoordRec((float) 53.199, (float) 4.7619), + new CoordRec((float) 62.7229, (float) 14.2857), + new CoordRec((float) 67.4848, (float) 28.5714), + new CoordRec((float) 67.4848, (float) 33.3333), + new CoordRec((float) 62.7229, (float) 47.619), + new CoordRec((float) 53.199, (float) 57.1429), + new CoordRec((float) 38.9133, (float) 61.9048), + new CoordRec((float) 34.1514, (float) 61.9048), + new CoordRec((float) 19.8657, (float) 57.1429), + new CoordRec((float) 10.3419, (float) 47.619), + new CoordRec((float) 5.58, (float) 33.3333), +}; + +static final StrokeRec char54[] = { + new StrokeRec(23, char54_stroke0), +}; + +/* char: 55 '7' */ + +static final CoordRec char55_stroke0[] = { + new CoordRec((float) 72.2267, (float) 100), + new CoordRec((float) 24.6076, (float) 0), +}; + +static final CoordRec char55_stroke1[] = { + new CoordRec((float) 5.56, (float) 100), + new CoordRec((float) 72.2267, (float) 100), +}; + +static final StrokeRec char55[] = { + new StrokeRec(2, char55_stroke0), + new StrokeRec(2, char55_stroke1), +}; + +/* char: 56 '8' */ + +static final CoordRec char56_stroke0[] = { + new CoordRec((float) 29.4095, (float) 100), + new CoordRec((float) 15.1238, (float) 95.2381), + new CoordRec((float) 10.3619, (float) 85.7143), + new CoordRec((float) 10.3619, (float) 76.1905), + new CoordRec((float) 15.1238, (float) 66.6667), + new CoordRec((float) 24.6476, (float) 61.9048), + new CoordRec((float) 43.6952, (float) 57.1429), + new CoordRec((float) 57.981, (float) 52.381), + new CoordRec((float) 67.5048, (float) 42.8571), + new CoordRec((float) 72.2667, (float) 33.3333), + new CoordRec((float) 72.2667, (float) 19.0476), + new CoordRec((float) 67.5048, (float) 9.5238), + new CoordRec((float) 62.7429, (float) 4.7619), + new CoordRec((float) 48.4571, (float) 0), + new CoordRec((float) 29.4095, (float) 0), + new CoordRec((float) 15.1238, (float) 4.7619), + new CoordRec((float) 10.3619, (float) 9.5238), + new CoordRec((float) 5.6, (float) 19.0476), + new CoordRec((float) 5.6, (float) 33.3333), + new CoordRec((float) 10.3619, (float) 42.8571), + new CoordRec((float) 19.8857, (float) 52.381), + new CoordRec((float) 34.1714, (float) 57.1429), + new CoordRec((float) 53.219, (float) 61.9048), + new CoordRec((float) 62.7429, (float) 66.6667), + new CoordRec((float) 67.5048, (float) 76.1905), + new CoordRec((float) 67.5048, (float) 85.7143), + new CoordRec((float) 62.7429, (float) 95.2381), + new CoordRec((float) 48.4571, (float) 100), + new CoordRec((float) 29.4095, (float) 100), +}; + +static final StrokeRec char56[] = { + new StrokeRec(29, char56_stroke0), +}; + +/* char: 57 '9' */ + +static final CoordRec char57_stroke0[] = { + new CoordRec((float) 68.5048, (float) 66.6667), + new CoordRec((float) 63.7429, (float) 52.381), + new CoordRec((float) 54.219, (float) 42.8571), + new CoordRec((float) 39.9333, (float) 38.0952), + new CoordRec((float) 35.1714, (float) 38.0952), + new CoordRec((float) 20.8857, (float) 42.8571), + new CoordRec((float) 11.3619, (float) 52.381), + new CoordRec((float) 6.6, (float) 66.6667), + new CoordRec((float) 6.6, (float) 71.4286), + new CoordRec((float) 11.3619, (float) 85.7143), + new CoordRec((float) 20.8857, (float) 95.2381), + new CoordRec((float) 35.1714, (float) 100), + new CoordRec((float) 39.9333, (float) 100), + new CoordRec((float) 54.219, (float) 95.2381), + new CoordRec((float) 63.7429, (float) 85.7143), + new CoordRec((float) 68.5048, (float) 66.6667), + new CoordRec((float) 68.5048, (float) 42.8571), + new CoordRec((float) 63.7429, (float) 19.0476), + new CoordRec((float) 54.219, (float) 4.7619), + new CoordRec((float) 39.9333, (float) 0), + new CoordRec((float) 30.4095, (float) 0), + new CoordRec((float) 16.1238, (float) 4.7619), + new CoordRec((float) 11.3619, (float) 14.2857), +}; + +static final StrokeRec char57[] = { + new StrokeRec(23, char57_stroke0), +}; + +/* char: 58 ':' */ + +static final CoordRec char58_stroke0[] = { + new CoordRec((float) 14.0819, (float) 66.6667), + new CoordRec((float) 9.32, (float) 61.9048), + new CoordRec((float) 14.0819, (float) 57.1429), + new CoordRec((float) 18.8438, (float) 61.9048), + new CoordRec((float) 14.0819, (float) 66.6667), +}; + +static final CoordRec char58_stroke1[] = { + new CoordRec((float) 14.0819, (float) 9.5238), + new CoordRec((float) 9.32, (float) 4.7619), + new CoordRec((float) 14.0819, (float) 0), + new CoordRec((float) 18.8438, (float) 4.7619), + new CoordRec((float) 14.0819, (float) 9.5238), +}; + +static final StrokeRec char58[] = { + new StrokeRec(5, char58_stroke0), + new StrokeRec(5, char58_stroke1), +}; + +/* char: 59 ';' */ + +static final CoordRec char59_stroke0[] = { + new CoordRec((float) 12.9619, (float) 66.6667), + new CoordRec((float) 8.2, (float) 61.9048), + new CoordRec((float) 12.9619, (float) 57.1429), + new CoordRec((float) 17.7238, (float) 61.9048), + new CoordRec((float) 12.9619, (float) 66.6667), +}; + +static final CoordRec char59_stroke1[] = { + new CoordRec((float) 17.7238, (float) 4.7619), + new CoordRec((float) 12.9619, (float) 0), + new CoordRec((float) 8.2, (float) 4.7619), + new CoordRec((float) 12.9619, (float) 9.5238), + new CoordRec((float) 17.7238, (float) 4.7619), + new CoordRec((float) 17.7238, (float) -4.7619), + new CoordRec((float) 12.9619, (float) -14.2857), + new CoordRec((float) 8.2, (float) -19.0476), +}; + +static final StrokeRec char59[] = { + new StrokeRec(5, char59_stroke0), + new StrokeRec(8, char59_stroke1), +}; + +/* char: 60 '<' */ + +static final CoordRec char60_stroke0[] = { + new CoordRec((float) 79.2505, (float) 85.7143), + new CoordRec((float) 3.06, (float) 42.8571), + new CoordRec((float) 79.2505, (float) 0), +}; + +static final StrokeRec char60[] = { + new StrokeRec(3, char60_stroke0), +}; + +/* char: 61 '=' */ + +static final CoordRec char61_stroke0[] = { + new CoordRec((float) 5.7, (float) 57.1429), + new CoordRec((float) 91.4143, (float) 57.1429), +}; + +static final CoordRec char61_stroke1[] = { + new CoordRec((float) 5.7, (float) 28.5714), + new CoordRec((float) 91.4143, (float) 28.5714), +}; + +static final StrokeRec char61[] = { + new StrokeRec(2, char61_stroke0), + new StrokeRec(2, char61_stroke1), +}; + +/* char: 62 '>' */ + +static final CoordRec char62_stroke0[] = { + new CoordRec((float) 2.78, (float) 85.7143), + new CoordRec((float) 78.9705, (float) 42.8571), + new CoordRec((float) 2.78, (float) 0), +}; + +static final StrokeRec char62[] = { + new StrokeRec(3, char62_stroke0), +}; + +/* char: 63 '?' */ + +static final CoordRec char63_stroke0[] = { + new CoordRec((float) 8.42, (float) 76.1905), + new CoordRec((float) 8.42, (float) 80.9524), + new CoordRec((float) 13.1819, (float) 90.4762), + new CoordRec((float) 17.9438, (float) 95.2381), + new CoordRec((float) 27.4676, (float) 100), + new CoordRec((float) 46.5152, (float) 100), + new CoordRec((float) 56.039, (float) 95.2381), + new CoordRec((float) 60.801, (float) 90.4762), + new CoordRec((float) 65.5629, (float) 80.9524), + new CoordRec((float) 65.5629, (float) 71.4286), + new CoordRec((float) 60.801, (float) 61.9048), + new CoordRec((float) 56.039, (float) 57.1429), + new CoordRec((float) 36.9914, (float) 47.619), + new CoordRec((float) 36.9914, (float) 33.3333), +}; + +static final CoordRec char63_stroke1[] = { + new CoordRec((float) 36.9914, (float) 9.5238), + new CoordRec((float) 32.2295, (float) 4.7619), + new CoordRec((float) 36.9914, (float) 0), + new CoordRec((float) 41.7533, (float) 4.7619), + new CoordRec((float) 36.9914, (float) 9.5238), +}; + +static final StrokeRec char63[] = { + new StrokeRec(14, char63_stroke0), + new StrokeRec(5, char63_stroke1), +}; + +/* char: 64 '@' */ + +static final CoordRec char64_stroke0[] = { + new CoordRec((float) 49.2171, (float) 52.381), + new CoordRec((float) 39.6933, (float) 57.1429), + new CoordRec((float) 30.1695, (float) 57.1429), + new CoordRec((float) 25.4076, (float) 47.619), + new CoordRec((float) 25.4076, (float) 42.8571), + new CoordRec((float) 30.1695, (float) 33.3333), + new CoordRec((float) 39.6933, (float) 33.3333), + new CoordRec((float) 49.2171, (float) 38.0952), +}; + +static final CoordRec char64_stroke1[] = { + new CoordRec((float) 49.2171, (float) 57.1429), + new CoordRec((float) 49.2171, (float) 38.0952), + new CoordRec((float) 53.979, (float) 33.3333), + new CoordRec((float) 63.5029, (float) 33.3333), + new CoordRec((float) 68.2648, (float) 42.8571), + new CoordRec((float) 68.2648, (float) 47.619), + new CoordRec((float) 63.5029, (float) 61.9048), + new CoordRec((float) 53.979, (float) 71.4286), + new CoordRec((float) 39.6933, (float) 76.1905), + new CoordRec((float) 34.9314, (float) 76.1905), + new CoordRec((float) 20.6457, (float) 71.4286), + new CoordRec((float) 11.1219, (float) 61.9048), + new CoordRec((float) 6.36, (float) 47.619), + new CoordRec((float) 6.36, (float) 42.8571), + new CoordRec((float) 11.1219, (float) 28.5714), + new CoordRec((float) 20.6457, (float) 19.0476), + new CoordRec((float) 34.9314, (float) 14.2857), + new CoordRec((float) 39.6933, (float) 14.2857), + new CoordRec((float) 53.979, (float) 19.0476), +}; + +static final StrokeRec char64[] = { + new StrokeRec(8, char64_stroke0), + new StrokeRec(19, char64_stroke1), +}; + +/* char: 65 'A' */ + +static final CoordRec char65_stroke0[] = { + new CoordRec((float) 40.5952, (float) 100), + new CoordRec((float) 2.5, (float) 0), +}; + +static final CoordRec char65_stroke1[] = { + new CoordRec((float) 40.5952, (float) 100), + new CoordRec((float) 78.6905, (float) 0), +}; + +static final CoordRec char65_stroke2[] = { + new CoordRec((float) 16.7857, (float) 33.3333), + new CoordRec((float) 64.4048, (float) 33.3333), +}; + +static final StrokeRec char65[] = { + new StrokeRec(2, char65_stroke0), + new StrokeRec(2, char65_stroke1), + new StrokeRec(2, char65_stroke2), +}; + +/* char: 66 'B' */ + +static final CoordRec char66_stroke0[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 11.42, (float) 0), +}; + +static final CoordRec char66_stroke1[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 54.2771, (float) 100), + new CoordRec((float) 68.5629, (float) 95.2381), + new CoordRec((float) 73.3248, (float) 90.4762), + new CoordRec((float) 78.0867, (float) 80.9524), + new CoordRec((float) 78.0867, (float) 71.4286), + new CoordRec((float) 73.3248, (float) 61.9048), + new CoordRec((float) 68.5629, (float) 57.1429), + new CoordRec((float) 54.2771, (float) 52.381), +}; + +static final CoordRec char66_stroke2[] = { + new CoordRec((float) 11.42, (float) 52.381), + new CoordRec((float) 54.2771, (float) 52.381), + new CoordRec((float) 68.5629, (float) 47.619), + new CoordRec((float) 73.3248, (float) 42.8571), + new CoordRec((float) 78.0867, (float) 33.3333), + new CoordRec((float) 78.0867, (float) 19.0476), + new CoordRec((float) 73.3248, (float) 9.5238), + new CoordRec((float) 68.5629, (float) 4.7619), + new CoordRec((float) 54.2771, (float) 0), + new CoordRec((float) 11.42, (float) 0), +}; + +static final StrokeRec char66[] = { + new StrokeRec(2, char66_stroke0), + new StrokeRec(9, char66_stroke1), + new StrokeRec(10, char66_stroke2), +}; + +/* char: 67 'C' */ + +static final CoordRec char67_stroke0[] = { + new CoordRec((float) 78.0886, (float) 76.1905), + new CoordRec((float) 73.3267, (float) 85.7143), + new CoordRec((float) 63.8029, (float) 95.2381), + new CoordRec((float) 54.279, (float) 100), + new CoordRec((float) 35.2314, (float) 100), + new CoordRec((float) 25.7076, (float) 95.2381), + new CoordRec((float) 16.1838, (float) 85.7143), + new CoordRec((float) 11.4219, (float) 76.1905), + new CoordRec((float) 6.66, (float) 61.9048), + new CoordRec((float) 6.66, (float) 38.0952), + new CoordRec((float) 11.4219, (float) 23.8095), + new CoordRec((float) 16.1838, (float) 14.2857), + new CoordRec((float) 25.7076, (float) 4.7619), + new CoordRec((float) 35.2314, (float) 0), + new CoordRec((float) 54.279, (float) 0), + new CoordRec((float) 63.8029, (float) 4.7619), + new CoordRec((float) 73.3267, (float) 14.2857), + new CoordRec((float) 78.0886, (float) 23.8095), +}; + +static final StrokeRec char67[] = { + new StrokeRec(18, char67_stroke0), +}; + +/* char: 68 'D' */ + +static final CoordRec char68_stroke0[] = { + new CoordRec((float) 11.96, (float) 100), + new CoordRec((float) 11.96, (float) 0), +}; + +static final CoordRec char68_stroke1[] = { + new CoordRec((float) 11.96, (float) 100), + new CoordRec((float) 45.2933, (float) 100), + new CoordRec((float) 59.579, (float) 95.2381), + new CoordRec((float) 69.1029, (float) 85.7143), + new CoordRec((float) 73.8648, (float) 76.1905), + new CoordRec((float) 78.6267, (float) 61.9048), + new CoordRec((float) 78.6267, (float) 38.0952), + new CoordRec((float) 73.8648, (float) 23.8095), + new CoordRec((float) 69.1029, (float) 14.2857), + new CoordRec((float) 59.579, (float) 4.7619), + new CoordRec((float) 45.2933, (float) 0), + new CoordRec((float) 11.96, (float) 0), +}; + +static final StrokeRec char68[] = { + new StrokeRec(2, char68_stroke0), + new StrokeRec(12, char68_stroke1), +}; + +/* char: 69 'E' */ + +static final CoordRec char69_stroke0[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 11.42, (float) 0), +}; + +static final CoordRec char69_stroke1[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 73.3248, (float) 100), +}; + +static final CoordRec char69_stroke2[] = { + new CoordRec((float) 11.42, (float) 52.381), + new CoordRec((float) 49.5152, (float) 52.381), +}; + +static final CoordRec char69_stroke3[] = { + new CoordRec((float) 11.42, (float) 0), + new CoordRec((float) 73.3248, (float) 0), +}; + +static final StrokeRec char69[] = { + new StrokeRec(2, char69_stroke0), + new StrokeRec(2, char69_stroke1), + new StrokeRec(2, char69_stroke2), + new StrokeRec(2, char69_stroke3), +}; + +/* char: 70 'F' */ + +static final CoordRec char70_stroke0[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 11.42, (float) 0), +}; + +static final CoordRec char70_stroke1[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 73.3248, (float) 100), +}; + +static final CoordRec char70_stroke2[] = { + new CoordRec((float) 11.42, (float) 52.381), + new CoordRec((float) 49.5152, (float) 52.381), +}; + +static final StrokeRec char70[] = { + new StrokeRec(2, char70_stroke0), + new StrokeRec(2, char70_stroke1), + new StrokeRec(2, char70_stroke2), +}; + +/* char: 71 'G' */ + +static final CoordRec char71_stroke0[] = { + new CoordRec((float) 78.4886, (float) 76.1905), + new CoordRec((float) 73.7267, (float) 85.7143), + new CoordRec((float) 64.2029, (float) 95.2381), + new CoordRec((float) 54.679, (float) 100), + new CoordRec((float) 35.6314, (float) 100), + new CoordRec((float) 26.1076, (float) 95.2381), + new CoordRec((float) 16.5838, (float) 85.7143), + new CoordRec((float) 11.8219, (float) 76.1905), + new CoordRec((float) 7.06, (float) 61.9048), + new CoordRec((float) 7.06, (float) 38.0952), + new CoordRec((float) 11.8219, (float) 23.8095), + new CoordRec((float) 16.5838, (float) 14.2857), + new CoordRec((float) 26.1076, (float) 4.7619), + new CoordRec((float) 35.6314, (float) 0), + new CoordRec((float) 54.679, (float) 0), + new CoordRec((float) 64.2029, (float) 4.7619), + new CoordRec((float) 73.7267, (float) 14.2857), + new CoordRec((float) 78.4886, (float) 23.8095), + new CoordRec((float) 78.4886, (float) 38.0952), +}; + +static final CoordRec char71_stroke1[] = { + new CoordRec((float) 54.679, (float) 38.0952), + new CoordRec((float) 78.4886, (float) 38.0952), +}; + +static final StrokeRec char71[] = { + new StrokeRec(19, char71_stroke0), + new StrokeRec(2, char71_stroke1), +}; + +/* char: 72 'H' */ + +static final CoordRec char72_stroke0[] = { + new CoordRec((float) 11.42, (float) 100), + new CoordRec((float) 11.42, (float) 0), +}; + +static final CoordRec char72_stroke1[] = { + new CoordRec((float) 78.0867, (float) 100), + new CoordRec((float) 78.0867, (float) 0), +}; + +static final CoordRec char72_stroke2[] = { + new CoordRec((float) 11.42, (float) 52.381), + new CoordRec((float) 78.0867, (float) 52.381), +}; + +static final StrokeRec char72[] = { + new StrokeRec(2, char72_stroke0), + new StrokeRec(2, char72_stroke1), + new StrokeRec(2, char72_stroke2), +}; + +/* char: 73 'I' */ + +static final CoordRec char73_stroke0[] = { + new CoordRec((float) 10.86, (float) 100), + new CoordRec((float) 10.86, (float) 0), +}; + +static final StrokeRec char73[] = { + new StrokeRec(2, char73_stroke0), +}; + +/* char: 74 'J' */ + +static final CoordRec char74_stroke0[] = { + new CoordRec((float) 50.119, (float) 100), + new CoordRec((float) 50.119, (float) 23.8095), + new CoordRec((float) 45.3571, (float) 9.5238), + new CoordRec((float) 40.5952, (float) 4.7619), + new CoordRec((float) 31.0714, (float) 0), + new CoordRec((float) 21.5476, (float) 0), + new CoordRec((float) 12.0238, (float) 4.7619), + new CoordRec((float) 7.2619, (float) 9.5238), + new CoordRec((float) 2.5, (float) 23.8095), + new CoordRec((float) 2.5, (float) 33.3333), +}; + +static final StrokeRec char74[] = { + new StrokeRec(10, char74_stroke0), +}; + +/* char: 75 'K' */ + +static final CoordRec char75_stroke0[] = { + new CoordRec((float) 11.28, (float) 100), + new CoordRec((float) 11.28, (float) 0), +}; + +static final CoordRec char75_stroke1[] = { + new CoordRec((float) 77.9467, (float) 100), + new CoordRec((float) 11.28, (float) 33.3333), +}; + +static final CoordRec char75_stroke2[] = { + new CoordRec((float) 35.0895, (float) 57.1429), + new CoordRec((float) 77.9467, (float) 0), +}; + +static final StrokeRec char75[] = { + new StrokeRec(2, char75_stroke0), + new StrokeRec(2, char75_stroke1), + new StrokeRec(2, char75_stroke2), +}; + +/* char: 76 'L' */ + +static final CoordRec char76_stroke0[] = { + new CoordRec((float) 11.68, (float) 100), + new CoordRec((float) 11.68, (float) 0), +}; + +static final CoordRec char76_stroke1[] = { + new CoordRec((float) 11.68, (float) 0), + new CoordRec((float) 68.8229, (float) 0), +}; + +static final StrokeRec char76[] = { + new StrokeRec(2, char76_stroke0), + new StrokeRec(2, char76_stroke1), +}; + +/* char: 77 'M' */ + +static final CoordRec char77_stroke0[] = { + new CoordRec((float) 10.86, (float) 100), + new CoordRec((float) 10.86, (float) 0), +}; + +static final CoordRec char77_stroke1[] = { + new CoordRec((float) 10.86, (float) 100), + new CoordRec((float) 48.9552, (float) 0), +}; + +static final CoordRec char77_stroke2[] = { + new CoordRec((float) 87.0505, (float) 100), + new CoordRec((float) 48.9552, (float) 0), +}; + +static final CoordRec char77_stroke3[] = { + new CoordRec((float) 87.0505, (float) 100), + new CoordRec((float) 87.0505, (float) 0), +}; + +static final StrokeRec char77[] = { + new StrokeRec(2, char77_stroke0), + new StrokeRec(2, char77_stroke1), + new StrokeRec(2, char77_stroke2), + new StrokeRec(2, char77_stroke3), +}; + +/* char: 78 'N' */ + +static final CoordRec char78_stroke0[] = { + new CoordRec((float) 11.14, (float) 100), + new CoordRec((float) 11.14, (float) 0), +}; + +static final CoordRec char78_stroke1[] = { + new CoordRec((float) 11.14, (float) 100), + new CoordRec((float) 77.8067, (float) 0), +}; + +static final CoordRec char78_stroke2[] = { + new CoordRec((float) 77.8067, (float) 100), + new CoordRec((float) 77.8067, (float) 0), +}; + +static final StrokeRec char78[] = { + new StrokeRec(2, char78_stroke0), + new StrokeRec(2, char78_stroke1), + new StrokeRec(2, char78_stroke2), +}; + +/* char: 79 'O' */ + +static final CoordRec char79_stroke0[] = { + new CoordRec((float) 34.8114, (float) 100), + new CoordRec((float) 25.2876, (float) 95.2381), + new CoordRec((float) 15.7638, (float) 85.7143), + new CoordRec((float) 11.0019, (float) 76.1905), + new CoordRec((float) 6.24, (float) 61.9048), + new CoordRec((float) 6.24, (float) 38.0952), + new CoordRec((float) 11.0019, (float) 23.8095), + new CoordRec((float) 15.7638, (float) 14.2857), + new CoordRec((float) 25.2876, (float) 4.7619), + new CoordRec((float) 34.8114, (float) 0), + new CoordRec((float) 53.859, (float) 0), + new CoordRec((float) 63.3829, (float) 4.7619), + new CoordRec((float) 72.9067, (float) 14.2857), + new CoordRec((float) 77.6686, (float) 23.8095), + new CoordRec((float) 82.4305, (float) 38.0952), + new CoordRec((float) 82.4305, (float) 61.9048), + new CoordRec((float) 77.6686, (float) 76.1905), + new CoordRec((float) 72.9067, (float) 85.7143), + new CoordRec((float) 63.3829, (float) 95.2381), + new CoordRec((float) 53.859, (float) 100), + new CoordRec((float) 34.8114, (float) 100), +}; + +static final StrokeRec char79[] = { + new StrokeRec(21, char79_stroke0), +}; + +/* char: 80 'P' */ + +static final CoordRec char80_stroke0[] = { + new CoordRec((float) 12.1, (float) 100), + new CoordRec((float) 12.1, (float) 0), +}; + +static final CoordRec char80_stroke1[] = { + new CoordRec((float) 12.1, (float) 100), + new CoordRec((float) 54.9571, (float) 100), + new CoordRec((float) 69.2429, (float) 95.2381), + new CoordRec((float) 74.0048, (float) 90.4762), + new CoordRec((float) 78.7667, (float) 80.9524), + new CoordRec((float) 78.7667, (float) 66.6667), + new CoordRec((float) 74.0048, (float) 57.1429), + new CoordRec((float) 69.2429, (float) 52.381), + new CoordRec((float) 54.9571, (float) 47.619), + new CoordRec((float) 12.1, (float) 47.619), +}; + +static final StrokeRec char80[] = { + new StrokeRec(2, char80_stroke0), + new StrokeRec(10, char80_stroke1), +}; + +/* char: 81 'Q' */ + +static final CoordRec char81_stroke0[] = { + new CoordRec((float) 33.8714, (float) 100), + new CoordRec((float) 24.3476, (float) 95.2381), + new CoordRec((float) 14.8238, (float) 85.7143), + new CoordRec((float) 10.0619, (float) 76.1905), + new CoordRec((float) 5.3, (float) 61.9048), + new CoordRec((float) 5.3, (float) 38.0952), + new CoordRec((float) 10.0619, (float) 23.8095), + new CoordRec((float) 14.8238, (float) 14.2857), + new CoordRec((float) 24.3476, (float) 4.7619), + new CoordRec((float) 33.8714, (float) 0), + new CoordRec((float) 52.919, (float) 0), + new CoordRec((float) 62.4429, (float) 4.7619), + new CoordRec((float) 71.9667, (float) 14.2857), + new CoordRec((float) 76.7286, (float) 23.8095), + new CoordRec((float) 81.4905, (float) 38.0952), + new CoordRec((float) 81.4905, (float) 61.9048), + new CoordRec((float) 76.7286, (float) 76.1905), + new CoordRec((float) 71.9667, (float) 85.7143), + new CoordRec((float) 62.4429, (float) 95.2381), + new CoordRec((float) 52.919, (float) 100), + new CoordRec((float) 33.8714, (float) 100), +}; + +static final CoordRec char81_stroke1[] = { + new CoordRec((float) 48.1571, (float) 19.0476), + new CoordRec((float) 76.7286, (float) -9.5238), +}; + +static final StrokeRec char81[] = { + new StrokeRec(21, char81_stroke0), + new StrokeRec(2, char81_stroke1), +}; + +/* char: 82 'R' */ + +static final CoordRec char82_stroke0[] = { + new CoordRec((float) 11.68, (float) 100), + new CoordRec((float) 11.68, (float) 0), +}; + +static final CoordRec char82_stroke1[] = { + new CoordRec((float) 11.68, (float) 100), + new CoordRec((float) 54.5371, (float) 100), + new CoordRec((float) 68.8229, (float) 95.2381), + new CoordRec((float) 73.5848, (float) 90.4762), + new CoordRec((float) 78.3467, (float) 80.9524), + new CoordRec((float) 78.3467, (float) 71.4286), + new CoordRec((float) 73.5848, (float) 61.9048), + new CoordRec((float) 68.8229, (float) 57.1429), + new CoordRec((float) 54.5371, (float) 52.381), + new CoordRec((float) 11.68, (float) 52.381), +}; + +static final CoordRec char82_stroke2[] = { + new CoordRec((float) 45.0133, (float) 52.381), + new CoordRec((float) 78.3467, (float) 0), +}; + +static final StrokeRec char82[] = { + new StrokeRec(2, char82_stroke0), + new StrokeRec(10, char82_stroke1), + new StrokeRec(2, char82_stroke2), +}; + +/* char: 83 'S' */ + +static final CoordRec char83_stroke0[] = { + new CoordRec((float) 74.6667, (float) 85.7143), + new CoordRec((float) 65.1429, (float) 95.2381), + new CoordRec((float) 50.8571, (float) 100), + new CoordRec((float) 31.8095, (float) 100), + new CoordRec((float) 17.5238, (float) 95.2381), + new CoordRec((float) 8, (float) 85.7143), + new CoordRec((float) 8, (float) 76.1905), + new CoordRec((float) 12.7619, (float) 66.6667), + new CoordRec((float) 17.5238, (float) 61.9048), + new CoordRec((float) 27.0476, (float) 57.1429), + new CoordRec((float) 55.619, (float) 47.619), + new CoordRec((float) 65.1429, (float) 42.8571), + new CoordRec((float) 69.9048, (float) 38.0952), + new CoordRec((float) 74.6667, (float) 28.5714), + new CoordRec((float) 74.6667, (float) 14.2857), + new CoordRec((float) 65.1429, (float) 4.7619), + new CoordRec((float) 50.8571, (float) 0), + new CoordRec((float) 31.8095, (float) 0), + new CoordRec((float) 17.5238, (float) 4.7619), + new CoordRec((float) 8, (float) 14.2857), +}; + +static final StrokeRec char83[] = { + new StrokeRec(20, char83_stroke0), +}; + +/* char: 84 'T' */ + +static final CoordRec char84_stroke0[] = { + new CoordRec((float) 35.6933, (float) 100), + new CoordRec((float) 35.6933, (float) 0), +}; + +static final CoordRec char84_stroke1[] = { + new CoordRec((float) 2.36, (float) 100), + new CoordRec((float) 69.0267, (float) 100), +}; + +static final StrokeRec char84[] = { + new StrokeRec(2, char84_stroke0), + new StrokeRec(2, char84_stroke1), +}; + +/* char: 85 'U' */ + +static final CoordRec char85_stroke0[] = { + new CoordRec((float) 11.54, (float) 100), + new CoordRec((float) 11.54, (float) 28.5714), + new CoordRec((float) 16.3019, (float) 14.2857), + new CoordRec((float) 25.8257, (float) 4.7619), + new CoordRec((float) 40.1114, (float) 0), + new CoordRec((float) 49.6352, (float) 0), + new CoordRec((float) 63.921, (float) 4.7619), + new CoordRec((float) 73.4448, (float) 14.2857), + new CoordRec((float) 78.2067, (float) 28.5714), + new CoordRec((float) 78.2067, (float) 100), +}; + +static final StrokeRec char85[] = { + new StrokeRec(10, char85_stroke0), +}; + +/* char: 86 'V' */ + +static final CoordRec char86_stroke0[] = { + new CoordRec((float) 2.36, (float) 100), + new CoordRec((float) 40.4552, (float) 0), +}; + +static final CoordRec char86_stroke1[] = { + new CoordRec((float) 78.5505, (float) 100), + new CoordRec((float) 40.4552, (float) 0), +}; + +static final StrokeRec char86[] = { + new StrokeRec(2, char86_stroke0), + new StrokeRec(2, char86_stroke1), +}; + +/* char: 87 'W' */ + +static final CoordRec char87_stroke0[] = { + new CoordRec((float) 2.22, (float) 100), + new CoordRec((float) 26.0295, (float) 0), +}; + +static final CoordRec char87_stroke1[] = { + new CoordRec((float) 49.839, (float) 100), + new CoordRec((float) 26.0295, (float) 0), +}; + +static final CoordRec char87_stroke2[] = { + new CoordRec((float) 49.839, (float) 100), + new CoordRec((float) 73.6486, (float) 0), +}; + +static final CoordRec char87_stroke3[] = { + new CoordRec((float) 97.4581, (float) 100), + new CoordRec((float) 73.6486, (float) 0), +}; + +static final StrokeRec char87[] = { + new StrokeRec(2, char87_stroke0), + new StrokeRec(2, char87_stroke1), + new StrokeRec(2, char87_stroke2), + new StrokeRec(2, char87_stroke3), +}; + +/* char: 88 'X' */ + +static final CoordRec char88_stroke0[] = { + new CoordRec((float) 2.5, (float) 100), + new CoordRec((float) 69.1667, (float) 0), +}; + +static final CoordRec char88_stroke1[] = { + new CoordRec((float) 69.1667, (float) 100), + new CoordRec((float) 2.5, (float) 0), +}; + +static final StrokeRec char88[] = { + new StrokeRec(2, char88_stroke0), + new StrokeRec(2, char88_stroke1), +}; + +/* char: 89 'Y' */ + +static final CoordRec char89_stroke0[] = { + new CoordRec((float) 1.52, (float) 100), + new CoordRec((float) 39.6152, (float) 52.381), + new CoordRec((float) 39.6152, (float) 0), +}; + +static final CoordRec char89_stroke1[] = { + new CoordRec((float) 77.7105, (float) 100), + new CoordRec((float) 39.6152, (float) 52.381), +}; + +static final StrokeRec char89[] = { + new StrokeRec(3, char89_stroke0), + new StrokeRec(2, char89_stroke1), +}; + +/* char: 90 'Z' */ + +static final CoordRec char90_stroke0[] = { + new CoordRec((float) 69.1667, (float) 100), + new CoordRec((float) 2.5, (float) 0), +}; + +static final CoordRec char90_stroke1[] = { + new CoordRec((float) 2.5, (float) 100), + new CoordRec((float) 69.1667, (float) 100), +}; + +static final CoordRec char90_stroke2[] = { + new CoordRec((float) 2.5, (float) 0), + new CoordRec((float) 69.1667, (float) 0), +}; + +static final StrokeRec char90[] = { + new StrokeRec(2, char90_stroke0), + new StrokeRec(2, char90_stroke1), + new StrokeRec(2, char90_stroke2), +}; + +/* char: 91 '[' */ + +static final CoordRec char91_stroke0[] = { + new CoordRec((float) 7.78, (float) 119.048), + new CoordRec((float) 7.78, (float) -33.3333), +}; + +static final CoordRec char91_stroke1[] = { + new CoordRec((float) 12.5419, (float) 119.048), + new CoordRec((float) 12.5419, (float) -33.3333), +}; + +static final CoordRec char91_stroke2[] = { + new CoordRec((float) 7.78, (float) 119.048), + new CoordRec((float) 41.1133, (float) 119.048), +}; + +static final CoordRec char91_stroke3[] = { + new CoordRec((float) 7.78, (float) -33.3333), + new CoordRec((float) 41.1133, (float) -33.3333), +}; + +static final StrokeRec char91[] = { + new StrokeRec(2, char91_stroke0), + new StrokeRec(2, char91_stroke1), + new StrokeRec(2, char91_stroke2), + new StrokeRec(2, char91_stroke3), +}; + +/* char: 92 '\' */ + +static final CoordRec char92_stroke0[] = { + new CoordRec((float) 5.84, (float) 100), + new CoordRec((float) 72.5067, (float) -14.2857), +}; + +static final StrokeRec char92[] = { + new StrokeRec(2, char92_stroke0), +}; + +/* char: 93 ']' */ + +static final CoordRec char93_stroke0[] = { + new CoordRec((float) 33.0114, (float) 119.048), + new CoordRec((float) 33.0114, (float) -33.3333), +}; + +static final CoordRec char93_stroke1[] = { + new CoordRec((float) 37.7733, (float) 119.048), + new CoordRec((float) 37.7733, (float) -33.3333), +}; + +static final CoordRec char93_stroke2[] = { + new CoordRec((float) 4.44, (float) 119.048), + new CoordRec((float) 37.7733, (float) 119.048), +}; + +static final CoordRec char93_stroke3[] = { + new CoordRec((float) 4.44, (float) -33.3333), + new CoordRec((float) 37.7733, (float) -33.3333), +}; + +static final StrokeRec char93[] = { + new StrokeRec(2, char93_stroke0), + new StrokeRec(2, char93_stroke1), + new StrokeRec(2, char93_stroke2), + new StrokeRec(2, char93_stroke3), +}; + +/* char: 94 '^' */ + +static final CoordRec char94_stroke0[] = { + new CoordRec((float) 44.0752, (float) 109.524), + new CoordRec((float) 5.98, (float) 42.8571), +}; + +static final CoordRec char94_stroke1[] = { + new CoordRec((float) 44.0752, (float) 109.524), + new CoordRec((float) 82.1705, (float) 42.8571), +}; + +static final StrokeRec char94[] = { + new StrokeRec(2, char94_stroke0), + new StrokeRec(2, char94_stroke1), +}; + +/* char: 95 '_' */ + +static final CoordRec char95_stroke0[] = { + new CoordRec((float)-1.1, (float) -33.3333), + new CoordRec((float) 103.662, (float) -33.3333), + new CoordRec((float) 103.662, (float) -28.5714), + new CoordRec((float)-1.1, (float) -28.5714), + new CoordRec((float)-1.1, (float) -33.3333), +}; + +static final StrokeRec char95[] = { + new StrokeRec(5, char95_stroke0), +}; + +/* char: 96 '`' */ + +static final CoordRec char96_stroke0[] = { + new CoordRec((float) 33.0219, (float) 100), + new CoordRec((float) 56.8314, (float) 71.4286), +}; + +static final CoordRec char96_stroke1[] = { + new CoordRec((float) 33.0219, (float) 100), + new CoordRec((float) 28.26, (float) 95.2381), + new CoordRec((float) 56.8314, (float) 71.4286), +}; + +static final StrokeRec char96[] = { + new StrokeRec(2, char96_stroke0), + new StrokeRec(3, char96_stroke1), +}; + +/* char: 97 'a' */ + +static final CoordRec char97_stroke0[] = { + new CoordRec((float) 63.8229, (float) 66.6667), + new CoordRec((float) 63.8229, (float) 0), +}; + +static final CoordRec char97_stroke1[] = { + new CoordRec((float) 63.8229, (float) 52.381), + new CoordRec((float) 54.299, (float) 61.9048), + new CoordRec((float) 44.7752, (float) 66.6667), + new CoordRec((float) 30.4895, (float) 66.6667), + new CoordRec((float) 20.9657, (float) 61.9048), + new CoordRec((float) 11.4419, (float) 52.381), + new CoordRec((float) 6.68, (float) 38.0952), + new CoordRec((float) 6.68, (float) 28.5714), + new CoordRec((float) 11.4419, (float) 14.2857), + new CoordRec((float) 20.9657, (float) 4.7619), + new CoordRec((float) 30.4895, (float) 0), + new CoordRec((float) 44.7752, (float) 0), + new CoordRec((float) 54.299, (float) 4.7619), + new CoordRec((float) 63.8229, (float) 14.2857), +}; + +static final StrokeRec char97[] = { + new StrokeRec(2, char97_stroke0), + new StrokeRec(14, char97_stroke1), +}; + +/* char: 98 'b' */ + +static final CoordRec char98_stroke0[] = { + new CoordRec((float) 8.76, (float) 100), + new CoordRec((float) 8.76, (float) 0), +}; + +static final CoordRec char98_stroke1[] = { + new CoordRec((float) 8.76, (float) 52.381), + new CoordRec((float) 18.2838, (float) 61.9048), + new CoordRec((float) 27.8076, (float) 66.6667), + new CoordRec((float) 42.0933, (float) 66.6667), + new CoordRec((float) 51.6171, (float) 61.9048), + new CoordRec((float) 61.141, (float) 52.381), + new CoordRec((float) 65.9029, (float) 38.0952), + new CoordRec((float) 65.9029, (float) 28.5714), + new CoordRec((float) 61.141, (float) 14.2857), + new CoordRec((float) 51.6171, (float) 4.7619), + new CoordRec((float) 42.0933, (float) 0), + new CoordRec((float) 27.8076, (float) 0), + new CoordRec((float) 18.2838, (float) 4.7619), + new CoordRec((float) 8.76, (float) 14.2857), +}; + +static final StrokeRec char98[] = { + new StrokeRec(2, char98_stroke0), + new StrokeRec(14, char98_stroke1), +}; + +/* char: 99 'c' */ + +static final CoordRec char99_stroke0[] = { + new CoordRec((float) 62.6629, (float) 52.381), + new CoordRec((float) 53.139, (float) 61.9048), + new CoordRec((float) 43.6152, (float) 66.6667), + new CoordRec((float) 29.3295, (float) 66.6667), + new CoordRec((float) 19.8057, (float) 61.9048), + new CoordRec((float) 10.2819, (float) 52.381), + new CoordRec((float) 5.52, (float) 38.0952), + new CoordRec((float) 5.52, (float) 28.5714), + new CoordRec((float) 10.2819, (float) 14.2857), + new CoordRec((float) 19.8057, (float) 4.7619), + new CoordRec((float) 29.3295, (float) 0), + new CoordRec((float) 43.6152, (float) 0), + new CoordRec((float) 53.139, (float) 4.7619), + new CoordRec((float) 62.6629, (float) 14.2857), +}; + +static final StrokeRec char99[] = { + new StrokeRec(14, char99_stroke0), +}; + +/* char: 100 'd' */ + +static final CoordRec char100_stroke0[] = { + new CoordRec((float) 61.7829, (float) 100), + new CoordRec((float) 61.7829, (float) 0), +}; + +static final CoordRec char100_stroke1[] = { + new CoordRec((float) 61.7829, (float) 52.381), + new CoordRec((float) 52.259, (float) 61.9048), + new CoordRec((float) 42.7352, (float) 66.6667), + new CoordRec((float) 28.4495, (float) 66.6667), + new CoordRec((float) 18.9257, (float) 61.9048), + new CoordRec((float) 9.4019, (float) 52.381), + new CoordRec((float) 4.64, (float) 38.0952), + new CoordRec((float) 4.64, (float) 28.5714), + new CoordRec((float) 9.4019, (float) 14.2857), + new CoordRec((float) 18.9257, (float) 4.7619), + new CoordRec((float) 28.4495, (float) 0), + new CoordRec((float) 42.7352, (float) 0), + new CoordRec((float) 52.259, (float) 4.7619), + new CoordRec((float) 61.7829, (float) 14.2857), +}; + +static final StrokeRec char100[] = { + new StrokeRec(2, char100_stroke0), + new StrokeRec(14, char100_stroke1), +}; + +/* char: 101 'e' */ + +static final CoordRec char101_stroke0[] = { + new CoordRec((float) 5.72, (float) 38.0952), + new CoordRec((float) 62.8629, (float) 38.0952), + new CoordRec((float) 62.8629, (float) 47.619), + new CoordRec((float) 58.101, (float) 57.1429), + new CoordRec((float) 53.339, (float) 61.9048), + new CoordRec((float) 43.8152, (float) 66.6667), + new CoordRec((float) 29.5295, (float) 66.6667), + new CoordRec((float) 20.0057, (float) 61.9048), + new CoordRec((float) 10.4819, (float) 52.381), + new CoordRec((float) 5.72, (float) 38.0952), + new CoordRec((float) 5.72, (float) 28.5714), + new CoordRec((float) 10.4819, (float) 14.2857), + new CoordRec((float) 20.0057, (float) 4.7619), + new CoordRec((float) 29.5295, (float) 0), + new CoordRec((float) 43.8152, (float) 0), + new CoordRec((float) 53.339, (float) 4.7619), + new CoordRec((float) 62.8629, (float) 14.2857), +}; + +static final StrokeRec char101[] = { + new StrokeRec(17, char101_stroke0), +}; + +/* char: 102 'f' */ + +static final CoordRec char102_stroke0[] = { + new CoordRec((float) 38.7752, (float) 100), + new CoordRec((float) 29.2514, (float) 100), + new CoordRec((float) 19.7276, (float) 95.2381), + new CoordRec((float) 14.9657, (float) 80.9524), + new CoordRec((float) 14.9657, (float) 0), +}; + +static final CoordRec char102_stroke1[] = { + new CoordRec((float) 0.68, (float) 66.6667), + new CoordRec((float) 34.0133, (float) 66.6667), +}; + +static final StrokeRec char102[] = { + new StrokeRec(5, char102_stroke0), + new StrokeRec(2, char102_stroke1), +}; + +/* char: 103 'g' */ + +static final CoordRec char103_stroke0[] = { + new CoordRec((float) 62.5029, (float) 66.6667), + new CoordRec((float) 62.5029, (float) -9.5238), + new CoordRec((float) 57.741, (float) -23.8095), + new CoordRec((float) 52.979, (float) -28.5714), + new CoordRec((float) 43.4552, (float) -33.3333), + new CoordRec((float) 29.1695, (float) -33.3333), + new CoordRec((float) 19.6457, (float) -28.5714), +}; + +static final CoordRec char103_stroke1[] = { + new CoordRec((float) 62.5029, (float) 52.381), + new CoordRec((float) 52.979, (float) 61.9048), + new CoordRec((float) 43.4552, (float) 66.6667), + new CoordRec((float) 29.1695, (float) 66.6667), + new CoordRec((float) 19.6457, (float) 61.9048), + new CoordRec((float) 10.1219, (float) 52.381), + new CoordRec((float) 5.36, (float) 38.0952), + new CoordRec((float) 5.36, (float) 28.5714), + new CoordRec((float) 10.1219, (float) 14.2857), + new CoordRec((float) 19.6457, (float) 4.7619), + new CoordRec((float) 29.1695, (float) 0), + new CoordRec((float) 43.4552, (float) 0), + new CoordRec((float) 52.979, (float) 4.7619), + new CoordRec((float) 62.5029, (float) 14.2857), +}; + +static final StrokeRec char103[] = { + new StrokeRec(7, char103_stroke0), + new StrokeRec(14, char103_stroke1), +}; + +/* char: 104 'h' */ + +static final CoordRec char104_stroke0[] = { + new CoordRec((float) 9.6, (float) 100), + new CoordRec((float) 9.6, (float) 0), +}; + +static final CoordRec char104_stroke1[] = { + new CoordRec((float) 9.6, (float) 47.619), + new CoordRec((float) 23.8857, (float) 61.9048), + new CoordRec((float) 33.4095, (float) 66.6667), + new CoordRec((float) 47.6952, (float) 66.6667), + new CoordRec((float) 57.219, (float) 61.9048), + new CoordRec((float) 61.981, (float) 47.619), + new CoordRec((float) 61.981, (float) 0), +}; + +static final StrokeRec char104[] = { + new StrokeRec(2, char104_stroke0), + new StrokeRec(7, char104_stroke1), +}; + +/* char: 105 'i' */ + +static final CoordRec char105_stroke0[] = { + new CoordRec((float) 10.02, (float) 100), + new CoordRec((float) 14.7819, (float) 95.2381), + new CoordRec((float) 19.5438, (float) 100), + new CoordRec((float) 14.7819, (float) 104.762), + new CoordRec((float) 10.02, (float) 100), +}; + +static final CoordRec char105_stroke1[] = { + new CoordRec((float) 14.7819, (float) 66.6667), + new CoordRec((float) 14.7819, (float) 0), +}; + +static final StrokeRec char105[] = { + new StrokeRec(5, char105_stroke0), + new StrokeRec(2, char105_stroke1), +}; + +/* char: 106 'j' */ + +static final CoordRec char106_stroke0[] = { + new CoordRec((float) 17.3876, (float) 100), + new CoordRec((float) 22.1495, (float) 95.2381), + new CoordRec((float) 26.9114, (float) 100), + new CoordRec((float) 22.1495, (float) 104.762), + new CoordRec((float) 17.3876, (float) 100), +}; + +static final CoordRec char106_stroke1[] = { + new CoordRec((float) 22.1495, (float) 66.6667), + new CoordRec((float) 22.1495, (float) -14.2857), + new CoordRec((float) 17.3876, (float) -28.5714), + new CoordRec((float) 7.8638, (float) -33.3333), + new CoordRec((float)-1.66, (float) -33.3333), +}; + +static final StrokeRec char106[] = { + new StrokeRec(5, char106_stroke0), + new StrokeRec(5, char106_stroke1), +}; + +/* char: 107 'k' */ + +static final CoordRec char107_stroke0[] = { + new CoordRec((float) 9.6, (float) 100), + new CoordRec((float) 9.6, (float) 0), +}; + +static final CoordRec char107_stroke1[] = { + new CoordRec((float) 57.219, (float) 66.6667), + new CoordRec((float) 9.6, (float) 19.0476), +}; + +static final CoordRec char107_stroke2[] = { + new CoordRec((float) 28.6476, (float) 38.0952), + new CoordRec((float) 61.981, (float) 0), +}; + +static final StrokeRec char107[] = { + new StrokeRec(2, char107_stroke0), + new StrokeRec(2, char107_stroke1), + new StrokeRec(2, char107_stroke2), +}; + +/* char: 108 'l' */ + +static final CoordRec char108_stroke0[] = { + new CoordRec((float) 10.02, (float) 100), + new CoordRec((float) 10.02, (float) 0), +}; + +static final StrokeRec char108[] = { + new StrokeRec(2, char108_stroke0), +}; + +/* char: 109 'm' */ + +static final CoordRec char109_stroke0[] = { + new CoordRec((float) 9.6, (float) 66.6667), + new CoordRec((float) 9.6, (float) 0), +}; + +static final CoordRec char109_stroke1[] = { + new CoordRec((float) 9.6, (float) 47.619), + new CoordRec((float) 23.8857, (float) 61.9048), + new CoordRec((float) 33.4095, (float) 66.6667), + new CoordRec((float) 47.6952, (float) 66.6667), + new CoordRec((float) 57.219, (float) 61.9048), + new CoordRec((float) 61.981, (float) 47.619), + new CoordRec((float) 61.981, (float) 0), +}; + +static final CoordRec char109_stroke2[] = { + new CoordRec((float) 61.981, (float) 47.619), + new CoordRec((float) 76.2667, (float) 61.9048), + new CoordRec((float) 85.7905, (float) 66.6667), + new CoordRec((float) 100.076, (float) 66.6667), + new CoordRec((float) 109.6, (float) 61.9048), + new CoordRec((float) 114.362, (float) 47.619), + new CoordRec((float) 114.362, (float) 0), +}; + +static final StrokeRec char109[] = { + new StrokeRec(2, char109_stroke0), + new StrokeRec(7, char109_stroke1), + new StrokeRec(7, char109_stroke2), +}; + +/* char: 110 'n' */ + +static final CoordRec char110_stroke0[] = { + new CoordRec((float) 9.18, (float) 66.6667), + new CoordRec((float) 9.18, (float) 0), +}; + +static final CoordRec char110_stroke1[] = { + new CoordRec((float) 9.18, (float) 47.619), + new CoordRec((float) 23.4657, (float) 61.9048), + new CoordRec((float) 32.9895, (float) 66.6667), + new CoordRec((float) 47.2752, (float) 66.6667), + new CoordRec((float) 56.799, (float) 61.9048), + new CoordRec((float) 61.561, (float) 47.619), + new CoordRec((float) 61.561, (float) 0), +}; + +static final StrokeRec char110[] = { + new StrokeRec(2, char110_stroke0), + new StrokeRec(7, char110_stroke1), +}; + +/* char: 111 'o' */ + +static final CoordRec char111_stroke0[] = { + new CoordRec((float) 28.7895, (float) 66.6667), + new CoordRec((float) 19.2657, (float) 61.9048), + new CoordRec((float) 9.7419, (float) 52.381), + new CoordRec((float) 4.98, (float) 38.0952), + new CoordRec((float) 4.98, (float) 28.5714), + new CoordRec((float) 9.7419, (float) 14.2857), + new CoordRec((float) 19.2657, (float) 4.7619), + new CoordRec((float) 28.7895, (float) 0), + new CoordRec((float) 43.0752, (float) 0), + new CoordRec((float) 52.599, (float) 4.7619), + new CoordRec((float) 62.1229, (float) 14.2857), + new CoordRec((float) 66.8848, (float) 28.5714), + new CoordRec((float) 66.8848, (float) 38.0952), + new CoordRec((float) 62.1229, (float) 52.381), + new CoordRec((float) 52.599, (float) 61.9048), + new CoordRec((float) 43.0752, (float) 66.6667), + new CoordRec((float) 28.7895, (float) 66.6667), +}; + +static final StrokeRec char111[] = { + new StrokeRec(17, char111_stroke0), +}; + +/* char: 112 'p' */ + +static final CoordRec char112_stroke0[] = { + new CoordRec((float) 9.46, (float) 66.6667), + new CoordRec((float) 9.46, (float) -33.3333), +}; + +static final CoordRec char112_stroke1[] = { + new CoordRec((float) 9.46, (float) 52.381), + new CoordRec((float) 18.9838, (float) 61.9048), + new CoordRec((float) 28.5076, (float) 66.6667), + new CoordRec((float) 42.7933, (float) 66.6667), + new CoordRec((float) 52.3171, (float) 61.9048), + new CoordRec((float) 61.841, (float) 52.381), + new CoordRec((float) 66.6029, (float) 38.0952), + new CoordRec((float) 66.6029, (float) 28.5714), + new CoordRec((float) 61.841, (float) 14.2857), + new CoordRec((float) 52.3171, (float) 4.7619), + new CoordRec((float) 42.7933, (float) 0), + new CoordRec((float) 28.5076, (float) 0), + new CoordRec((float) 18.9838, (float) 4.7619), + new CoordRec((float) 9.46, (float) 14.2857), +}; + +static final StrokeRec char112[] = { + new StrokeRec(2, char112_stroke0), + new StrokeRec(14, char112_stroke1), +}; + +/* char: 113 'q' */ + +static final CoordRec char113_stroke0[] = { + new CoordRec((float) 61.9829, (float) 66.6667), + new CoordRec((float) 61.9829, (float) -33.3333), +}; + +static final CoordRec char113_stroke1[] = { + new CoordRec((float) 61.9829, (float) 52.381), + new CoordRec((float) 52.459, (float) 61.9048), + new CoordRec((float) 42.9352, (float) 66.6667), + new CoordRec((float) 28.6495, (float) 66.6667), + new CoordRec((float) 19.1257, (float) 61.9048), + new CoordRec((float) 9.6019, (float) 52.381), + new CoordRec((float) 4.84, (float) 38.0952), + new CoordRec((float) 4.84, (float) 28.5714), + new CoordRec((float) 9.6019, (float) 14.2857), + new CoordRec((float) 19.1257, (float) 4.7619), + new CoordRec((float) 28.6495, (float) 0), + new CoordRec((float) 42.9352, (float) 0), + new CoordRec((float) 52.459, (float) 4.7619), + new CoordRec((float) 61.9829, (float) 14.2857), +}; + +static final StrokeRec char113[] = { + new StrokeRec(2, char113_stroke0), + new StrokeRec(14, char113_stroke1), +}; + +/* char: 114 'r' */ + +static final CoordRec char114_stroke0[] = { + new CoordRec((float) 9.46, (float) 66.6667), + new CoordRec((float) 9.46, (float) 0), +}; + +static final CoordRec char114_stroke1[] = { + new CoordRec((float) 9.46, (float) 38.0952), + new CoordRec((float) 14.2219, (float) 52.381), + new CoordRec((float) 23.7457, (float) 61.9048), + new CoordRec((float) 33.2695, (float) 66.6667), + new CoordRec((float) 47.5552, (float) 66.6667), +}; + +static final StrokeRec char114[] = { + new StrokeRec(2, char114_stroke0), + new StrokeRec(5, char114_stroke1), +}; + +/* char: 115 's' */ + +static final CoordRec char115_stroke0[] = { + new CoordRec((float) 57.081, (float) 52.381), + new CoordRec((float) 52.319, (float) 61.9048), + new CoordRec((float) 38.0333, (float) 66.6667), + new CoordRec((float) 23.7476, (float) 66.6667), + new CoordRec((float) 9.4619, (float) 61.9048), + new CoordRec((float) 4.7, (float) 52.381), + new CoordRec((float) 9.4619, (float) 42.8571), + new CoordRec((float) 18.9857, (float) 38.0952), + new CoordRec((float) 42.7952, (float) 33.3333), + new CoordRec((float) 52.319, (float) 28.5714), + new CoordRec((float) 57.081, (float) 19.0476), + new CoordRec((float) 57.081, (float) 14.2857), + new CoordRec((float) 52.319, (float) 4.7619), + new CoordRec((float) 38.0333, (float) 0), + new CoordRec((float) 23.7476, (float) 0), + new CoordRec((float) 9.4619, (float) 4.7619), + new CoordRec((float) 4.7, (float) 14.2857), +}; + +static final StrokeRec char115[] = { + new StrokeRec(17, char115_stroke0), +}; + +/* char: 116 't' */ + +static final CoordRec char116_stroke0[] = { + new CoordRec((float) 14.8257, (float) 100), + new CoordRec((float) 14.8257, (float) 19.0476), + new CoordRec((float) 19.5876, (float) 4.7619), + new CoordRec((float) 29.1114, (float) 0), + new CoordRec((float) 38.6352, (float) 0), +}; + +static final CoordRec char116_stroke1[] = { + new CoordRec((float) 0.54, (float) 66.6667), + new CoordRec((float) 33.8733, (float) 66.6667), +}; + +static final StrokeRec char116[] = { + new StrokeRec(5, char116_stroke0), + new StrokeRec(2, char116_stroke1), +}; + +/* char: 117 'u' */ + +static final CoordRec char117_stroke0[] = { + new CoordRec((float) 9.46, (float) 66.6667), + new CoordRec((float) 9.46, (float) 19.0476), + new CoordRec((float) 14.2219, (float) 4.7619), + new CoordRec((float) 23.7457, (float) 0), + new CoordRec((float) 38.0314, (float) 0), + new CoordRec((float) 47.5552, (float) 4.7619), + new CoordRec((float) 61.841, (float) 19.0476), +}; + +static final CoordRec char117_stroke1[] = { + new CoordRec((float) 61.841, (float) 66.6667), + new CoordRec((float) 61.841, (float) 0), +}; + +static final StrokeRec char117[] = { + new StrokeRec(7, char117_stroke0), + new StrokeRec(2, char117_stroke1), +}; + +/* char: 118 'v' */ + +static final CoordRec char118_stroke0[] = { + new CoordRec((float) 1.8, (float) 66.6667), + new CoordRec((float) 30.3714, (float) 0), +}; + +static final CoordRec char118_stroke1[] = { + new CoordRec((float) 58.9429, (float) 66.6667), + new CoordRec((float) 30.3714, (float) 0), +}; + +static final StrokeRec char118[] = { + new StrokeRec(2, char118_stroke0), + new StrokeRec(2, char118_stroke1), +}; + +/* char: 119 'w' */ + +static final CoordRec char119_stroke0[] = { + new CoordRec((float) 2.5, (float) 66.6667), + new CoordRec((float) 21.5476, (float) 0), +}; + +static final CoordRec char119_stroke1[] = { + new CoordRec((float) 40.5952, (float) 66.6667), + new CoordRec((float) 21.5476, (float) 0), +}; + +static final CoordRec char119_stroke2[] = { + new CoordRec((float) 40.5952, (float) 66.6667), + new CoordRec((float) 59.6429, (float) 0), +}; + +static final CoordRec char119_stroke3[] = { + new CoordRec((float) 78.6905, (float) 66.6667), + new CoordRec((float) 59.6429, (float) 0), +}; + +static final StrokeRec char119[] = { + new StrokeRec(2, char119_stroke0), + new StrokeRec(2, char119_stroke1), + new StrokeRec(2, char119_stroke2), + new StrokeRec(2, char119_stroke3), +}; + +/* char: 120 'x' */ + +static final CoordRec char120_stroke0[] = { + new CoordRec((float) 1.66, (float) 66.6667), + new CoordRec((float) 54.041, (float) 0), +}; + +static final CoordRec char120_stroke1[] = { + new CoordRec((float) 54.041, (float) 66.6667), + new CoordRec((float) 1.66, (float) 0), +}; + +static final StrokeRec char120[] = { + new StrokeRec(2, char120_stroke0), + new StrokeRec(2, char120_stroke1), +}; + +/* char: 121 'y' */ + +static final CoordRec char121_stroke0[] = { + new CoordRec((float) 6.5619, (float) 66.6667), + new CoordRec((float) 35.1333, (float) 0), +}; + +static final CoordRec char121_stroke1[] = { + new CoordRec((float) 63.7048, (float) 66.6667), + new CoordRec((float) 35.1333, (float) 0), + new CoordRec((float) 25.6095, (float) -19.0476), + new CoordRec((float) 16.0857, (float) -28.5714), + new CoordRec((float) 6.5619, (float) -33.3333), + new CoordRec((float) 1.8, (float) -33.3333), +}; + +static final StrokeRec char121[] = { + new StrokeRec(2, char121_stroke0), + new StrokeRec(6, char121_stroke1), +}; + +/* char: 122 'z' */ + +static final CoordRec char122_stroke0[] = { + new CoordRec((float) 56.821, (float) 66.6667), + new CoordRec((float) 4.44, (float) 0), +}; + +static final CoordRec char122_stroke1[] = { + new CoordRec((float) 4.44, (float) 66.6667), + new CoordRec((float) 56.821, (float) 66.6667), +}; + +static final CoordRec char122_stroke2[] = { + new CoordRec((float) 4.44, (float) 0), + new CoordRec((float) 56.821, (float) 0), +}; + +static final StrokeRec char122[] = { + new StrokeRec(2, char122_stroke0), + new StrokeRec(2, char122_stroke1), + new StrokeRec(2, char122_stroke2), +}; + +/* char: 123 '{' */ + +static final CoordRec char123_stroke0[] = { + new CoordRec((float) 31.1895, (float) 119.048), + new CoordRec((float) 21.6657, (float) 114.286), + new CoordRec((float) 16.9038, (float) 109.524), + new CoordRec((float) 12.1419, (float) 100), + new CoordRec((float) 12.1419, (float) 90.4762), + new CoordRec((float) 16.9038, (float) 80.9524), + new CoordRec((float) 21.6657, (float) 76.1905), + new CoordRec((float) 26.4276, (float) 66.6667), + new CoordRec((float) 26.4276, (float) 57.1429), + new CoordRec((float) 16.9038, (float) 47.619), +}; + +static final CoordRec char123_stroke1[] = { + new CoordRec((float) 21.6657, (float) 114.286), + new CoordRec((float) 16.9038, (float) 104.762), + new CoordRec((float) 16.9038, (float) 95.2381), + new CoordRec((float) 21.6657, (float) 85.7143), + new CoordRec((float) 26.4276, (float) 80.9524), + new CoordRec((float) 31.1895, (float) 71.4286), + new CoordRec((float) 31.1895, (float) 61.9048), + new CoordRec((float) 26.4276, (float) 52.381), + new CoordRec((float) 7.38, (float) 42.8571), + new CoordRec((float) 26.4276, (float) 33.3333), + new CoordRec((float) 31.1895, (float) 23.8095), + new CoordRec((float) 31.1895, (float) 14.2857), + new CoordRec((float) 26.4276, (float) 4.7619), + new CoordRec((float) 21.6657, (float) 0), + new CoordRec((float) 16.9038, (float) -9.5238), + new CoordRec((float) 16.9038, (float) -19.0476), + new CoordRec((float) 21.6657, (float) -28.5714), +}; + +static final CoordRec char123_stroke2[] = { + new CoordRec((float) 16.9038, (float) 38.0952), + new CoordRec((float) 26.4276, (float) 28.5714), + new CoordRec((float) 26.4276, (float) 19.0476), + new CoordRec((float) 21.6657, (float) 9.5238), + new CoordRec((float) 16.9038, (float) 4.7619), + new CoordRec((float) 12.1419, (float) -4.7619), + new CoordRec((float) 12.1419, (float) -14.2857), + new CoordRec((float) 16.9038, (float) -23.8095), + new CoordRec((float) 21.6657, (float) -28.5714), + new CoordRec((float) 31.1895, (float) -33.3333), +}; + +static final StrokeRec char123[] = { + new StrokeRec(10, char123_stroke0), + new StrokeRec(17, char123_stroke1), + new StrokeRec(10, char123_stroke2), +}; + +/* char: 124 '|' */ + +static final CoordRec char124_stroke0[] = { + new CoordRec((float) 11.54, (float) 119.048), + new CoordRec((float) 11.54, (float) -33.3333), +}; + +static final StrokeRec char124[] = { + new StrokeRec(2, char124_stroke0), +}; + +/* char: 125 '}' */ + +static final CoordRec char125_stroke0[] = { + new CoordRec((float) 9.18, (float) 119.048), + new CoordRec((float) 18.7038, (float) 114.286), + new CoordRec((float) 23.4657, (float) 109.524), + new CoordRec((float) 28.2276, (float) 100), + new CoordRec((float) 28.2276, (float) 90.4762), + new CoordRec((float) 23.4657, (float) 80.9524), + new CoordRec((float) 18.7038, (float) 76.1905), + new CoordRec((float) 13.9419, (float) 66.6667), + new CoordRec((float) 13.9419, (float) 57.1429), + new CoordRec((float) 23.4657, (float) 47.619), +}; + +static final CoordRec char125_stroke1[] = { + new CoordRec((float) 18.7038, (float) 114.286), + new CoordRec((float) 23.4657, (float) 104.762), + new CoordRec((float) 23.4657, (float) 95.2381), + new CoordRec((float) 18.7038, (float) 85.7143), + new CoordRec((float) 13.9419, (float) 80.9524), + new CoordRec((float) 9.18, (float) 71.4286), + new CoordRec((float) 9.18, (float) 61.9048), + new CoordRec((float) 13.9419, (float) 52.381), + new CoordRec((float) 32.9895, (float) 42.8571), + new CoordRec((float) 13.9419, (float) 33.3333), + new CoordRec((float) 9.18, (float) 23.8095), + new CoordRec((float) 9.18, (float) 14.2857), + new CoordRec((float) 13.9419, (float) 4.7619), + new CoordRec((float) 18.7038, (float) 0), + new CoordRec((float) 23.4657, (float) -9.5238), + new CoordRec((float) 23.4657, (float) -19.0476), + new CoordRec((float) 18.7038, (float) -28.5714), +}; + +static final CoordRec char125_stroke2[] = { + new CoordRec((float) 23.4657, (float) 38.0952), + new CoordRec((float) 13.9419, (float) 28.5714), + new CoordRec((float) 13.9419, (float) 19.0476), + new CoordRec((float) 18.7038, (float) 9.5238), + new CoordRec((float) 23.4657, (float) 4.7619), + new CoordRec((float) 28.2276, (float) -4.7619), + new CoordRec((float) 28.2276, (float) -14.2857), + new CoordRec((float) 23.4657, (float) -23.8095), + new CoordRec((float) 18.7038, (float) -28.5714), + new CoordRec((float) 9.18, (float) -33.3333), +}; + +static final StrokeRec char125[] = { + new StrokeRec(10, char125_stroke0), + new StrokeRec(17, char125_stroke1), + new StrokeRec(10, char125_stroke2), +}; + +/* char: 126 '~' */ + +static final CoordRec char126_stroke0[] = { + new CoordRec((float) 2.92, (float) 28.5714), + new CoordRec((float) 2.92, (float) 38.0952), + new CoordRec((float) 7.6819, (float) 52.381), + new CoordRec((float) 17.2057, (float) 57.1429), + new CoordRec((float) 26.7295, (float) 57.1429), + new CoordRec((float) 36.2533, (float) 52.381), + new CoordRec((float) 55.301, (float) 38.0952), + new CoordRec((float) 64.8248, (float) 33.3333), + new CoordRec((float) 74.3486, (float) 33.3333), + new CoordRec((float) 83.8724, (float) 38.0952), + new CoordRec((float) 88.6343, (float) 47.619), +}; + +static final CoordRec char126_stroke1[] = { + new CoordRec((float) 2.92, (float) 38.0952), + new CoordRec((float) 7.6819, (float) 47.619), + new CoordRec((float) 17.2057, (float) 52.381), + new CoordRec((float) 26.7295, (float) 52.381), + new CoordRec((float) 36.2533, (float) 47.619), + new CoordRec((float) 55.301, (float) 33.3333), + new CoordRec((float) 64.8248, (float) 28.5714), + new CoordRec((float) 74.3486, (float) 28.5714), + new CoordRec((float) 83.8724, (float) 33.3333), + new CoordRec((float) 88.6343, (float) 47.619), + new CoordRec((float) 88.6343, (float) 57.1429), +}; + +static final StrokeRec char126[] = { + new StrokeRec(11, char126_stroke0), + new StrokeRec(11, char126_stroke1), +}; + +/* char: 127 */ + +static final CoordRec char127_stroke0[] = { + new CoordRec((float) 52.381, (float) 100), + new CoordRec((float) 14.2857, (float) -33.3333), +}; + +static final CoordRec char127_stroke1[] = { + new CoordRec((float) 28.5714, (float) 66.6667), + new CoordRec((float) 14.2857, (float) 61.9048), + new CoordRec((float) 4.7619, (float) 52.381), + new CoordRec((float) 0, (float) 38.0952), + new CoordRec((float) 0, (float) 23.8095), + new CoordRec((float) 4.7619, (float) 14.2857), + new CoordRec((float) 14.2857, (float) 4.7619), + new CoordRec((float) 28.5714, (float) 0), + new CoordRec((float) 38.0952, (float) 0), + new CoordRec((float) 52.381, (float) 4.7619), + new CoordRec((float) 61.9048, (float) 14.2857), + new CoordRec((float) 66.6667, (float) 28.5714), + new CoordRec((float) 66.6667, (float) 42.8571), + new CoordRec((float) 61.9048, (float) 52.381), + new CoordRec((float) 52.381, (float) 61.9048), + new CoordRec((float) 38.0952, (float) 66.6667), + new CoordRec((float) 28.5714, (float) 66.6667), +}; + +static final StrokeRec char127[] = { + new StrokeRec(2, char127_stroke0), + new StrokeRec(17, char127_stroke1), +}; + +static final StrokeCharRec chars[] = { + new StrokeCharRec( 0, /* char0 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char1 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char2 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char3 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char4 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char5 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char6 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char7 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char8 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char9 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char10 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char11 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char12 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char13 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char14 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char15 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char16 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char17 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char18 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char19 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char20 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char21 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char22 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char23 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char24 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char25 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char26 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char27 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char28 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char29 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char30 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char31 */ null, (float) 0, (float) 0 ), + new StrokeCharRec( 0, /* char32 */ null, (float) 52.381, (float) 104.762 ), + new StrokeCharRec( 2, char33, (float) 13.3819, (float) 26.6238 ), + new StrokeCharRec( 2, char34, (float) 23.0676, (float) 51.4352 ), + new StrokeCharRec( 4, char35, (float) 36.5333, (float) 79.4886 ), + new StrokeCharRec( 3, char36, (float) 38.1533, (float) 76.2067 ), + new StrokeCharRec( 3, char37, (float) 49.2171, (float) 96.5743 ), + new StrokeCharRec( 1, char38, (float) 53.599, (float) 101.758 ), + new StrokeCharRec( 1, char39, (float) 4.44, (float) 13.62 ), + new StrokeCharRec( 1, char40, (float) 21.8657, (float) 47.1733 ), + new StrokeCharRec( 1, char41, (float) 24.3276, (float) 47.5333 ), + new StrokeCharRec( 3, char42, (float) 30.7695, (float) 59.439 ), + new StrokeCharRec( 2, char43, (float) 48.8371, (float) 97.2543 ), + new StrokeCharRec( 1, char44, (float) 13.5219, (float) 26.0638 ), + new StrokeCharRec( 1, char45, (float) 50.2371, (float) 100.754 ), + new StrokeCharRec( 1, char46, (float) 13.1019, (float) 26.4838 ), + new StrokeCharRec( 1, char47, (float) 40.5733, (float) 82.1067 ), + new StrokeCharRec( 1, char48, (float) 38.3133, (float) 77.0667 ), + new StrokeCharRec( 1, char49, (float) 30.8676, (float) 66.5295 ), + new StrokeCharRec( 1, char50, (float) 38.7533, (float) 77.6467 ), + new StrokeCharRec( 1, char51, (float) 38.3333, (float) 77.0467 ), + new StrokeCharRec( 2, char52, (float) 37.2133, (float) 80.1686 ), + new StrokeCharRec( 1, char53, (float) 38.1933, (float) 77.6867 ), + new StrokeCharRec( 1, char54, (float) 34.1514, (float) 73.8048 ), + new StrokeCharRec( 2, char55, (float) 38.8933, (float) 77.2267 ), + new StrokeCharRec( 1, char56, (float) 38.9333, (float) 77.6667 ), + new StrokeCharRec( 1, char57, (float) 39.9333, (float) 74.0648 ), + new StrokeCharRec( 2, char58, (float) 14.0819, (float) 26.2238 ), + new StrokeCharRec( 2, char59, (float) 12.9619, (float) 26.3038 ), + new StrokeCharRec( 1, char60, (float) 41.1552, (float) 81.6105 ), + new StrokeCharRec( 2, char61, (float) 48.5571, (float) 97.2543 ), + new StrokeCharRec( 1, char62, (float) 40.8752, (float) 81.6105 ), + new StrokeCharRec( 2, char63, (float) 36.9914, (float) 73.9029 ), + new StrokeCharRec( 2, char64, (float) 34.9314, (float) 74.3648 ), + new StrokeCharRec( 3, char65, (float) 40.5952, (float) 80.4905 ), + new StrokeCharRec( 3, char66, (float) 44.7533, (float) 83.6267 ), + new StrokeCharRec( 1, char67, (float) 39.9933, (float) 84.4886 ), + new StrokeCharRec( 2, char68, (float) 45.2933, (float) 85.2867 ), + new StrokeCharRec( 4, char69, (float) 39.9914, (float) 78.1848 ), + new StrokeCharRec( 3, char70, (float) 39.9914, (float) 78.7448 ), + new StrokeCharRec( 2, char71, (float) 40.3933, (float) 89.7686 ), + new StrokeCharRec( 3, char72, (float) 44.7533, (float) 89.0867 ), + new StrokeCharRec( 1, char73, (float) 10.86, (float) 21.3 ), + new StrokeCharRec( 1, char74, (float) 31.0714, (float) 59.999 ), + new StrokeCharRec( 3, char75, (float) 44.6133, (float) 79.3267 ), + new StrokeCharRec( 2, char76, (float) 40.2514, (float) 71.3229 ), + new StrokeCharRec( 4, char77, (float) 48.9552, (float) 97.2105 ), + new StrokeCharRec( 3, char78, (float) 44.4733, (float) 88.8067 ), + new StrokeCharRec( 1, char79, (float) 44.3352, (float) 88.8305 ), + new StrokeCharRec( 2, char80, (float) 45.4333, (float) 85.6667 ), + new StrokeCharRec( 2, char81, (float) 43.3952, (float) 88.0905 ), + new StrokeCharRec( 3, char82, (float) 45.0133, (float) 82.3667 ), + new StrokeCharRec( 1, char83, (float) 41.3333, (float) 80.8267 ), + new StrokeCharRec( 2, char84, (float) 35.6933, (float) 71.9467 ), + new StrokeCharRec( 1, char85, (float) 44.8733, (float) 89.4867 ), + new StrokeCharRec( 2, char86, (float) 40.4552, (float) 81.6105 ), + new StrokeCharRec( 4, char87, (float) 49.839, (float) 100.518 ), + new StrokeCharRec( 2, char88, (float) 35.8333, (float) 72.3667 ), + new StrokeCharRec( 2, char89, (float) 39.6152, (float) 79.6505 ), + new StrokeCharRec( 3, char90, (float) 35.8333, (float) 73.7467 ), + new StrokeCharRec( 4, char91, (float) 22.0657, (float) 46.1133 ), + new StrokeCharRec( 1, char92, (float) 39.1733, (float) 78.2067 ), + new StrokeCharRec( 4, char93, (float) 23.4876, (float) 46.3933 ), + new StrokeCharRec( 2, char94, (float) 44.0752, (float) 90.2305 ), + new StrokeCharRec( 1, char95, (float) 51.281, (float) 104.062 ), + new StrokeCharRec( 2, char96, (float) 42.5457, (float) 83.5714 ), + new StrokeCharRec( 2, char97, (float) 35.2514, (float) 66.6029 ), + new StrokeCharRec( 2, char98, (float) 37.3314, (float) 70.4629 ), + new StrokeCharRec( 1, char99, (float) 34.0914, (float) 68.9229 ), + new StrokeCharRec( 2, char100, (float) 33.2114, (float) 70.2629 ), + new StrokeCharRec( 1, char101, (float) 34.2914, (float) 68.5229 ), + new StrokeCharRec( 2, char102, (float) 14.9657, (float) 38.6552 ), + new StrokeCharRec( 2, char103, (float) 33.9314, (float) 70.9829 ), + new StrokeCharRec( 2, char104, (float) 33.4095, (float) 71.021 ), + new StrokeCharRec( 2, char105, (float) 14.7819, (float) 28.8638 ), + new StrokeCharRec( 2, char106, (float) 17.3876, (float) 36.2314 ), + new StrokeCharRec( 3, char107, (float) 33.4095, (float) 62.521 ), + new StrokeCharRec( 1, char108, (float) 10.02, (float) 19.34 ), + new StrokeCharRec( 3, char109, (float) 61.981, (float) 123.962 ), + new StrokeCharRec( 2, char110, (float) 32.9895, (float) 70.881 ), + new StrokeCharRec( 1, char111, (float) 33.5514, (float) 71.7448 ), + new StrokeCharRec( 2, char112, (float) 38.0314, (float) 70.8029 ), + new StrokeCharRec( 2, char113, (float) 33.4114, (float) 70.7429 ), + new StrokeCharRec( 2, char114, (float) 23.7457, (float) 49.4952 ), + new StrokeCharRec( 1, char115, (float) 28.5095, (float) 62.321 ), + new StrokeCharRec( 2, char116, (float) 14.8257, (float) 39.3152 ), + new StrokeCharRec( 2, char117, (float) 33.2695, (float) 71.161 ), + new StrokeCharRec( 2, char118, (float) 30.3714, (float) 60.6029 ), + new StrokeCharRec( 4, char119, (float) 40.5952, (float) 80.4905 ), + new StrokeCharRec( 2, char120, (float) 25.4695, (float) 56.401 ), + new StrokeCharRec( 2, char121, (float) 35.1333, (float) 66.0648 ), + new StrokeCharRec( 3, char122, (float) 28.2495, (float) 61.821 ), + new StrokeCharRec( 3, char123, (float) 21.6657, (float) 41.6295 ), + new StrokeCharRec( 1, char124, (float) 11.54, (float) 23.78 ), + new StrokeCharRec( 3, char125, (float) 18.7038, (float) 41.4695 ), + new StrokeCharRec( 2, char126, (float) 45.7771, (float) 91.2743 ), + new StrokeCharRec( 2, char127, (float) 33.3333, (float) 66.6667 ), +}; + +public static final StrokeFontRec glutStrokeRoman = new StrokeFontRec( "Roman", 128, chars, (float) 119.048, (float) -33.3333 ); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java new file mode 100644 index 000000000..af3d538ae --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeCharRec.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class StrokeCharRec { + public int num_strokes; + public StrokeRec[] stroke; + public float center; + public float right; + + public StrokeCharRec(int num_strokes, + StrokeRec[] stroke, + float center, + float right) { + this.num_strokes = num_strokes; + this.stroke = stroke; + this.center = center; + this.right = right; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java new file mode 100644 index 000000000..d3195f24d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeFontRec.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class StrokeFontRec { + public String name; + public int num_chars; + public StrokeCharRec[] ch; + public float top; + public float bottom; + + public StrokeFontRec(String name, + int num_chars, + StrokeCharRec[] ch, + float top, + float bottom) { + this.name = name; + this.num_chars = num_chars; + this.ch = ch; + this.top = top; + this.bottom = bottom; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java new file mode 100644 index 000000000..8796e8b08 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/StrokeRec.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.gl2; + +/* Copyright (c) Mark J. Kilgard, 1994, 1998. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +class StrokeRec { + public int num_coords; + public CoordRec[] coord; + + public StrokeRec(int num_coords, + CoordRec[] coord) { + this.num_coords = num_coords; + this.coord = coord; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java new file mode 100755 index 000000000..714c134d4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/gl2/TileRenderer.java @@ -0,0 +1,601 @@ +package com.jogamp.opengl.util.gl2; + +import java.awt.Dimension; +import java.nio.Buffer; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.opengl.glu.gl2.*; + +/** + * A fairly direct port of Brian Paul's tile rendering library, found + * at <a href = "http://www.mesa3d.org/brianp/TR.html"> + * http://www.mesa3d.org/brianp/TR.html </a> . I've java-fied it, but + * the functionality is the same. + * + * Original code Copyright (C) 1997-2005 Brian Paul. Licensed under + * BSD-compatible terms with permission of the author. See LICENSE.txt + * for license information. + * + * @author ryanm + */ +public class TileRenderer +{ + private static final int DEFAULT_TILE_WIDTH = 256; + + private static final int DEFAULT_TILE_HEIGHT = 256; + + private static final int DEFAULT_TILE_BORDER = 0; + + // + // Enumeration flags for accessing variables + // + // @author ryanm + // + + /** + * The width of a tile + */ + public static final int TR_TILE_WIDTH = 0; + /** + * The height of a tile + */ + public static final int TR_TILE_HEIGHT = 1; + /** + * The width of the border around the tiles + */ + public static final int TR_TILE_BORDER = 2; + /** + * The width of the final image + */ + public static final int TR_IMAGE_WIDTH = 3; + /** + * The height of the final image + */ + public static final int TR_IMAGE_HEIGHT = 4; + /** + * The number of rows of tiles + */ + public static final int TR_ROWS = 5; + /** + * The number of columns of tiles + */ + public static final int TR_COLUMNS = 6; + /** + * The current row number + */ + public static final int TR_CURRENT_ROW = 7; + /** + * The current column number + */ + public static final int TR_CURRENT_COLUMN = 8; + /** + * The width of the current tile + */ + public static final int TR_CURRENT_TILE_WIDTH = 9; + /** + * The height of the current tile + */ + public static final int TR_CURRENT_TILE_HEIGHT = 10; + /** + * The order that the rows are traversed + */ + public static final int TR_ROW_ORDER = 11; + + + /** + * Indicates we are traversing rows from the top to the bottom + */ + public static final int TR_TOP_TO_BOTTOM = 1; + + /** + * Indicates we are traversing rows from the bottom to the top + */ + public static final int TR_BOTTOM_TO_TOP = 2; + + /* Final image parameters */ + private Dimension imageSize = new Dimension(); + + private int imageFormat, imageType; + + private Buffer imageBuffer; + + /* Tile parameters */ + private Dimension tileSize = new Dimension(); + + private Dimension tileSizeNB = new Dimension(); + + private int tileBorder; + + private int tileFormat, tileType; + + private Buffer tileBuffer; + + /* Projection parameters */ + private boolean perspective; + + private double left; + + private double right; + + private double bottom; + + private double top; + + private double near; + + private double far; + + /* Misc */ + private int rowOrder; + + private int rows, columns; + + private int currentTile; + + private int currentTileWidth, currentTileHeight; + + private int currentRow, currentColumn; + + private int[] viewportSave = new int[ 4 ]; + + /** + * Creates a new TileRenderer object + */ + public TileRenderer() + { + tileSize.width = DEFAULT_TILE_WIDTH; + tileSize.height = DEFAULT_TILE_HEIGHT; + tileBorder = DEFAULT_TILE_BORDER; + rowOrder = TR_BOTTOM_TO_TOP; + currentTile = -1; + } + + /** + * Sets up the number of rows and columns needed + */ + private void setup() + { + columns = ( imageSize.width + tileSizeNB.width - 1 ) / tileSizeNB.width; + rows = ( imageSize.height + tileSizeNB.height - 1 ) / tileSizeNB.height; + currentTile = 0; + + assert columns >= 0; + assert rows >= 0; + } + + /** + * Sets the size of the tiles to use in rendering. The actual + * effective size of the tile depends on the border size, ie ( + * width - 2*border ) * ( height - 2 * border ) + * + * @param width + * The width of the tiles. Must not be larger than the GL + * context + * @param height + * The height of the tiles. Must not be larger than the + * GL context + * @param border + * The width of the borders on each tile. This is needed + * to avoid artifacts when rendering lines or points with + * thickness > 1. + */ + public void setTileSize( int width, int height, int border ) + { + assert ( border >= 0 ); + assert ( width >= 1 ); + assert ( height >= 1 ); + assert ( width >= 2 * border ); + assert ( height >= 2 * border ); + + tileBorder = border; + tileSize.width = width; + tileSize.height = height; + tileSizeNB.width = width - 2 * border; + tileSizeNB.height = height - 2 * border; + setup(); + } + + /** + * Specify a buffer the tiles to be copied to. This is not + * necessary for the creation of the final image, but useful if you + * want to inspect each tile in turn. + * + * @param format + * Interpreted as in glReadPixels + * @param type + * Interpreted as in glReadPixels + * @param image + * The buffer itself. Must be large enough to contain a + * tile, minus any borders + */ + public void setTileBuffer( int format, int type, Buffer image ) + { + tileFormat = format; + tileType = type; + tileBuffer = image; + } + + /** + * Sets the desired size of the final image + * + * @param width + * The width of the final image + * @param height + * The height of the final image + */ + public void setImageSize( int width, int height ) + { + imageSize.width = width; + imageSize.height = height; + setup(); + } + + /** + * Sets the buffer in which to store the final image + * + * @param format + * Interpreted as in glReadPixels + * @param type + * Interpreted as in glReadPixels + * @param image + * the buffer itself, must be large enough to hold the + * final image + */ + public void setImageBuffer( int format, int type, Buffer image ) + { + imageFormat = format; + imageType = type; + imageBuffer = image; + } + + /** + * Gets the parameters of this TileRenderer object + * + * @param param + * The parameter that is to be retrieved + * @return the value of the parameter + */ + public int getParam( int param ) + { + switch (param) { + case TR_TILE_WIDTH: + return tileSize.width; + case TR_TILE_HEIGHT: + return tileSize.height; + case TR_TILE_BORDER: + return tileBorder; + case TR_IMAGE_WIDTH: + return imageSize.width; + case TR_IMAGE_HEIGHT: + return imageSize.height; + case TR_ROWS: + return rows; + case TR_COLUMNS: + return columns; + case TR_CURRENT_ROW: + if( currentTile < 0 ) + return -1; + else + return currentRow; + case TR_CURRENT_COLUMN: + if( currentTile < 0 ) + return -1; + else + return currentColumn; + case TR_CURRENT_TILE_WIDTH: + return currentTileWidth; + case TR_CURRENT_TILE_HEIGHT: + return currentTileHeight; + case TR_ROW_ORDER: + return rowOrder; + default: + throw new IllegalArgumentException("Invalid enumerant as argument"); + } + } + + /** + * Sets the order of row traversal + * + * @param order + * The row traversal order, must be + * eitherTR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP + */ + public void setRowOrder( int order ) + { + if (order == TR_TOP_TO_BOTTOM || order == TR_BOTTOM_TO_TOP) { + rowOrder = order; + } else { + throw new IllegalArgumentException("Must pass TR_TOP_TO_BOTTOM or TR_BOTTOM_TO_TOP"); + } + } + + /** + * Sets the context to use an orthographic projection. Must be + * called before rendering the first tile + * + * @param left + * As in glOrtho + * @param right + * As in glOrtho + * @param bottom + * As in glOrtho + * @param top + * As in glOrtho + * @param zNear + * As in glOrtho + * @param zFar + * As in glOrtho + */ + public void trOrtho( double left, double right, double bottom, double top, double zNear, + double zFar ) + { + this.perspective = false; + this.left = left; + this.right = right; + this.bottom = bottom; + this.top = top; + this.near = zNear; + this.far = zFar; + } + + /** + * Sets the perspective projection frustrum. Must be called before + * rendering the first tile + * + * @param left + * As in glFrustrum + * @param right + * As in glFrustrum + * @param bottom + * As in glFrustrum + * @param top + * As in glFrustrum + * @param zNear + * As in glFrustrum + * @param zFar + * As in glFrustrum + */ + public void trFrustum( double left, double right, double bottom, double top, double zNear, + double zFar ) + { + this.perspective = true; + this.left = left; + this.right = right; + this.bottom = bottom; + this.top = top; + this.near = zNear; + this.far = zFar; + } + + /** + * Convenient way to specify a perspective projection + * + * @param fovy + * As in gluPerspective + * @param aspect + * As in gluPerspective + * @param zNear + * As in gluPerspective + * @param zFar + * As in gluPerspective + */ + public void trPerspective( double fovy, double aspect, double zNear, double zFar ) + { + double xmin, xmax, ymin, ymax; + ymax = zNear * Math.tan( fovy * 3.14159265 / 360.0 ); + ymin = -ymax; + xmin = ymin * aspect; + xmax = ymax * aspect; + trFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); + } + + /** + * Begins rendering a tile. The projection matrix stack should be + * left alone after calling this + * + * @param gl + * The gl context + */ + public void beginTile( GL2 gl ) + { + if (currentTile <= 0) { + setup(); + /* + * Save user's viewport, will be restored after last tile + * rendered + */ + gl.glGetIntegerv( GL2.GL_VIEWPORT, viewportSave, 0 ); + } + + /* which tile (by row and column) we're about to render */ + if (rowOrder == TR_BOTTOM_TO_TOP) { + currentRow = currentTile / columns; + currentColumn = currentTile % columns; + } else { + currentRow = rows - ( currentTile / columns ) - 1; + currentColumn = currentTile % columns; + } + assert ( currentRow < rows ); + assert ( currentColumn < columns ); + + int border = tileBorder; + + int th, tw; + + /* Compute actual size of this tile with border */ + if (currentRow < rows - 1) { + th = tileSize.height; + } else { + th = imageSize.height - ( rows - 1 ) * ( tileSizeNB.height ) + 2 * border; + } + + if (currentColumn < columns - 1) { + tw = tileSize.width; + } else { + tw = imageSize.width - ( columns - 1 ) * ( tileSizeNB.width ) + 2 * border; + } + + /* Save tile size, with border */ + currentTileWidth = tw; + currentTileHeight = th; + + gl.glViewport( 0, 0, tw, th ); + + /* save current matrix mode */ + int[] matrixMode = new int[ 1 ]; + gl.glGetIntegerv( GL2.GL_MATRIX_MODE, matrixMode, 0 ); + gl.glMatrixMode( GL2.GL_PROJECTION ); + gl.glLoadIdentity(); + + /* compute projection parameters */ + double l = + left + ( right - left ) * ( currentColumn * tileSizeNB.width - border ) + / imageSize.width; + double r = l + ( right - left ) * tw / imageSize.width; + double b = + bottom + ( top - bottom ) * ( currentRow * tileSizeNB.height - border ) + / imageSize.height; + double t = b + ( top - bottom ) * th / imageSize.height; + + if( perspective ) { + gl.glFrustum( l, r, b, t, near, far ); + } else { + gl.glOrtho( l, r, b, t, near, far ); + } + + /* restore user's matrix mode */ + gl.glMatrixMode( matrixMode[ 0 ] ); + } + + /** + * Must be called after rendering the scene + * + * @param gl + * the gl context + * @return true if there are more tiles to be rendered, false if + * the final image is complete + */ + public boolean endTile( GL2 gl ) + { + int[] prevRowLength = new int[ 1 ], prevSkipRows = new int[ 1 ], prevSkipPixels = new int[ 1 ], prevAlignment = + new int[ 1 ]; + + assert ( currentTile >= 0 ); + + // be sure OpenGL rendering is finished + gl.glFlush(); + + // save current glPixelStore values + gl.glGetIntegerv( GL2.GL_PACK_ROW_LENGTH, prevRowLength, 0 ); + gl.glGetIntegerv( GL2.GL_PACK_SKIP_ROWS, prevSkipRows, 0 ); + gl.glGetIntegerv( GL2.GL_PACK_SKIP_PIXELS, prevSkipPixels, 0 ); + gl.glGetIntegerv( GL2.GL_PACK_ALIGNMENT, prevAlignment, 0 ); + + if( tileBuffer != null ) { + int srcX = tileBorder; + int srcY = tileBorder; + int srcWidth = tileSizeNB.width; + int srcHeight = tileSizeNB.height; + gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, tileFormat, tileType, tileBuffer ); + } + + if( imageBuffer != null ) { + int srcX = tileBorder; + int srcY = tileBorder; + int srcWidth = currentTileWidth - 2 * tileBorder; + int srcHeight = currentTileHeight - 2 * tileBorder; + int destX = tileSizeNB.width * currentColumn; + int destY = tileSizeNB.height * currentRow; + + /* setup pixel store for glReadPixels */ + gl.glPixelStorei( GL2.GL_PACK_ROW_LENGTH, imageSize.width ); + gl.glPixelStorei( GL2.GL_PACK_SKIP_ROWS, destY ); + gl.glPixelStorei( GL2.GL_PACK_SKIP_PIXELS, destX ); + gl.glPixelStorei( GL2.GL_PACK_ALIGNMENT, 1 ); + + /* read the tile into the final image */ + gl.glReadPixels( srcX, srcY, srcWidth, srcHeight, imageFormat, imageType, imageBuffer ); + } + + /* restore previous glPixelStore values */ + gl.glPixelStorei( GL2.GL_PACK_ROW_LENGTH, prevRowLength[ 0 ] ); + gl.glPixelStorei( GL2.GL_PACK_SKIP_ROWS, prevSkipRows[ 0 ] ); + gl.glPixelStorei( GL2.GL_PACK_SKIP_PIXELS, prevSkipPixels[ 0 ] ); + gl.glPixelStorei( GL2.GL_PACK_ALIGNMENT, prevAlignment[ 0 ] ); + + /* increment tile counter, return 1 if more tiles left to render */ + currentTile++; + if( currentTile >= rows * columns ) { + /* restore user's viewport */ + gl.glViewport( viewportSave[ 0 ], viewportSave[ 1 ], viewportSave[ 2 ], viewportSave[ 3 ] ); + currentTile = -1; /* all done */ + return false; + } else { + return true; + } + } + + /** + * Tile rendering causes problems with using glRasterPos3f, so you + * should use this replacement instead + * + * @param x + * As in glRasterPos3f + * @param y + * As in glRasterPos3f + * @param z + * As in glRasterPos3f + * @param gl + * The gl context + * @param glu + * A GLUgl2 object + */ + public void trRasterPos3f( float x, float y, float z, GL2 gl, GLUgl2 glu ) + { + if (currentTile < 0) { + /* not doing tile rendering right now. Let OpenGL do this. */ + gl.glRasterPos3f( x, y, z ); + } else { + double[] modelview = new double[ 16 ], proj = new double[ 16 ]; + int[] viewport = new int[ 4 ]; + double[] win = new double[3]; + + /* Get modelview, projection and viewport */ + gl.glGetDoublev( GL2.GL_MODELVIEW_MATRIX, modelview, 0 ); + gl.glGetDoublev( GL2.GL_PROJECTION_MATRIX, proj, 0 ); + viewport[ 0 ] = 0; + viewport[ 1 ] = 0; + viewport[ 2 ] = currentTileWidth; + viewport[ 3 ] = currentTileHeight; + + /* Project object coord to window coordinate */ + if( glu.gluProject( x, y, z, modelview, 0, proj, 0, viewport, 0, win, 0 ) ) { + + /* set raster pos to window coord (0,0) */ + gl.glMatrixMode( GL2.GL_MODELVIEW ); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glMatrixMode( GL2.GL_PROJECTION ); + gl.glPushMatrix(); + gl.glLoadIdentity(); + gl.glOrtho( 0.0, currentTileWidth, 0.0, currentTileHeight, 0.0, 1.0 ); + gl.glRasterPos3d( 0.0, 0.0, -win[ 2 ] ); + + /* + * Now use empty bitmap to adjust raster position to + * (winX,winY) + */ + { + byte[] bitmap = { 0 }; + gl.glBitmap( 1, 1, 0.0f, 0.0f, ( float ) win[ 0 ], ( float ) win[ 1 ], bitmap , 0 ); + } + + /* restore original matrices */ + gl.glPopMatrix(); /* proj */ + gl.glMatrixMode( GL2.GL_MODELVIEW ); + gl.glPopMatrix(); + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/GLSLArrayHandler.java new file mode 100644 index 000000000..1119aa5ab --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/GLSLArrayHandler.java @@ -0,0 +1,60 @@ + +package com.jogamp.opengl.util.glsl; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.glsl.ShaderState; +import java.nio.*; + +public class GLSLArrayHandler implements GLArrayHandler { + private GLArrayDataEditable ad; + + public GLSLArrayHandler(GLArrayDataEditable ad) { + this.ad = ad; + } + + protected final void passVertexAttribPointer(GL2ES2 gl, ShaderState st) { + st.glVertexAttribPointer(gl, ad); + } + + public void enableBuffer(GL gl, boolean enable) { + if(!gl.isGL2ES2()) { + throw new GLException("GLSLArrayHandler expects a GL2ES2 implementation"); + } + GL2ES2 glsl = gl.getGL2ES2(); + ShaderState st = ShaderState.getCurrent(); + if(null==st) { + throw new GLException("No ShaderState current"); + } + + if(enable) { + st.glEnableVertexAttribArray(glsl, ad.getName()); + + Buffer buffer = ad.getBuffer(); + + if(ad.isVBO()) { + // always bind and refresh the VBO mgr, + // in case more than one gl*Pointer objects are in use + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, ad.getVBOName()); + if(!ad.isBufferWritten()) { + if(null!=buffer) { + glsl.glBufferData(GL.GL_ARRAY_BUFFER, buffer.limit() * ad.getComponentSize(), buffer, ad.getBufferUsage()); + } + ad.setBufferWritten(true); + } + passVertexAttribPointer(glsl, st); + } else if(null!=buffer) { + passVertexAttribPointer(glsl, st); + ad.setBufferWritten(true); + } + } else { + if(ad.isVBO()) { + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + st.glDisableVertexAttribArray(glsl, ad.getName()); + } + } + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java new file mode 100644 index 000000000..d0e7ea29d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderCode.java @@ -0,0 +1,348 @@ + +package com.jogamp.opengl.util.glsl; + +import com.jogamp.common.nio.Buffers; +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.impl.Debug; + +import java.util.*; +import java.nio.*; +import java.io.*; +import java.net.*; +import java.security.*; + +public class ShaderCode { + public static final boolean DEBUG = Debug.debug("GLSLCode"); + public static final boolean DEBUG_CODE = Debug.isPropertyDefined("jogl.debug.GLSLCode", true, AccessController.getContext()); + + public static final String SUFFIX_VERTEX_SOURCE = "vp" ; + public static final String SUFFIX_VERTEX_BINARY = "bvp" ; + public static final String SUFFIX_FRAGMENT_SOURCE = "fp" ; + public static final String SUFFIX_FRAGMENT_BINARY = "bfp" ; + + public static final String SUB_PATH_NVIDIA = "nvidia" ; + + public ShaderCode(int type, int number, String[][] source) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + case GL2ES2.GL_FRAGMENT_SHADER: + break; + default: + throw new GLException("Unknown shader type: "+type); + } + shaderSource = source; + shaderBinaryFormat = -1; + shaderBinary = null; + shaderType = type; + shader = Buffers.newDirectIntBuffer(number); + id = getNextID(); + + if(DEBUG_CODE) { + System.out.println("Created: "+toString()); + dumpShaderSource(System.out); + } + } + + public ShaderCode(int type, int number, int binFormat, Buffer binary) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + case GL2ES2.GL_FRAGMENT_SHADER: + break; + default: + throw new GLException("Unknown shader type: "+type); + } + shaderSource = null; + shaderBinaryFormat = binFormat; + shaderBinary = binary; + shaderType = type; + shader = Buffers.newDirectIntBuffer(number); + id = getNextID(); + } + + public static ShaderCode create(GL2ES2 gl, int type, int number, Class context, String[] sourceFiles) { + if(!ShaderUtil.isShaderCompilerAvailable(gl)) return null; + + String[][] shaderSources = null; + if(null!=sourceFiles) { + shaderSources = new String[sourceFiles.length][1]; + for(int i=0; null!=shaderSources && i<sourceFiles.length; i++) { + shaderSources[i][0] = readShaderSource(context, sourceFiles[i]); + if(null == shaderSources[i][0]) { + shaderSources = null; + } + } + } + if(null==shaderSources) { + return null; + } + return new ShaderCode(type, number, shaderSources); + } + + public static ShaderCode create(int type, int number, Class context, int binFormat, String binaryFile) { + ByteBuffer shaderBinary = null; + if(null!=binaryFile && 0<=binFormat) { + shaderBinary = readShaderBinary(context, binaryFile); + if(null == shaderBinary) { + binFormat = -1; + } + } + if(null==shaderBinary) { + return null; + } + return new ShaderCode(type, number, binFormat, shaderBinary); + } + + public static String getFileSuffix(boolean binary, int type) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + return binary?SUFFIX_VERTEX_BINARY:SUFFIX_VERTEX_SOURCE; + case GL2ES2.GL_FRAGMENT_SHADER: + return binary?SUFFIX_FRAGMENT_BINARY:SUFFIX_FRAGMENT_SOURCE; + default: + throw new GLException("illegal shader type: "+type); + } + } + + public static String getBinarySubPath(int binFormat) { + switch (binFormat) { + case GLES2.GL_NVIDIA_PLATFORM_BINARY_NV: + return SUB_PATH_NVIDIA; + default: + throw new GLException("unsupported binary format: "+binFormat); + } + } + + public static ShaderCode create(GL2ES2 gl, int type, int number, Class context, + String srcRoot, String binRoot, String basename) { + ShaderCode res = null; + String srcFileName = null; + String binFileName = null; + + if(ShaderUtil.isShaderCompilerAvailable(gl)) { + String srcPath[] = new String[1]; + srcFileName = srcRoot + '/' + basename + "." + getFileSuffix(false, type); + srcPath[0] = srcFileName; + res = create(gl, type, number, context, srcPath); + if(null!=res) { + return res; + } + } + Set binFmts = ShaderUtil.getShaderBinaryFormats(gl); + for(Iterator iter=binFmts.iterator(); null==res && iter.hasNext(); ) { + int bFmt = ((Integer)(iter.next())).intValue(); + String bFmtPath = getBinarySubPath(bFmt); + if(null==bFmtPath) continue; + binFileName = binRoot + '/' + bFmtPath + '/' + basename + "." + getFileSuffix(true, type); + res = create(type, number, context, bFmt, binFileName); + } + + if(null==res) { + throw new GLException("No shader code found (source nor binary) for src: "+srcFileName+ + ", bin: "+binFileName); + } + + return res; + } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + public int shaderType() { return shaderType; } + public String shaderTypeStr() { return shaderTypeStr(shaderType); } + + public static String shaderTypeStr(int type) { + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + return "VERTEX_SHADER"; + case GL2ES2.GL_FRAGMENT_SHADER: + return "FRAGMENT_SHADER"; + } + return "UNKNOWN_SHADER"; + } + + public int shaderBinaryFormat() { return shaderBinaryFormat; } + public Buffer shaderBinary() { return shaderBinary; } + public String[][] shaderSource() { return shaderSource; } + + public boolean isValid() { return valid; } + + public IntBuffer shader() { return shader; } + + public boolean compile(GL2ES2 gl) { + return compile(gl, null); + } + public boolean compile(GL2ES2 gl, PrintStream verboseOut) { + if(isValid()) return true; + + // Create & Compile the vertex/fragment shader objects + if(null!=shaderSource) { + valid=ShaderUtil.createAndCompileShader(gl, shader, shaderType, + shaderSource, verboseOut); + } else if(null!=shaderBinary) { + valid=ShaderUtil.createAndLoadShader(gl, shader, shaderType, + shaderBinaryFormat, shaderBinary, verboseOut); + } else { + throw new GLException("no code (source or binary)"); + } + return valid; + } + + public void destroy(GL2ES2 gl) { + if(isValid()) { + if(null!=gl) { + ShaderUtil.deleteShader(gl, shader()); + } + valid=false; + } + if(null!=shaderBinary) { + shaderBinary.clear(); + shaderBinary=null; + } + shaderSource=null; + shaderBinaryFormat=-1; + shaderType=-1; + id=null; + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer("ShaderCode [id="+id+", type="+shaderTypeStr()+", valid="+valid+", shader: "); + for(int i=0; i<shader.remaining(); i++) { + buf.append(" "+shader.get(i)); + } + if(null!=shaderSource) { + buf.append(", source]"); + } else if(null!=shaderBinary) { + buf.append(", binary "+shaderBinary+"]"); + } + return buf.toString(); + } + + public void dumpShaderSource(PrintStream out) { + if(null==shaderSource) { + out.println("<no shader source>"); + return; + } + int sourceNum = (null!=shaderSource)?shaderSource.length:0; + int shaderNum = (null!=shader)?shader.capacity():0; + for(int i=0; i<shaderNum; i++) { + out.println(""); + out.println("Shader #"+i+"/"+shaderNum+" name "+shader.get(i)); + out.println("--------------------------------------------------------------"); + if(i>=sourceNum) { + out.println("<no shader source>"); + } else { + String[] src = shaderSource[i]; + for(int j=0; j<src.length; j++) { + out.println("Segment "+j+"/"+src.length+" :"); + out.println(src[j]); + out.println(""); + } + } + out.println("--------------------------------------------------------------"); + } + } + + public static void readShaderSource(ClassLoader context, String path, URL url, StringBuffer result) { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream())); + String line = null; + while ((line = reader.readLine()) != null) { + if (line.startsWith("#include ")) { + String includeFile = line.substring(9).trim(); + // Try relative path first + String next = Locator.getRelativeOf(path, includeFile); + URL nextURL = Locator.getResource(next, context); + if (nextURL == null) { + // Try absolute path + next = includeFile; + nextURL = Locator.getResource(next, context); + } + if (nextURL == null) { + // Fail + throw new FileNotFoundException("Can't find include file " + includeFile); + } + readShaderSource(context, next, nextURL, result); + } else { + result.append(line + "\n"); + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String readShaderSource(Class context, String path) { + ClassLoader contextCL = (null!=context)?context.getClassLoader():null; + URL url = Locator.getResource(path, contextCL); + if (url == null && null!=context) { + // Try again by scoping the path within the class's package + String className = context.getName().replace('.', '/'); + int lastSlash = className.lastIndexOf('/'); + if (lastSlash >= 0) { + String tmpPath = className.substring(0, lastSlash + 1) + path; + url = Locator.getResource(tmpPath, contextCL); + if (url != null) { + path = tmpPath; + } + } + } + if (url == null) { + return null; + } + StringBuffer result = new StringBuffer(); + readShaderSource(contextCL, path, url, result); + return result.toString(); + } + + public static ByteBuffer readShaderBinary(Class context, String path) { + try { + URL url = Locator.getResource(context, path); + if (url == null) { + return null; + } + return StreamUtil.readAll2Buffer(new BufferedInputStream(url.openStream())); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + protected String[][] shaderSource = null; + protected Buffer shaderBinary = null; + protected int shaderBinaryFormat = -1; + protected IntBuffer shader = null; + protected int shaderType = -1; + protected Integer id = null; + + protected boolean valid=false; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java new file mode 100644 index 000000000..430ed08ce --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderProgram.java @@ -0,0 +1,215 @@ + +package com.jogamp.opengl.util.glsl; + +import javax.media.opengl.*; + +import java.util.HashMap; +import java.util.Iterator; +import java.io.PrintStream; + +public class ShaderProgram { + public ShaderProgram() { + id = getNextID(); + } + + public boolean linked() { + return programLinked; + } + + public boolean inUse() { + return programInUse; + } + + public int program() { return shaderProgram; } + + /** + * returns the uniq shader id as an integer + * @see #key() + */ + public int id() { return id.intValue(); } + + /** + * returns the uniq shader id as an Integer + * + * @see #id() + */ + public Integer key() { return id; } + + /** + * Detaches all shader codes and deletes the program. + * Destroys the shader codes as well. + * Calls release(gl, true) + * + * @see #release(GL2ES2, boolean) + */ + public synchronized void destroy(GL2ES2 gl) { + release(gl, true); + } + + /** + * Detaches all shader codes and deletes the program. + * Calls release(gl, false) + * + * @see #release(GL2ES2, boolean) + */ + public synchronized void release(GL2ES2 gl) { + release(gl, false); + } + + /** + * Detaches all shader codes and deletes the program. + * If releaseShaderToo is true, destroys the shader codes as well. + */ + public synchronized void release(GL2ES2 gl, boolean releaseShaderToo) { + glUseProgram(gl, false); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + ShaderUtil.detachShader(gl, shaderProgram, shaderCode.shader()); + if(releaseShaderToo) { + shaderCode.destroy(gl); + } + } + shaderMap.clear(); + gl.glDeleteProgram(shaderProgram); + shaderProgram=-1; + } + + // + // ShaderCode handling + // + + /** + * Adds a new shader to a this non running program. + * + * @return false if the program is in use, or the shader already exist, + * otherwise true. + */ + public synchronized boolean add(ShaderCode shaderCode) { + if(shaderMap.containsKey(shaderCode.key())) return false; + shaderMap.put(shaderCode.key(), shaderCode); + return true; + } + + public synchronized ShaderCode getShader(int id) { + return (ShaderCode) shaderMap.get(new Integer(id)); + } + + // + // Program handling + // + + /** + * Replace a shader in a 'running' program. + * Refetches all previously bin/get attribute names + * and resets all attribute data as well + * + * @param gl + * @param oldShaderID the to be replace Shader + * @param newShader the new ShaderCode + * @param verboseOut the optional verbose outputstream + * @throws GLException is the program is not linked + * + * @see ShaderState#glEnableVertexAttribArray + * @see ShaderState#glDisableVertexAttribArray + * @see ShaderState#glVertexAttribPointer + * @see ShaderState#getVertexAttribPointer + * @see ShaderState#glReleaseAllVertexAttributes + * @see ShaderState#glResetAllVertexAttributes + * @see ShaderState#glResetAllVertexAttributes + * @see ShaderState#glResetAllVertexAttributes + */ + public synchronized boolean glReplaceShader(GL2ES2 gl, int oldShaderID, ShaderCode newShader, PrintStream verboseOut) { + if(!programLinked) throw new GLException("Program is not linked"); + boolean shaderWasInUse = programInUse; + glUseProgram(gl, false); + if(!newShader.compile(gl, verboseOut)) { + return false; + } + if(oldShaderID>=0) { + ShaderCode oldShader = (ShaderCode) shaderMap.remove(new Integer(oldShaderID)); + if(null!=oldShader) { + ShaderUtil.detachShader(gl, shaderProgram, oldShader.shader()); + } + } + add(newShader); + + ShaderUtil.attachShader(gl, shaderProgram, newShader.shader()); + gl.glLinkProgram(shaderProgram); + if ( ! ShaderUtil.isProgramValid(gl, shaderProgram, System.err) ) { + return false; + } + + if(shaderWasInUse) { + glUseProgram(gl, true); + } + return true; + } + + public synchronized boolean link(GL2ES2 gl, PrintStream verboseOut) { + if(programLinked) throw new GLException("Program is already linked"); + + if(0>shaderProgram) { + shaderProgram = gl.glCreateProgram(); + } + + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + ShaderCode shaderCode = (ShaderCode) iter.next(); + if(!shaderCode.compile(gl, verboseOut)) { + return false; + } + ShaderUtil.attachShader(gl, shaderProgram, shaderCode.shader()); + } + + // Link the program + gl.glLinkProgram(shaderProgram); + + programLinked = ShaderUtil.isProgramValid(gl, shaderProgram, System.err); + + return programLinked; + } + + public boolean equals(Object obj) { + if(this==obj) return true; + if(obj instanceof ShaderCode) { + return id()==((ShaderCode)obj).id(); + } + return false; + } + public int hashCode() { + return id.intValue(); + } + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderProgram[id="+id); + buf.append(", linked="+programLinked+", inUse="+programInUse+", program: "+shaderProgram+", ["); + for(Iterator iter=shaderMap.values().iterator(); iter.hasNext(); ) { + buf.append((ShaderCode) iter.next()); + buf.append(" "); + } + buf.append("]"); + return buf.toString(); + } + + protected synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(!programLinked) throw new GLException("Program is not linked"); + if(programInUse==on) return; + gl.glUseProgram(on?shaderProgram:0); + programInUse = on; + + //Throwable tX = new Throwable("Info: ShaderProgram.glUseProgram: "+on); + //tX.printStackTrace(); + + } + + protected boolean programLinked = false; + protected boolean programInUse = false; + protected int shaderProgram=-1; + protected HashMap shaderMap = new HashMap(); + protected Integer id = null; + + private static synchronized Integer getNextID() { + return new Integer(nextID++); + } + protected static int nextID = 1; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java new file mode 100644 index 000000000..86f9251b7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -0,0 +1,649 @@ + +package com.jogamp.opengl.util.glsl; + +import javax.media.opengl.*; +import com.jogamp.opengl.impl.Debug; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.security.*; + +public class ShaderState { + public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true, AccessController.getContext()); + + public ShaderState() { + } + + public boolean verbose() { return verbose; } + + public void setVerbose(boolean v) { verbose=v; } + + /** + * Fetches the current shader state from the thread local storage (TLS) + * + * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrent() + */ + public static synchronized ShaderState getCurrent() { + GLContext current = GLContext.getCurrent(); + if(null==current) { + throw new GLException("No context is current on this thread"); + } + return (ShaderState) current.getAttachedObject(ShaderState.class.getName()); + } + + /** + * Turns the shader program on or off.<br> + * Puts this ShaderState to to the thread local storage (TLS), + * if <code>on</code> is <code>true</code>. + * + * @see com.jogamp.opengl.util.glsl.ShaderState#glUseProgram(GL2ES2, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrent() + */ + public synchronized void glUseProgram(GL2ES2 gl, boolean on) { + if(on) { + if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, true); + } else { + throw new GLException("No program is attached"); + } + // update the current ShaderState to the TLS .. + gl.getContext().putAttachedObject(ShaderState.class.getName(), this); + } else if(null!=shaderProgram) { + shaderProgram.glUseProgram(gl, false); + } + } + + public boolean linked() { + return (null!=shaderProgram)?shaderProgram.linked():false; + } + + public boolean inUse() { + return (null!=shaderProgram)?shaderProgram.inUse():false; + } + + /** + * Attach or switch a shader program + * + * Attaching a shader program the first time, + * as well as switching to another program on the fly, + * while managing all attribute and uniform data. + */ + public synchronized void attachShaderProgram(GL2ES2 gl, ShaderProgram prog) { + boolean prgInUse = false; // earmarked state + + if(DEBUG) { + int curId = (null!=shaderProgram)?shaderProgram.id():-1; + int newId = (null!=prog)?prog.id():-1; + System.err.println("Info: attachShaderProgram: "+curId+" -> "+newId+"\n\t"+shaderProgram+"\n\t"+prog); + if(verbose) { + Throwable tX = new Throwable("Info: attachShaderProgram: Trace"); + tX.printStackTrace(); + } + } + if(null!=shaderProgram) { + if(shaderProgram.equals(prog)) { + // nothing to do .. + if(DEBUG) { + System.err.println("Info: attachShaderProgram: NOP: equal id: "+shaderProgram.id()); + } + return; + } + prgInUse = shaderProgram.inUse(); + shaderProgram.glUseProgram(gl, false); + } + + // register new one + shaderProgram = prog; + + if(null!=shaderProgram) { + // reinstall all data .. + shaderProgram.glUseProgram(gl, true); + glResetAllVertexAttributes(gl); + glResetAllUniforms(gl); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + if(DEBUG) { + System.err.println("Info: attachShaderProgram: END"); + } + } + + public ShaderProgram shaderProgram() { return shaderProgram; } + + /** + * Calls release(gl, true, true) + * + * @see #glReleaseAllVertexAttributes + * @see #glReleaseAllUniforms + * @see #release(GL2ES2, boolean, boolean) + */ + public synchronized void destroy(GL2ES2 gl) { + release(gl, true, true); + } + + /** + * Calls release(gl, false, false) + * + * @see #glReleaseAllVertexAttributes + * @see #glReleaseAllUniforms + * @see #release(GL2ES2, boolean, boolean) + */ + public synchronized void releaseAllData(GL2ES2 gl) { + release(gl, false, false); + } + + /** + * @see #glReleaseAllVertexAttributes + * @see #glReleaseAllUniforms + * @see ShaderProgram#release(GL2ES2, boolean) + */ + public synchronized void release(GL2ES2 gl, boolean releaseProgramToo, boolean releaseShaderToo) { + boolean prgInUse = false; + if(null!=shaderProgram) { + prgInUse = shaderProgram.inUse(); + if(!prgInUse) { + shaderProgram.glUseProgram(gl, true); + } + } + glReleaseAllVertexAttributes(gl); + glReleaseAllUniforms(gl); + if(null!=shaderProgram) { + if(releaseProgramToo) { + shaderProgram.release(gl, releaseShaderToo); + } else if(!prgInUse) { + shaderProgram.glUseProgram(gl, false); + } + } + } + + // + // Shader attribute handling + // + + /** + * Binds an attribute to the shader. + * This must be done before the program is linked ! + * n name - 1 idx, where name is a uniq key + * + * @throws GLException is the program is already linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see ShaderProgram#glReplaceShader + */ + public void glBindAttribLocation(GL2ES2 gl, int index, String name) { + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + Integer idx = new Integer(index); + if(!attribMap2Idx.containsKey(name)) { + attribMap2Idx.put(name, idx); + gl.glBindAttribLocation(shaderProgram.program(), index, name); + } + } + + /** + * Gets the index of a shader attribute. + * This must be done after the program is linked ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + * @throws GLException is the program is not linked + * + * @see #glBindAttribLocation + * @see javax.media.opengl.GL2ES2#glBindAttribLocation + * @see #glGetAttribLocation + * @see javax.media.opengl.GL2ES2#glGetAttribLocation + * @see #getAttribLocation + * @see ShaderProgram#glReplaceShader + */ + public int glGetAttribLocation(GL2ES2 gl, String name) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + int index = getAttribLocation(name); + if(0>index) { + index = gl.glGetAttribLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + attribMap2Idx.put(name, idx); + if(DEBUG) { + System.err.println("Info: glGetAttribLocation: "+name+", loc: "+index); + } + } else if(verbose) { + Throwable tX = new Throwable("Info: glGetAttribLocation failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getAttribLocation(String name) { + Integer idx = (Integer) attribMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + + // + // Enabled Vertex Arrays and its data + // + + /** + * Enable a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @return false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public boolean glEnableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.add(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glEnableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glEnableVertexAttribArray: "+name+", loc: "+index); + } + gl.glEnableVertexAttribArray(index); + return true; + } + + public boolean isVertexAttribArrayEnabled(String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + return enabledVertexAttribArraySet.contains(name); + } + + /** + * Disables a vertex attribute array + * + * Even if the attribute is not found in the current shader, + * it is removed from this state. + * + * @return false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public boolean glDisableVertexAttribArray(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + enabledVertexAttribArraySet.remove(name); + int index = glGetAttribLocation(gl, name); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glDisableVertexAttribArray failed, no index for: "+name); + tX.printStackTrace(); + } + return false; + } + if(DEBUG) { + System.err.println("Info: glDisableVertexAttribArray: "+name); + } + gl.glDisableVertexAttribArray(index); + return true; + } + + /** + * Set the vertex attribute data. + * Enable the attribute, if it is not enabled yet. + * + * Even if the attribute is not found in the current shader, + * it is stored in this state. + * + * @param data the GLArrayData's name must match the attributes one, + * it's index will be set with the attribute's location, + * if found. + * + * @return false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public boolean glVertexAttribPointer(GL2ES2 gl, GLArrayData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + if(!enabledVertexAttribArraySet.contains(data.getName())) { + if(!glEnableVertexAttribArray(gl, data.getName())) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer: couldn't enable: "+data); + tX.printStackTrace(); + } + } + } + int index = getAttribLocation(data.getName()); + if(0>index) { + if(verbose) { + Throwable tX = new Throwable("Info: glVertexAttribPointer failed, no index for: "+data); + tX.printStackTrace(); + } + } + data.setLocation(index); + vertexAttribMap2Data.put(data.getName(), data); + if(0<=index) { + // only pass the data, if the attribute exists in the current shader + if(DEBUG) { + System.err.println("Info: glVertexAttribPointer: "+data); + } + gl.glVertexAttribPointer(data); + return true; + } + return false; + } + + /** + * Get the vertex attribute data, previously set. + * + * @return the GLArrayData object, null if not previously set. + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public GLArrayData getVertexAttribPointer(String name) { + return (GLArrayData) vertexAttribMap2Data.get(name); + } + + /** + * Releases all mapped vertex attribute data, + * disables all enabled attributes and loses all indices + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public void glReleaseAllVertexAttributes(GL2ES2 gl) { + if(null!=shaderProgram) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + for(Iterator iter = vertexAttribMap2Data.keySet().iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: mapped vertex attribute couldn't be disabled"); + } + } + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + if(!glDisableVertexAttribArray(gl, (String) iter.next())) { + throw new GLException("Internal Error: prev enabled vertex attribute couldn't be disabled"); + } + } + } + vertexAttribMap2Data.clear(); + enabledVertexAttribArraySet.clear(); + attribMap2Idx.clear(); + } + + /** + * Disables all vertex attribute arrays. + * + * Their enabled stated will be removed from this state only + * if 'removeFromState' is true. + * + * This method purpose is more for debugging. + * + * @throws GLException is the program is not in use but the shaderProgram is set + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public void glDisableAllVertexAttributeArrays(GL2ES2 gl, boolean removeFromState) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + String name = (String) iter.next(); + if(removeFromState) { + enabledVertexAttribArraySet.remove(name); + } + int index = glGetAttribLocation(gl, name); + if(0<=index) { + gl.glDisableVertexAttribArray(index); + } + } + } + + /** + * Reset all previously enabled mapped vertex attribute data, + * incl enabling them + * + * @throws GLException is the program is not in use + * + * @see #glEnableVertexAttribArray + * @see #glDisableVertexAttribArray + * @see #glVertexAttribPointer + * @see #getVertexAttribPointer + * @see #glReleaseAllVertexAttributes + * @see #glResetAllVertexAttributes + * @see ShaderProgram#glReplaceShader + */ + public void glResetAllVertexAttributes(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + attribMap2Idx.clear(); + + /** + * + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + glEnableVertexAttribArray(gl, (String) iter.next()); + } + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + GLArrayData data = (GLArrayData) iter.next(); + + ... + } */ + + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + // get new location .. + String name = (String) iter.next(); + int loc = glGetAttribLocation(gl, name); + + // get & update data .. + GLArrayData data = getVertexAttribPointer(name); + data.setLocation(loc); + vertexAttribMap2Data.put(name, data); + + if(0>loc) { + // not used in shader + continue; + } + + // enable attrib, VBO and pass location/data + gl.glEnableVertexAttribArray(loc); + + if( data.isVBO() ) { + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, data.getVBOName()); + } + + gl.glVertexAttribPointer(data); + } + } + + // + // Shader Uniform handling + // + + /** + * Gets the index of a shader uniform. + * This must be done when the program is in use ! + * + * @return -1 if there is no such attribute available, + * otherwise >= 0 + + * @throws GLException is the program is not linked + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see ShaderProgram#glReplaceShader + */ + protected int glGetUniformLocation(GL2ES2 gl, String name) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int index = getUniformLocation(name); + if(0>index) { + index = gl.glGetUniformLocation(shaderProgram.program(), name); + if(0<=index) { + Integer idx = new Integer(index); + uniformMap2Idx.put(name, idx); + } else if(verbose) { + Throwable tX = new Throwable("Info: glUniform failed, no location for: "+name+", index: "+index); + tX.printStackTrace(); + } + } + return index; + } + + protected int getUniformLocation(String name) { + Integer idx = (Integer) uniformMap2Idx.get(name); + return (null!=idx)?idx.intValue():-1; + } + + /** + * Set the uniform data. + * + * Even if the uniform is not found in the current shader, + * it is stored in this state. + * + * @param data the GLUniforms's name must match the uniform one, + * it's index will be set with the uniforms's location, + * if found. + * + * + * @return false, if the name is not found, otherwise true + * + * @throws GLException if the program is not in use + * + * @see #glGetUniformLocation + * @see javax.media.opengl.GL2ES2#glGetUniformLocation + * @see #getUniformLocation + * @see ShaderProgram#glReplaceShader + */ + public boolean glUniform(GL2ES2 gl, GLUniformData data) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + int location = glGetUniformLocation(gl, data.getName()); + data.setLocation(location); + uniformMap2Data.put(data.getName(), data); + if(0<=location) { + // only pass the data, if the uniform exists in the current shader + if(DEBUG) { + System.err.println("Info: glUniform: "+data); + } + gl.glUniform(data); + } + return true; + } + + /** + * Get the uniform data, previously set. + * + * @return the GLUniformData object, null if not previously set. + */ + public GLUniformData getUniform(String name) { + return (GLUniformData) uniformMap2Data.get(name); + } + + /** + * Releases all mapped uniform data + * and loses all indices + * + * @throws GLException is the program is not in use + */ + public void glReleaseAllUniforms(GL2ES2 gl) { + uniformMap2Data.clear(); + uniformMap2Idx.clear(); + } + + /** + * Reset all previously mapped uniform data + * + * @throws GLException is the program is not in use + */ + public void glResetAllUniforms(GL2ES2 gl) { + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + uniformMap2Idx.clear(); + for(Iterator iter = uniformMap2Data.values().iterator(); iter.hasNext(); ) { + glUniform(gl, (GLUniformData) iter.next()); + } + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("ShaderState["); + buf.append(shaderProgram.toString()); + buf.append(",EnabledStates: ["); + for(Iterator iter = enabledVertexAttribArraySet.iterator(); iter.hasNext(); ) { + buf.append("\n "); + buf.append((String)iter.next()); + } + buf.append("], ["); + for(Iterator iter = vertexAttribMap2Data.values().iterator(); iter.hasNext(); ) { + GLArrayData data = (GLArrayData) iter.next(); + if(data.getLocation()>=0) { + buf.append("\n "); + buf.append(data); + } + } + buf.append("], ["); + for(Iterator iter=uniformMap2Data.values().iterator(); iter.hasNext(); ) { + GLUniformData data = (GLUniformData) iter.next(); + if(data.getLocation()>=0) { + buf.append("\n "); + buf.append(data); + } + } + buf.append("]"); + return buf.toString(); + } + + protected boolean verbose = false; + protected ShaderProgram shaderProgram=null; + protected HashMap attribMap2Idx = new HashMap(); + protected HashSet enabledVertexAttribArraySet = new HashSet(); + protected HashMap vertexAttribMap2Data = new HashMap(); + protected HashMap uniformMap2Idx = new HashMap(); + protected HashMap uniformMap2Data = new HashMap(); + +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java new file mode 100644 index 000000000..c7e845953 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderUtil.java @@ -0,0 +1,476 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + */ + +package com.jogamp.opengl.util.glsl; + +import java.io.PrintStream; +import java.nio.*; +import java.util.*; + +import javax.media.opengl.*; + +public class ShaderUtil { + static abstract class Impl { + public abstract String getShaderInfoLog(GL gl, int shaderObj); + public abstract String getProgramInfoLog(GL gl, int programObj); + public abstract boolean isShaderStatusValid(GL gl, int shaderObj, int name); + public abstract boolean isShaderStatusValid(GL gl, int shaderObj, int name, PrintStream verboseOut); + public abstract boolean isShaderStatusValid(GL gl, IntBuffer shaders, int name); + public abstract boolean isShaderStatusValid(GL gl, IntBuffer shaders, int name, PrintStream verboseOut); + public abstract boolean isProgramStatusValid(GL gl, int programObj, int name); + public abstract boolean isProgramValid(GL gl, int programObj); + public abstract boolean isProgramValid(GL gl, int programObj, PrintStream verboseOut); + public abstract void createShader(GL gl, int type, IntBuffer shaders); + public abstract Set getShaderBinaryFormats(GL gl); + public abstract boolean isShaderCompilerAvailable(GL gl); + public abstract void shaderSource(GL gl, int shader, java.lang.String[] source); + public abstract void shaderSource(GL gl, IntBuffer shaders, java.lang.String[][] sources); + public abstract void shaderBinary(GL gl, IntBuffer shaders, int binFormat, java.nio.Buffer bin); + public abstract void compileShader(GL gl, IntBuffer shaders); + public abstract void attachShader(GL gl, int program, IntBuffer shaders); + public abstract void detachShader(GL gl, int program, IntBuffer shaders); + public abstract void deleteShader(GL gl, IntBuffer shaders); + + public abstract boolean createAndLoadShader(GL gl, IntBuffer shader, int shaderType, + int binFormat, java.nio.Buffer bin, + PrintStream verboseOut); + + public abstract boolean createAndCompileShader(GL gl, IntBuffer shader, int shaderType, + java.lang.String[][] sources, + PrintStream verboseOut); + } + + static class GL2ES2Impl extends Impl { + public String getShaderInfoLog(GL _gl, int shaderObj) { + GL2ES2 gl = _gl.getGL2ES2(); + int[] infoLogLength=new int[1]; + gl.glGetShaderiv(shaderObj, gl.GL_INFO_LOG_LENGTH, infoLogLength, 0); + + if(infoLogLength[0]==0) { + return "(no info log)"; + } + int[] charsWritten=new int[1]; + byte[] infoLogBytes = new byte[infoLogLength[0]]; + gl.glGetShaderInfoLog(shaderObj, infoLogLength[0], charsWritten, 0, infoLogBytes, 0); + + return new String(infoLogBytes, 0, charsWritten[0]); + } + + public String getProgramInfoLog(GL _gl, int programObj) { + GL2ES2 gl = _gl.getGL2ES2(); + int[] infoLogLength=new int[1]; + gl.glGetProgramiv(programObj, gl.GL_INFO_LOG_LENGTH, infoLogLength, 0); + + if(infoLogLength[0]==0) { + return "(no info log)"; + } + int[] charsWritten=new int[1]; + byte[] infoLogBytes = new byte[infoLogLength[0]]; + gl.glGetProgramInfoLog(programObj, infoLogLength[0], charsWritten, 0, infoLogBytes, 0); + + return new String(infoLogBytes, 0, charsWritten[0]); + } + + public boolean isShaderStatusValid(GL _gl, int shaderObj, int name) { + return isShaderStatusValid(_gl, shaderObj, name, null); + } + + public boolean isShaderStatusValid(GL _gl, int shaderObj, int name, PrintStream verboseOut) { + GL2ES2 gl = _gl.getGL2ES2(); + int[] ires = new int[1]; + gl.glGetShaderiv(shaderObj, name, ires, 0); + + boolean res = ires[0]==1; + if(!res && null!=verboseOut) { + verboseOut.println("Shader status invalid: "+ getShaderInfoLog(gl, shaderObj)); + } + return res; + } + + public boolean isShaderStatusValid(GL _gl, IntBuffer shaders, int name) { + return isShaderStatusValid(_gl, shaders, name, null); + } + + public boolean isShaderStatusValid(GL _gl, IntBuffer shaders, int name, PrintStream verboseOut) { + boolean res = true; + for (int i = shaders.position(); i < shaders.limit(); i++) { + res = isShaderStatusValid(_gl, shaders.get(i), name, verboseOut) && res; + } + return res; + } + + public boolean isProgramStatusValid(GL _gl, int programObj, int name) { + GL2ES2 gl = _gl.getGL2ES2(); + int[] ires = new int[1]; + gl.glGetProgramiv(programObj, name, ires, 0); + + return ires[0]==1; + } + + public boolean isProgramValid(GL _gl, int programObj) { + return isProgramValid(_gl, programObj, null); + } + + public boolean isProgramValid(GL _gl, int programObj, PrintStream verboseOut) { + GL2ES2 gl = _gl.getGL2ES2(); + int[] ires = new int[1]; + if(!gl.glIsProgram(programObj)) { + if(null!=verboseOut) { + verboseOut.println("Program name invalid: "+programObj); + } + return false; + } + if(!isProgramStatusValid(gl, programObj, gl.GL_LINK_STATUS)) { + if(null!=verboseOut) { + verboseOut.println("Program link failed: "+programObj+"\n\t"+ getProgramInfoLog(gl, programObj)); + } + return false; + } + if ( !gl.isGLES2() || isShaderCompilerAvailable(gl) ) { + // failed on APX2500 (ES2.0, no compiler) for valid programs + gl.glValidateProgram(programObj); + if(!isProgramStatusValid(gl, programObj, gl.GL_VALIDATE_STATUS)) { + if(null!=verboseOut) { + verboseOut.println("Program validation failed: "+programObj+"\n\t"+ getProgramInfoLog(gl, programObj)); + } + return false; + } + } + return true; + } + + public void createShader(GL _gl, int type, IntBuffer shaders) { + GL2ES2 gl = _gl.getGL2ES2(); + for (int i = shaders.position(); i < shaders.limit(); i++) { + shaders.put(i, gl.glCreateShader(type)); + } + } + + private Boolean shaderCompilerAvailable = null; + private Set shaderBinaryFormats = null; + + public Set getShaderBinaryFormats(GL _gl) { + GL2ES2 gl = _gl.getGL2ES2(); + if(null==shaderBinaryFormats) { + if(gl.getContext()!=GLContext.getCurrent()) { + return new HashSet(0); // bail out + } + + int[] param = new int[1]; + shaderBinaryFormats = new HashSet(); + + if (gl.isGLES2()) { + gl.glGetIntegerv(GL2ES2.GL_NUM_SHADER_BINARY_FORMATS, param, 0); + int numFormats = param[0]; + if(numFormats>0) { + int[] formats = new int[numFormats]; + gl.glGetIntegerv(GL2ES2.GL_SHADER_BINARY_FORMATS, formats, 0); + for(int i=0; i<numFormats; i++) { + shaderBinaryFormats.add(new Integer(formats[i])); + } + } + } + } + return shaderBinaryFormats; + } + + + public boolean isShaderCompilerAvailable(GL _gl) { + GL2ES2 gl = _gl.getGL2ES2(); + if(null==shaderCompilerAvailable) { + if(gl.getContext()!=GLContext.getCurrent()) { + return false; // bail out + } + Set bfs = getShaderBinaryFormats(gl); + if(gl.isGLES2()) { + byte[] param = new byte[1]; + gl.glGetBooleanv(GL2ES2.GL_SHADER_COMPILER, param, 0); + boolean v = param[0]!=(byte)0x00; + if(!v && bfs.size()==0) { + // no supported binary formats, hence a compiler must be available! + v = true; + } + shaderCompilerAvailable = new Boolean(v); + } else if( gl.isGL2ES2() ) { + shaderCompilerAvailable = new Boolean(true); + } else { + throw new GLException("Invalid OpenGL profile"); + } + } + return shaderCompilerAvailable.booleanValue(); + } + + public void shaderSource(GL _gl, int shader, java.lang.String[] source) + { + GL2ES2 gl = _gl.getGL2ES2(); + if(!isShaderCompilerAvailable(_gl)) { + throw new GLException("No compiler is available"); + } + + int count = (null!=source)?source.length:0; + if(count==0) { + throw new GLException("No sources specified"); + } + + int[] lengths = new int[count]; + for(int i=0; i<count; i++) { + lengths[i] = source[i].length(); + } + gl.glShaderSource(shader, count, source, lengths, 0); + } + + public void shaderSource(GL _gl, IntBuffer shaders, java.lang.String[][] sources) + { + int sourceNum = (null!=sources)?sources.length:0; + int shaderNum = (null!=shaders)?shaders.remaining():0; + if(shaderNum<=0 || sourceNum<=0 || shaderNum!=sourceNum) { + throw new GLException("Invalid number of shaders and/or sources: shaders="+ + shaderNum+", sources="+sourceNum); + } + for(int i=0; i<sourceNum; i++) { + shaderSource(_gl, shaders.get(shaders.position() + i), sources[i]); + } + } + + public void shaderBinary(GL _gl, IntBuffer shaders, int binFormat, java.nio.Buffer bin) + { + GL2ES2 gl = _gl.getGL2ES2(); + if(getShaderBinaryFormats(gl).size()<=0) { + throw new GLException("No binary formats are supported"); + } + + int shaderNum = shaders.remaining(); + if(shaderNum<=0) { + throw new GLException("No shaders specified"); + } + if(null==bin) { + throw new GLException("Null shader binary"); + } + int binLength = bin.remaining(); + if(0>=binLength) { + throw new GLException("Empty shader binary (remaining == 0)"); + } + gl.glShaderBinary(shaderNum, shaders, binFormat, bin, binLength); + } + + public void compileShader(GL _gl, IntBuffer shaders) + { + GL2ES2 gl = _gl.getGL2ES2(); + for (int i = shaders.position(); i < shaders.limit(); i++) { + gl.glCompileShader(shaders.get(i)); + } + } + + public void attachShader(GL _gl, int program, IntBuffer shaders) + { + GL2ES2 gl = _gl.getGL2ES2(); + for (int i = shaders.position(); i < shaders.limit(); i++) { + gl.glAttachShader(program, shaders.get(i)); + } + } + + public void detachShader(GL _gl, int program, IntBuffer shaders) + { + GL2ES2 gl = _gl.getGL2ES2(); + for (int i = shaders.position(); i < shaders.limit(); i++) { + gl.glDetachShader(program, shaders.get(i)); + } + } + + public void deleteShader(GL _gl, IntBuffer shaders) + { + GL2ES2 gl = _gl.getGL2ES2(); + for (int i = shaders.position(); i < shaders.limit(); i++) { + gl.glDeleteShader(shaders.get(i)); + + } + } + + public boolean createAndLoadShader(GL _gl, IntBuffer shader, int shaderType, + int binFormat, java.nio.Buffer bin, + PrintStream verboseOut) + { + GL2ES2 gl = _gl.getGL2ES2(); + int err = gl.glGetError(); // flush previous errors .. + if(err!=GL.GL_NO_ERROR && null!=verboseOut) { + verboseOut.println("createAndLoadShader: Pre GL Error: 0x"+Integer.toHexString(err)); + } + + createShader(gl, shaderType, shader); + err = gl.glGetError(); + if(err!=GL.GL_NO_ERROR) { + throw new GLException("createAndLoadShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err)); + } + + + shaderBinary(gl, shader, binFormat, bin); + + err = gl.glGetError(); + if(err!=GL.GL_NO_ERROR && null!=verboseOut) { + verboseOut.println("createAndLoadShader: ShaderBinary failed, GL Error: 0x"+Integer.toHexString(err)); + } + return err == GL.GL_NO_ERROR; + } + + public boolean createAndCompileShader(GL _gl, IntBuffer shader, int shaderType, + java.lang.String[][] sources, + PrintStream verboseOut) + { + GL2ES2 gl = _gl.getGL2ES2(); + int err = gl.glGetError(); // flush previous errors .. + if(err!=GL.GL_NO_ERROR && null!=verboseOut) { + verboseOut.println("createAndCompileShader: Pre GL Error: 0x"+Integer.toHexString(err)); + } + + createShader(gl, shaderType, shader); + err = gl.glGetError(); + if(err!=GL.GL_NO_ERROR) { + throw new GLException("createAndCompileShader: CreateShader failed, GL Error: 0x"+Integer.toHexString(err)); + } + + shaderSource(gl, shader, sources); + err = gl.glGetError(); + if(err!=GL.GL_NO_ERROR) { + throw new GLException("createAndCompileShader: ShaderSource failed, GL Error: 0x"+Integer.toHexString(err)); + } + + compileShader(gl, shader); + err = gl.glGetError(); + if(err!=GL.GL_NO_ERROR && null!=verboseOut) { + verboseOut.println("createAndCompileShader: CompileShader failed, GL Error: 0x"+Integer.toHexString(err)); + } + + return isShaderStatusValid(gl, shader, gl.GL_COMPILE_STATUS, verboseOut) && err == GL.GL_NO_ERROR; + } + + } + + public static String getShaderInfoLog(GL gl, int shaderObj) { + return getImpl(gl).getShaderInfoLog(gl, shaderObj); + } + + public static String getProgramInfoLog(GL gl, int programObj) { + return getImpl(gl).getProgramInfoLog(gl, programObj); + } + + public static boolean isShaderStatusValid(GL gl, int shaderObj, int name) { + return getImpl(gl).isShaderStatusValid(gl, shaderObj, name); + } + + public static boolean isShaderStatusValid(GL gl, int shaderObj, int name, PrintStream verboseOut) { + return getImpl(gl).isShaderStatusValid(gl, shaderObj, name, verboseOut); + } + + public static boolean isShaderStatusValid(GL gl, IntBuffer shaders, int name) { + return getImpl(gl).isShaderStatusValid(gl, shaders, name); + } + + public static boolean isShaderStatusValid(GL gl, IntBuffer shaders, int name, PrintStream verboseOut) { + return getImpl(gl).isShaderStatusValid(gl, shaders, name, verboseOut); + } + + public static boolean isProgramStatusValid(GL gl, int programObj, int name) { + return getImpl(gl).isProgramStatusValid(gl, programObj, name); + } + + public static boolean isProgramValid(GL gl, int programObj) { + return getImpl(gl).isProgramValid(gl, programObj); + } + + public static boolean isProgramValid(GL gl, int programObj, PrintStream verboseOut) { + return getImpl(gl).isProgramValid(gl, programObj, verboseOut); + } + + public static void createShader(GL gl, int type, IntBuffer shaders) { + getImpl(gl).createShader(gl, type, shaders); + } + + public static Set getShaderBinaryFormats(GL gl) { + return getImpl(gl).getShaderBinaryFormats(gl); + } + + public static boolean isShaderCompilerAvailable(GL gl) { + return getImpl(gl).isShaderCompilerAvailable(gl); + } + + public static void shaderSource(GL gl, int shader, java.lang.String[] source) { + getImpl(gl).shaderSource(gl, shader, source); + } + + public static void shaderSource(GL gl, IntBuffer shaders, java.lang.String[][] sources) { + getImpl(gl).shaderSource(gl, shaders, sources); + } + + public static void shaderBinary(GL gl, IntBuffer shaders, int binFormat, java.nio.Buffer bin) { + getImpl(gl).shaderBinary(gl, shaders, binFormat, bin); + } + + public static void compileShader(GL gl, IntBuffer shaders) { + getImpl(gl).compileShader(gl, shaders); + } + + public static void attachShader(GL gl, int program, IntBuffer shaders) { + getImpl(gl).attachShader(gl, program, shaders); + } + + public static void detachShader(GL gl, int program, IntBuffer shaders) { + getImpl(gl).detachShader(gl, program, shaders); + } + + public static void deleteShader(GL gl, IntBuffer shaders) { + getImpl(gl).deleteShader(gl, shaders); + } + + public static boolean createAndLoadShader(GL gl, IntBuffer shader, int shaderType, + int binFormat, java.nio.Buffer bin, + PrintStream verboseOut) { + return getImpl(gl).createAndLoadShader(gl, shader, shaderType, binFormat, bin, verboseOut); + } + + public static boolean createAndCompileShader(GL gl, IntBuffer shader, int shaderType, + java.lang.String[][] sources, + PrintStream verboseOut) { + return getImpl(gl).createAndCompileShader(gl, shader, shaderType, sources, verboseOut); + } + + private static Impl getImpl(GL _gl) { + GL2ES2 gl = _gl.getGL2ES2(); + GLContext context = gl.getContext(); + Impl impl = (Impl) context.getAttachedObject(ShaderUtil.class.getName()); + if (impl == null) { + impl = new GL2ES2Impl(); + context.putAttachedObject(ShaderUtil.class.getName(), impl); + } + return impl; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java new file mode 100644 index 000000000..7ec4ac50e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/FixedFuncUtil.java @@ -0,0 +1,90 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package com.jogamp.opengl.util.glsl.fixedfunc; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; + +import com.jogamp.opengl.util.glsl.fixedfunc.impl.*; + +/** + * Tool to pipeline GL2ES2 into a fixed function emulation implementing GL2ES1. + */ +public class FixedFuncUtil { + /** + * @return If gl is a GL2ES1 and force is false, return the type cast object, + * otherwise create a fixed function emulation pipeline with the GL2ES2 impl. + * @throws GLException if the GL object is neither GL2ES1 nor GL2ES2 + */ + public static final GL2ES1 getFixedFuncImpl(GL gl, boolean force) { + if(!force && gl.isGL2ES1()) { + return gl.getGL2ES1(); + } else if(gl.isGL2ES2()) { + GL2ES2 es2 = gl.getGL2ES2(); + FixedFuncHook hook = new FixedFuncHook(es2); + FixedFuncImpl impl = new FixedFuncImpl(es2, hook); + gl.getContext().setGL(impl); + return impl; + } + throw new GLException("GL Object is neither GL2ES1 nor GL2ES2: "+gl.getContext()); + } + + /** + * @return If gl is a GL2ES1, return the type cast object, + * otherwise create a fixed function emulation pipeline with the GL2ES2 impl. + * @throws GLException if the GL object is neither GL2ES1 nor GL2ES2 + */ + public static final GL2ES1 getFixedFuncImpl(GL gl) { + return getFixedFuncImpl(gl, false); + } + + /** + * Mapping fixed function (client) array indices to + * GLSL array attribute names. + * + * Useful for uniq mapping of canonical array index names as listed. + * + * @see #mgl_Vertex + * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_VERTEX_ARRAY + * @see #mgl_Normal + * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_NORMAL_ARRAY + * @see #mgl_Color + * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_COLOR_ARRAY + * @see #mgl_MultiTexCoord + * @see javax.media.opengl.fixedfunc.GLPointerFunc#GL_TEXTURE_COORD_ARRAY + * @see javax.media.opengl.fixedfunc.GLPointerFunc#glEnableClientState + * @see javax.media.opengl.fixedfunc.GLPointerFunc#glVertexPointer + * @see javax.media.opengl.fixedfunc.GLPointerFunc#glColorPointer + * @see javax.media.opengl.fixedfunc.GLPointerFunc#glNormalPointer + * @see javax.media.opengl.fixedfunc.GLPointerFunc#glTexCoordPointer + */ + public static String getPredefinedArrayIndexName(int glArrayIndex) { + return FixedFuncPipeline.getPredefinedArrayIndexName(glArrayIndex); + } + + /** + * String name for + * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY + */ + public static final String mgl_Vertex = FixedFuncPipeline.mgl_Vertex; + + /** + * String name for + * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY + */ + public static final String mgl_Normal = FixedFuncPipeline.mgl_Normal; + + /** + * String name for + * @see javax.media.opengl.GL2#GL_COLOR_ARRAY + */ + public static final String mgl_Color = FixedFuncPipeline.mgl_Color; + + /** + * String name for + * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY + */ + public static final String mgl_MultiTexCoord = FixedFuncPipeline.mgl_MultiTexCoord; +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncHook.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncHook.java new file mode 100755 index 000000000..b8e3922a4 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncHook.java @@ -0,0 +1,331 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + */ + +package com.jogamp.opengl.util.glsl.fixedfunc.impl; + +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; +import javax.media.opengl.glu.*; +import com.jogamp.common.nio.Buffers; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.glsl.*; +import java.nio.*; + +public class FixedFuncHook implements GLLightingFunc, GLMatrixFunc, GLPointerFunc { + public static final int MAX_TEXTURE_UNITS = 8; + + protected FixedFuncPipeline fixedFunction=null; + protected PMVMatrix pmvMatrix=null; + protected GL2ES2 gl=null; + + public FixedFuncHook (GL2ES2 gl) { + this(gl, null); + } + + public FixedFuncHook (GL2ES2 gl, PMVMatrix matrix) { + this.gl = gl; + pmvMatrix = (null!=matrix)?matrix:new PMVMatrix(); + + fixedFunction = new FixedFuncPipeline(gl, pmvMatrix); + } + + public FixedFuncHook(GL2ES2 gl, PMVMatrix matrix, + Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot, + String vertexColorFile, + String vertexColorLightFile, + String fragmentColorFile, + String fragmentColorTextureFile) { + this.gl = gl; + pmvMatrix = matrix; + + fixedFunction = new FixedFuncPipeline(gl, pmvMatrix, + shaderRootClass, shaderSrcRoot, shaderBinRoot, + vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); + } + + public void destroy() { + fixedFunction.destroy(gl); + fixedFunction = null; + } + + public PMVMatrix getMatrix() { return pmvMatrix; } + + // + // FixedFuncHookIf - hooks + // + public void glDrawArrays(int mode, int first, int count) { + fixedFunction.validate(gl); + gl.glDrawArrays(mode, first, count); + } + public void glDrawElements(int mode, int count, int type, java.nio.Buffer indices) { + fixedFunction.validate(gl); + gl.glDrawElements(mode, count, type, indices); + } + public void glDrawElements(int mode, int count, int type, long indices_buffer_offset) { + fixedFunction.validate(gl); + gl.glDrawElements(mode, count, type, indices_buffer_offset); + } + + public void glActiveTexture(int texture) { + fixedFunction.glActiveTexture(gl, texture); + gl.glActiveTexture(texture); + } + public void glEnable(int cap) { + if(fixedFunction.glEnable(gl, cap, true)) { + gl.glEnable(cap); + } + } + public void glDisable(int cap) { + if(fixedFunction.glEnable(gl, cap, false)) { + gl.glDisable(cap); + } + } + public void glCullFace(int faceName) { + fixedFunction.glCullFace(gl, faceName); + gl.glCullFace(faceName); + } + + public void glGetFloatv(int pname, java.nio.FloatBuffer params) { + if(pmvMatrix.isMatrixGetName(pname)) { + pmvMatrix.glGetFloatv(pname, params); + return; + } + gl.glGetFloatv(pname, params); + } + public void glGetFloatv(int pname, float[] params, int params_offset) { + if(pmvMatrix.isMatrixGetName(pname)) { + pmvMatrix.glGetFloatv(pname, params, params_offset); + return; + } + gl.glGetFloatv(pname, params, params_offset); + } + public void glGetIntegerv(int pname, IntBuffer params) { + if(pmvMatrix.isMatrixGetName(pname)) { + pmvMatrix.glGetIntegerv(pname, params); + return; + } + gl.glGetIntegerv(pname, params); + } + public void glGetIntegerv(int pname, int[] params, int params_offset) { + if(pmvMatrix.isMatrixGetName(pname)) { + pmvMatrix.glGetIntegerv(pname, params, params_offset); + return; + } + gl.glGetIntegerv(pname, params, params_offset); + } + + // + // MatrixIf + // + public int glGetMatrixMode() { + return pmvMatrix.glGetMatrixMode(); + } + public void glMatrixMode(int mode) { + pmvMatrix.glMatrixMode(mode); + } + public void glLoadMatrixf(java.nio.FloatBuffer m) { + pmvMatrix.glLoadMatrixf(m); + } + public void glLoadMatrixf(float[] m, int m_offset) { + glLoadMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset)); + } + public void glPopMatrix() { + pmvMatrix.glPopMatrix(); + } + public void glPushMatrix() { + pmvMatrix.glPushMatrix(); + } + public void glLoadIdentity() { + pmvMatrix.glLoadIdentity(); + } + public void glMultMatrixf(java.nio.FloatBuffer m) { + pmvMatrix.glMultMatrixf(m); + } + public void glMultMatrixf(float[] m, int m_offset) { + glMultMatrixf(GLBuffers.newDirectFloatBuffer(m, m_offset)); + } + public void glTranslatef(float x, float y, float z) { + pmvMatrix.glTranslatef(x, y, z); + } + public void glRotatef(float angdeg, float x, float y, float z) { + pmvMatrix.glRotatef(angdeg, x, y, z); + } + public void glScalef(float x, float y, float z) { + pmvMatrix.glScalef(x, y, z); + } + public void glOrthof(float left, float right, float bottom, float top, float zNear, float zFar) { + pmvMatrix.glOrthof(left, right, bottom, top, zNear, zFar); + } + public void glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar) { + pmvMatrix.glFrustumf(left, right, bottom, top, zNear, zFar); + } + + // + // LightingIf + // + public void glColor4f(float red, float green, float blue, float alpha) { + fixedFunction.glColor4fv(gl, GLBuffers.newDirectFloatBuffer(new float[] { red, green, blue, alpha })); + } + + public void glLightfv(int light, int pname, java.nio.FloatBuffer params) { + fixedFunction.glLightfv(gl, light, pname, params); + } + public void glLightfv(int light, int pname, float[] params, int params_offset) { + glLightfv(light, pname, GLBuffers.newDirectFloatBuffer(params, params_offset)); + } + public void glMaterialfv(int face, int pname, java.nio.FloatBuffer params) { + fixedFunction.glMaterialfv(gl, face, pname, params); + } + public void glMaterialfv(int face, int pname, float[] params, int params_offset) { + glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(params, params_offset)); + } + public void glMaterialf(int face, int pname, float param) { + glMaterialfv(face, pname, GLBuffers.newDirectFloatBuffer(new float[] { param })); + } + public void glShadeModel(int mode) { + fixedFunction.glShadeModel(gl, mode); + } + + // + // PointerIf + // + public void glEnableClientState(int glArrayIndex) { + fixedFunction.glEnableClientState(gl, glArrayIndex); + } + public void glDisableClientState(int glArrayIndex) { + fixedFunction.glDisableClientState(gl, glArrayIndex); + } + + public void glVertexPointer(GLArrayData array) { + if(array.isVBO()) { + if(!gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not enabled: "+array); + } + } else { + if(gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not disabled: "+array); + } + Buffers.rangeCheck(array.getBuffer(), 1); + if (!Buffers.isDirect(array.getBuffer())) { + throw new GLException("Argument \"pointer\" was not a direct buffer"); } + } + fixedFunction.glVertexPointer(gl, array); + } + + public void glVertexPointer(int size, int type, int stride, java.nio.Buffer pointer) { + glVertexPointer(GLArrayDataWrapper.createFixed(gl, GL_VERTEX_ARRAY, size, type, false, stride, pointer, 0, 0)); + } + public void glVertexPointer(int size, int type, int stride, long pointer_buffer_offset) { + int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + if(vboName==0) { + throw new GLException("no GL_ARRAY_BUFFER VBO bound"); + } + glVertexPointer(GLArrayDataWrapper.createFixed(gl, GL_VERTEX_ARRAY, size, type, false, + stride, null, vboName, pointer_buffer_offset)); + } + + public void glColorPointer(GLArrayData array) { + if(array.isVBO()) { + if(!gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not enabled: "+array); + } + } else { + if(gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not disabled: "+array); + } + Buffers.rangeCheck(array.getBuffer(), 1); + if (!Buffers.isDirect(array.getBuffer())) { + throw new GLException("Argument \"pointer\" was not a direct buffer"); } + } + fixedFunction.glColorPointer(gl, array); + } + public void glColorPointer(int size, int type, int stride, java.nio.Buffer pointer) { + glColorPointer(GLArrayDataWrapper.createFixed(gl, GL_COLOR_ARRAY, size, type, false, + stride, pointer, 0, 0)); + } + public void glColorPointer(int size, int type, int stride, long pointer_buffer_offset) { + int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + if(vboName==0) { + throw new GLException("no GL_ARRAY_BUFFER VBO bound"); + } + glColorPointer(GLArrayDataWrapper.createFixed(gl, GL_COLOR_ARRAY, size, type, false, + stride, null, vboName, pointer_buffer_offset)); + } + + public void glNormalPointer(GLArrayData array) { + if(array.getComponentNumber()!=3) { + throw new GLException("Only 3 components per normal allowed"); + } + if(array.isVBO()) { + if(!gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not enabled: "+array); + } + } else { + if(gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not disabled: "+array); + } + Buffers.rangeCheck(array.getBuffer(), 1); + if (!Buffers.isDirect(array.getBuffer())) { + throw new GLException("Argument \"pointer\" was not a direct buffer"); } + } + fixedFunction.glNormalPointer(gl, array); + } + public void glNormalPointer(int type, int stride, java.nio.Buffer pointer) { + glNormalPointer(GLArrayDataWrapper.createFixed(gl, GL_NORMAL_ARRAY, 3, type, false, + stride, pointer, 0, 0)); + } + public void glNormalPointer(int type, int stride, long pointer_buffer_offset) { + int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + if(vboName==0) { + throw new GLException("no GL_ARRAY_BUFFER VBO bound"); + } + glNormalPointer(GLArrayDataWrapper.createFixed(gl, GL_NORMAL_ARRAY, 3, type, false, + stride, null, vboName, pointer_buffer_offset)); + } + + public void glTexCoordPointer(GLArrayData array) { + if(array.isVBO()) { + if(!gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not enabled: "+array); + } + } else { + if(gl.glIsVBOArrayEnabled()) { + throw new GLException("VBO array is not disabled: "+array); + } + Buffers.rangeCheck(array.getBuffer(), 1); + if (!Buffers.isDirect(array.getBuffer())) { + throw new GLException("Argument \"pointer\" was not a direct buffer"); } + } + fixedFunction.glTexCoordPointer(gl, array); + } + public void glTexCoordPointer(int size, int type, int stride, java.nio.Buffer pointer) { + glTexCoordPointer( + GLArrayDataWrapper.createFixed(gl, GL_TEXTURE_COORD_ARRAY, size, type, false, stride, pointer, 0,0)); + } + public void glTexCoordPointer(int size, int type, int stride, long pointer_buffer_offset) { + int vboName = gl.glGetBoundBuffer(GL.GL_ARRAY_BUFFER); + if(vboName==0) { + throw new GLException("no GL_ARRAY_BUFFER VBO bound"); + } + glTexCoordPointer( + GLArrayDataWrapper.createFixed(gl, GL_TEXTURE_COORD_ARRAY, size, type, false, + stride, null, vboName, pointer_buffer_offset) ); + } + + public final String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(getClass().getName()+" ("); + if(null!=pmvMatrix) { + buf.append(", matrixDirty: "+pmvMatrix.isDirty()); + } + buf.append("\n\t, FixedFunction: "+fixedFunction); + buf.append(gl); + buf.append(" )"); + + return buf.toString(); + } + +} + + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncPipeline.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncPipeline.java new file mode 100644 index 000000000..529e4567b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/FixedFuncPipeline.java @@ -0,0 +1,554 @@ + +package com.jogamp.opengl.util.glsl.fixedfunc.impl; + +import com.jogamp.common.nio.Buffers; +import javax.media.opengl.*; +import javax.media.opengl.fixedfunc.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.glsl.*; +import java.nio.*; + +public class FixedFuncPipeline { + public static final int MAX_TEXTURE_UNITS = 8; + public static final int MAX_LIGHTS = 8; + + // We can't have any dependencies on the FixedFuncUtil class for build bootstrapping reasons + public static final String mgl_Vertex = "mgl_Vertex"; + public static final String mgl_Normal = "mgl_Normal"; + public static final String mgl_Color = "mgl_Color"; + public static final String mgl_MultiTexCoord = "mgl_MultiTexCoord" ; + + public static String getPredefinedArrayIndexName(int glArrayIndex) { + switch(glArrayIndex) { + case GLPointerFunc.GL_VERTEX_ARRAY: + return mgl_Vertex; + case GLPointerFunc.GL_NORMAL_ARRAY: + return mgl_Normal; + case GLPointerFunc.GL_COLOR_ARRAY: + return mgl_Color; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + return mgl_MultiTexCoord; + } + return null; + } + + public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix) { + init(gl, pmvMatrix, FixedFuncPipeline.class, shaderSrcRootDef, shaderBinRootDef, + vertexColorFileDef, vertexColorLightFileDef, fragmentColorFileDef, fragmentColorTextureFileDef); + } + public FixedFuncPipeline(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot, + String vertexColorFile, + String vertexColorLightFile, + String fragmentColorFile, + String fragmentColorTextureFile) { + init(gl, pmvMatrix, shaderRootClass, shaderSrcRoot, shaderBinRoot, + vertexColorFile, vertexColorLightFile, fragmentColorFile, fragmentColorTextureFile); + } + + public boolean verbose() { return verbose; } + + public void setVerbose(boolean v) { verbose=v; } + + public boolean isValid() { + return shaderState.linked(); + } + + public ShaderState getShaderState() { + return shaderState; + } + + public int getActiveTextureUnit() { + return activeTextureUnit; + } + + public String getArrayIndexName(int glArrayIndex) { + String name = getPredefinedArrayIndexName(glArrayIndex); + switch(glArrayIndex) { + case GLPointerFunc.GL_VERTEX_ARRAY: + case GLPointerFunc.GL_NORMAL_ARRAY: + case GLPointerFunc.GL_COLOR_ARRAY: + break; + case GLPointerFunc.GL_TEXTURE_COORD_ARRAY: + name = name + activeTextureUnit; + } + return name; + } + + public void destroy(GL2ES2 gl) { + shaderProgramColor.release(gl, true); + shaderProgramColorLight.release(gl, true); + shaderProgramColorTexture.release(gl, true); + shaderProgramColorTextureLight.release(gl, true); + shaderState.destroy(gl); + } + + public void glEnableClientState(GL2ES2 gl, int glArrayIndex) { + shaderState.glUseProgram(gl, true); + + shaderState.glEnableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); + // textureCoordsEnabled |= (1 << activeTextureUnit); + if ( textureCoordsEnabled.get(activeTextureUnit) != 1 ) { + textureCoordsEnabled.put(activeTextureUnit, 1); + textureCoordsEnabledDirty = true; + } + } + + public void glDisableClientState(GL2ES2 gl, int glArrayIndex) { + shaderState.glUseProgram(gl, true); + + shaderState.glDisableVertexAttribArray(gl, getArrayIndexName(glArrayIndex)); + // textureCoordsEnabled &= ~(1 << activeTextureUnit); + if ( textureCoordsEnabled.get(activeTextureUnit) != 0 ) { + textureCoordsEnabled.put(activeTextureUnit, 0); + textureCoordsEnabledDirty = true; + } + } + + public void glVertexPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glColorPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glColor4fv(GL2ES2 gl, FloatBuffer data ) { + shaderState.glUseProgram(gl, true); + GLUniformData ud = shaderState.getUniform(mgl_ColorStatic); + if(null!=ud) { + ud.setData(data); + shaderState.glUniform(gl, ud); + } + } + + public void glNormalPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glTexCoordPointer(GL2ES2 gl, GLArrayData data) { + shaderState.glUseProgram(gl, true); + data.setName( getArrayIndexName(data.getIndex()) ); + shaderState.glVertexAttribPointer(gl, data); + } + + public void glLightfv(GL2ES2 gl, int light, int pname, java.nio.FloatBuffer params) { + shaderState.glUseProgram(gl, true); + light -=GLLightingFunc.GL_LIGHT0; + if(0 <= light && light < MAX_LIGHTS) { + GLUniformData ud = null; + switch(pname) { + case GLLightingFunc.GL_AMBIENT: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].ambient"); + break; + case GLLightingFunc.GL_DIFFUSE: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].diffuse"); + break; + case GLLightingFunc.GL_SPECULAR: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].specular"); + break; + case GLLightingFunc.GL_POSITION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].position"); + break; + case GLLightingFunc.GL_SPOT_DIRECTION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotDirection"); + break; + case GLLightingFunc.GL_SPOT_EXPONENT: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotExponent"); + break; + case GLLightingFunc.GL_SPOT_CUTOFF: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].spotCutoff"); + break; + case GLLightingFunc.GL_CONSTANT_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].constantAttenuation"); + break; + case GLLightingFunc.GL_LINEAR_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].linearAttenuation"); + break; + case GLLightingFunc.GL_QUADRATIC_ATTENUATION: + ud = shaderState.getUniform(mgl_LightSource+"["+light+"].quadraticAttenuation"); + break; + default: + if(verbose) { + System.err.println("glLightfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_POSITION GL_SPOT_DIRECTION]: "+pname); + } + return; + } + if(null!=ud) { + ud.setData(params); + shaderState.glUniform(gl, ud); + } + } else if(verbose) { + System.err.println("glLightfv light not within [0.."+MAX_LIGHTS+"]: "+light); + } + } + + public void glMaterialfv(GL2ES2 gl, int face, int pname, java.nio.FloatBuffer params) { + shaderState.glUseProgram(gl, true); + + switch (face) { + case GL.GL_FRONT: + case GL.GL_FRONT_AND_BACK: + break; + case GL.GL_BACK: + if(verbose) { + System.err.println("glMaterialfv face GL_BACK currently not supported"); + } + break; + default: + } + + GLUniformData ud = null; + switch(pname) { + case GLLightingFunc.GL_AMBIENT: + ud = shaderState.getUniform(mgl_FrontMaterial+".ambient"); + break; + case GLLightingFunc.GL_AMBIENT_AND_DIFFUSE: + glMaterialfv(gl, face, GLLightingFunc.GL_AMBIENT, params); + // fall through intended .. + case GLLightingFunc.GL_DIFFUSE: + ud = shaderState.getUniform(mgl_FrontMaterial+".diffuse"); + break; + case GLLightingFunc.GL_SPECULAR: + ud = shaderState.getUniform(mgl_FrontMaterial+".specular"); + break; + case GLLightingFunc.GL_EMISSION: + ud = shaderState.getUniform(mgl_FrontMaterial+".emission"); + break; + case GLLightingFunc.GL_SHININESS: + ud = shaderState.getUniform(mgl_FrontMaterial+".shininess"); + break; + default: + if(verbose) { + System.err.println("glMaterialfv pname not within [GL_AMBIENT GL_DIFFUSE GL_SPECULAR GL_EMISSION GL_SHININESS]: "+pname); + } + return; + } + if(null!=ud) { + ud.setData(params); + shaderState.glUniform(gl, ud); + } + } + + public void glShadeModel(GL2ES2 gl, int mode) { + shaderState.glUseProgram(gl, true); + GLUniformData ud = shaderState.getUniform(mgl_ShadeModel); + if(null!=ud) { + ud.setData(mode); + shaderState.glUniform(gl, ud); + } + } + + public void glActiveTexture(GL2ES2 gl, int textureUnit) { + textureUnit -= GL.GL_TEXTURE0; + if(0 <= textureUnit && textureUnit<MAX_TEXTURE_UNITS) { + shaderState.glUseProgram(gl, true); + GLUniformData ud; + ud = shaderState.getUniform(mgl_ActiveTexture); + if(null!=ud) { + ud.setData(textureUnit); + shaderState.glUniform(gl, ud); + } + ud = shaderState.getUniform(mgl_ActiveTextureIdx); + if(null!=ud) { + ud.setData(textureUnit); + shaderState.glUniform(gl, ud); + } + activeTextureUnit = textureUnit; + } else { + throw new GLException("glActivateTexture textureUnit not within GL_TEXTURE0 + [0.."+MAX_TEXTURE_UNITS+"]: "+textureUnit); + } + } + + /** + * @return false if digested in regard to GL2ES2 spec, + * eg this call must not be passed to an underlying ES2 implementation. + * true if this call shall be passed to an underlying GL2ES2/ES2 implementation as well. + */ + public boolean glEnable(GL2ES2 gl, int cap, boolean enable) { + switch(cap) { + case GL.GL_TEXTURE_2D: + textureEnabled=enable; + return true; + case GLLightingFunc.GL_LIGHTING: + lightingEnabled=enable; + return false; + case GL.GL_CULL_FACE: + cullFace=Math.abs(cullFace); + if(!enable) { + cullFace*=-1; + } + return true; + } + + int light = cap - GLLightingFunc.GL_LIGHT0; + if(0 <= light && light < MAX_LIGHTS) { + if ( (lightsEnabled.get(light)==1) != enable ) { + lightsEnabled.put(light, enable?1:0); + lightsEnabledDirty = true; + return false; + } + } + return true; // pass it on .. + } + + public void glCullFace(GL2ES2 gl, int faceName) { + switch(faceName) { + case GL.GL_FRONT: + faceName = 1; break; + case GL.GL_BACK: + faceName = 2; break; + case GL.GL_FRONT_AND_BACK: + faceName = 3; break; + } + if(0>cullFace) { + faceName *= -1; + } + cullFace = faceName; + } + + public void validate(GL2ES2 gl) { + shaderState.glUseProgram(gl, true); + GLUniformData ud; + if(pmvMatrix.update()) { + ud = shaderState.getUniform(mgl_PMVMatrix); + if(null!=ud) { + // same data object .. + shaderState.glUniform(gl, ud); + } else { + throw new GLException("Failed to update: mgl_PMVMatrix"); + } + ud = shaderState.getUniform(mgl_NormalMatrix); + if(null!=ud) { + // same data object .. + shaderState.glUniform(gl, ud); + } + } + ud = shaderState.getUniform(mgl_ColorEnabled); + if(null!=ud) { + int ca = (shaderState.isVertexAttribArrayEnabled(mgl_Color)==true)?1:0; + if(ca!=ud.intValue()) { + ud.setData(ca); + shaderState.glUniform(gl, ud); + } + } + ud = shaderState.getUniform(mgl_CullFace); + if(null!=ud) { + if(cullFace!=ud.intValue()) { + ud.setData(cullFace); + shaderState.glUniform(gl, ud); + } + } + + if(lightsEnabledDirty) { + ud = shaderState.getUniform(mgl_LightsEnabled); + if(null!=ud) { + // same data object + shaderState.glUniform(gl, ud); + } + lightsEnabledDirty=false; + } + + if(textureCoordsEnabledDirty) { + ud = shaderState.getUniform(mgl_TexCoordEnabled); + if(null!=ud) { + // same data object + shaderState.glUniform(gl, ud); + } + textureCoordsEnabledDirty=false; + } + + if(textureEnabled) { + if(lightingEnabled) { + shaderState.attachShaderProgram(gl, shaderProgramColorTextureLight); + } else { + shaderState.attachShaderProgram(gl, shaderProgramColorTexture); + } + } else { + if(lightingEnabled) { + shaderState.attachShaderProgram(gl, shaderProgramColorLight); + } else { + shaderState.attachShaderProgram(gl, shaderProgramColor); + } + } + if(DEBUG) { + System.err.println("validate: "+this); + } + } + + public String toString() { + return "FixedFuncPipeline[pmv: "+pmvMatrix+ + ", textureEnabled: "+textureEnabled+ + ", textureCoordsEnabled: "+textureCoordsEnabled+ + ", lightingEnabled: "+lightingEnabled+ + ", lightsEnabled: "+lightsEnabled+ + "\n\t, shaderProgramColor: "+shaderProgramColor+ + "\n\t, shaderProgramColorTexture: "+shaderProgramColorTexture+ + "\n\t, shaderProgramColorLight: "+shaderProgramColorLight+ + "\n\t, shaderProgramColorTextureLight: "+shaderProgramColorTextureLight+ + "\n\t, ShaderState: "+shaderState+ + "]"; + } + + protected void init(GL2ES2 gl, PMVMatrix pmvMatrix, Class shaderRootClass, String shaderSrcRoot, String shaderBinRoot, + String vertexColorFile, + String vertexColorLightFile, + String fragmentColorFile, + String fragmentColorTextureFile) + { + if(null==pmvMatrix) { + throw new GLException("PMVMatrix is null"); + } + this.pmvMatrix=pmvMatrix; + this.shaderState=new ShaderState(); + this.shaderState.setVerbose(verbose); + ShaderCode vertexColor, vertexColorLight, fragmentColor, fragmentColorTexture; + + vertexColor = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, 1, shaderRootClass, + shaderSrcRoot, shaderBinRoot, vertexColorFile); + + vertexColorLight = ShaderCode.create( gl, gl.GL_VERTEX_SHADER, 1, shaderRootClass, + shaderSrcRoot, shaderBinRoot, vertexColorLightFile); + + fragmentColor = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, 1, shaderRootClass, + shaderSrcRoot, shaderBinRoot, fragmentColorFile); + + fragmentColorTexture = ShaderCode.create( gl, gl.GL_FRAGMENT_SHADER, 1, shaderRootClass, + shaderSrcRoot, shaderBinRoot, fragmentColorTextureFile); + + shaderProgramColor = new ShaderProgram(); + shaderProgramColor.add(vertexColor); + shaderProgramColor.add(fragmentColor); + if(!shaderProgramColor.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColor program: "+shaderProgramColor); + } + + shaderProgramColorTexture = new ShaderProgram(); + shaderProgramColorTexture.add(vertexColor); + shaderProgramColorTexture.add(fragmentColorTexture); + if(!shaderProgramColorTexture.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorTexture program: "+shaderProgramColorTexture); + } + + shaderProgramColorLight = new ShaderProgram(); + shaderProgramColorLight.add(vertexColorLight); + shaderProgramColorLight.add(fragmentColor); + if(!shaderProgramColorLight.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorLight); + } + + shaderProgramColorTextureLight = new ShaderProgram(); + shaderProgramColorTextureLight.add(vertexColorLight); + shaderProgramColorTextureLight.add(fragmentColorTexture); + if(!shaderProgramColorTextureLight.link(gl, System.err)) { + throw new GLException("Couldn't link VertexColorLight program: "+shaderProgramColorTextureLight); + } + + shaderState.attachShaderProgram(gl, shaderProgramColor); + shaderState.glUseProgram(gl, true); + + // mandatory .. + if(!shaderState.glUniform(gl, new GLUniformData(mgl_PMVMatrix, 4, 4, pmvMatrix.glGetPMvMviMatrixf()))) { + throw new GLException("Error setting PMVMatrix in shader: "+this); + } + + // optional parameter .. + shaderState.glUniform(gl, new GLUniformData(mgl_NormalMatrix, 3, 3, pmvMatrix.glGetNormalMatrixf())); + + shaderState.glUniform(gl, new GLUniformData(mgl_ColorEnabled, 0)); + shaderState.glUniform(gl, new GLUniformData(mgl_ColorStatic, 4, zero4f)); + shaderState.glUniform(gl, new GLUniformData(mgl_TexCoordEnabled, 1, textureCoordsEnabled)); + shaderState.glUniform(gl, new GLUniformData(mgl_ActiveTexture, activeTextureUnit)); + shaderState.glUniform(gl, new GLUniformData(mgl_ActiveTextureIdx, activeTextureUnit)); + shaderState.glUniform(gl, new GLUniformData(mgl_ShadeModel, 0)); + shaderState.glUniform(gl, new GLUniformData(mgl_CullFace, cullFace)); + for(int i=0; i<MAX_LIGHTS; i++) { + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].ambient", 4, defAmbient)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].diffuse", 4, defDiffuse)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].specular", 4, defSpecular)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].position", 4, defPosition)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotDirection", 3, defSpotDir)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotExponent", defSpotExponent)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].spotCutoff", defSpotCutoff)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].constantAttenuation", defConstantAtten)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].linearAttenuation", defLinearAtten)); + shaderState.glUniform(gl, new GLUniformData(mgl_LightSource+"["+i+"].quadraticAttenuation", defQuadraticAtten)); + } + shaderState.glUniform(gl, new GLUniformData(mgl_LightsEnabled, 1, lightsEnabled)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".ambient", 4, defMatAmbient)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".diffuse", 4, defMatDiffuse)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".specular", 4, defMatSpecular)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".emission", 4, defMatEmission)); + shaderState.glUniform(gl, new GLUniformData(mgl_FrontMaterial+".shininess", defMatShininess)); + + shaderState.glUseProgram(gl, false); + } + + protected static final boolean DEBUG=false; + protected boolean verbose=false; + + protected boolean textureEnabled=false; + protected IntBuffer textureCoordsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); + protected boolean textureCoordsEnabledDirty = false; + protected int activeTextureUnit=0; + + protected int cullFace=-2; // <=0 disabled, 1: front, 2: back (default, but disabled), 3: front & back + + protected boolean lightingEnabled=false; + protected IntBuffer lightsEnabled = Buffers.newDirectIntBuffer(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 }); + protected boolean lightsEnabledDirty = false; + + protected PMVMatrix pmvMatrix; + protected ShaderState shaderState; + protected ShaderProgram shaderProgramColor; + protected ShaderProgram shaderProgramColorTexture; + protected ShaderProgram shaderProgramColorLight; + protected ShaderProgram shaderProgramColorTextureLight; + + // uniforms .. + protected static final String mgl_PMVMatrix = "mgl_PMVMatrix"; // m4fv[3] + protected static final String mgl_NormalMatrix = "mgl_NormalMatrix"; // m4fv + protected static final String mgl_ColorEnabled = "mgl_ColorEnabled"; // 1i + protected static final String mgl_ColorStatic = "mgl_ColorStatic"; // 4fv + + protected static final String mgl_LightSource = "mgl_LightSource"; // struct mgl_LightSourceParameters[MAX_LIGHTS] + protected static final String mgl_FrontMaterial = "mgl_FrontMaterial"; // struct mgl_MaterialParameters + protected static final String mgl_LightsEnabled = "mgl_LightsEnabled"; // int mgl_LightsEnabled[MAX_LIGHTS]; + + protected static final String mgl_ShadeModel = "mgl_ShadeModel"; // 1i + + protected static final String mgl_TexCoordEnabled = "mgl_TexCoordEnabled"; // int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS]; + protected static final String mgl_ActiveTexture = "mgl_ActiveTexture"; // 1i + protected static final String mgl_ActiveTextureIdx = "mgl_ActiveTextureIdx";// 1i + + protected static final String mgl_CullFace = "mgl_CullFace"; // 1i + + protected static final FloatBuffer zero4f = Buffers.newDirectFloatBuffer(new float[] { 0.0f, 0.0f, 0.0f, 0.0f }); + + public static final FloatBuffer defAmbient = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f }); + public static final FloatBuffer defDiffuse = zero4f; + public static final FloatBuffer defSpecular= zero4f; + public static final FloatBuffer defPosition= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 1f, 0f }); + public static final FloatBuffer defSpotDir = Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, -1f }); + public static final float defSpotExponent = 0f; + public static final float defSpotCutoff = 180f; + public static final float defConstantAtten = 1f; + public static final float defLinearAtten = 0f; + public static final float defQuadraticAtten= 0f; + + public static final FloatBuffer defMatAmbient = Buffers.newDirectFloatBuffer(new float[] { 0.2f, 0.2f, 0.2f, 1.0f }); + public static final FloatBuffer defMatDiffuse = Buffers.newDirectFloatBuffer(new float[] { 0.8f, 0.8f, 0.8f, 1.0f }); + public static final FloatBuffer defMatSpecular= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); + public static final FloatBuffer defMatEmission= Buffers.newDirectFloatBuffer(new float[] { 0f, 0f, 0f, 1f}); + public static final float defMatShininess = 0f; + + protected static final String vertexColorFileDef = "FixedFuncColor"; + protected static final String vertexColorLightFileDef = "FixedFuncColorLight"; + protected static final String fragmentColorFileDef = "FixedFuncColor"; + protected static final String fragmentColorTextureFileDef = "FixedFuncColorTexture"; + protected static final String shaderSrcRootDef = "shaders" ; + protected static final String shaderBinRootDef = "shaders/bin" ; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.fp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.fp new file mode 100644 index 000000000..408ff7251 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.fp @@ -0,0 +1,16 @@ +#include es_precision.glsl + +#include mgl_uniform.glsl +#include mgl_varying.glsl + +void main (void) +{ + if( mgl_CullFace > 0 && + ( ( mgl_CullFace == 1 && gl_FrontFacing ) || + ( mgl_CullFace == 2 && !gl_FrontFacing ) || + ( mgl_CullFace == 3 ) ) ) { + discard; + } + gl_FragColor = frontColor; +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.vp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.vp new file mode 100644 index 000000000..346e40196 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColor.vp @@ -0,0 +1,22 @@ +#include es_precision.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_attribute.glsl +#include mgl_varying.glsl + +#include mgl_settexcoord.vp + +void main(void) +{ + if(mgl_ColorEnabled>0) { + frontColor=mgl_Color; + } else { + frontColor=mgl_ColorStatic; + } + + gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex; + + setTexCoord(gl_Position); +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorLight.vp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorLight.vp new file mode 100644 index 000000000..ce203cfb9 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorLight.vp @@ -0,0 +1,70 @@ +#include es_precision.glsl +#include mgl_lightdef.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_uniform_light.glsl +#include mgl_attribute.glsl +#include mgl_varying.glsl + +#include mgl_settexcoord.vp + +void main(void) +{ + vec4 position; + vec3 normal, lightDir, cameraDir, halfDir; + vec4 ambient, diffuse, specular; + float NdotL, NdotHV, dist, attenuation; + int i; + + position = mgl_PMVMatrix[1] * mgl_Vertex; // vertex eye position + + normal = normalize(mgl_NormalMatrix * mgl_Normal); + // cameraPosition: (mgl_PMVMatrix[2] * vec4(0,0,0,1.0)).xyz + cameraDir = normalize( (mgl_PMVMatrix[2] * vec4(0,0,0,1.0)).xyz - mgl_Vertex.xyz ); + + ambient = vec4(0,0,0,0); + diffuse = vec4(0,0,0,0); + specular = vec4(0,0,0,0); + + bool lightEnabled = false; + + for(i=0; i<MAX_LIGHTS; i++) { + if( 0!= mgl_LightsEnabled[i] ) { + lightEnabled = true; + ambient += mgl_LightSource[i].ambient; + lightDir = mgl_LightSource[i].position.xyz - position.xyz; + dist = length(lightDir); + lightDir = normalize(lightDir); + attenuation = 1.0 / ( + mgl_LightSource[i].constantAttenuation+ + mgl_LightSource[i].linearAttenuation * dist + + mgl_LightSource[i].quadraticAttenuation * dist * dist ); + NdotL = max(0.0, dot(normal, lightDir)); + diffuse += mgl_LightSource[i].diffuse * NdotL * attenuation; + if (NdotL != 0.0) { + halfDir = normalize (lightDir + cameraDir); + NdotHV = max(0.0, dot(normal, halfDir)); + specular += mgl_LightSource[i].specular * + pow(NdotHV,mgl_FrontMaterial.shininess) * attenuation; + } + } + } + ambient += mgl_FrontMaterial.ambient; + diffuse *= mgl_FrontMaterial.diffuse; + specular *= mgl_FrontMaterial.specular; + + if(mgl_ColorEnabled>0) { + frontColor=mgl_Color; + } else { + frontColor=mgl_ColorStatic; + } + if( lightEnabled ) { + frontColor *= ambient + diffuse + specular; + } + + gl_Position = mgl_PMVMatrix[0] * position; + + setTexCoord(gl_Position); +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorTexture.fp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorTexture.fp new file mode 100644 index 000000000..86e6ace73 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/FixedFuncColorTexture.fp @@ -0,0 +1,47 @@ + +#include es_precision.glsl +#include mgl_lightdef.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_varying.glsl + +vec4 getTexColor(in sampler2D tex, in int idx) { + vec4 coord; + if(idx==0) { + coord= mgl_TexCoords[0]; + } else if(idx==1) { + coord= mgl_TexCoords[1]; + } else if(idx==2) { + coord= mgl_TexCoords[2]; + } else if(idx==3) { + coord= mgl_TexCoords[3]; + } else if(idx==4) { + coord= mgl_TexCoords[4]; + } else if(idx==5) { + coord= mgl_TexCoords[5]; + } else if(idx==6) { + coord= mgl_TexCoords[6]; + } else { + coord= mgl_TexCoords[7]; + } + return texture2D(tex, coord.st); +} + +void main (void) +{ + if( mgl_CullFace > 0 && + ( ( mgl_CullFace == 1 && gl_FrontFacing ) || + ( mgl_CullFace == 2 && !gl_FrontFacing ) || + ( mgl_CullFace == 3 ) ) ) { + discard; + } + + vec4 texColor = getTexColor(mgl_ActiveTexture,mgl_ActiveTextureIdx); + + if(length(texColor.rgb)>0.0) { + gl_FragColor = vec4(frontColor.rgb*texColor.rgb, frontColor.a) ; + } else { + gl_FragColor = frontColor; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bfp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bfp Binary files differnew file mode 100755 index 000000000..3ebaaee1d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bfp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bvp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bvp Binary files differnew file mode 100755 index 000000000..279ef72c7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColor.bvp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorLight.bvp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorLight.bvp Binary files differnew file mode 100755 index 000000000..5a9deea71 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorLight.bvp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorTexture.bfp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorTexture.bfp Binary files differnew file mode 100755 index 000000000..ce1397fe1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/bin/nvidia/FixedFuncColorTexture.bfp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/es_precision.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/es_precision.glsl new file mode 100644 index 000000000..fd6abe54e --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/es_precision.glsl @@ -0,0 +1,14 @@ +#ifndef es_precision_glsl +#define es_precision_glsl + +#ifdef GL_ES + #define MEDIUMP mediump + #define HIGHP highp + #define LOWP lowp +#else + #define MEDIUMP + #define HIGHP + #define LOWP +#endif + +#endif // es_precision_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_attribute.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_attribute.glsl new file mode 100644 index 000000000..b09bdb05a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_attribute.glsl @@ -0,0 +1,19 @@ + +#ifndef mgl_attribute_glsl +#define mgl_attribute_glsl + +#include es_precision.glsl + +attribute HIGHP vec4 mgl_Vertex; +attribute HIGHP vec3 mgl_Normal; +attribute HIGHP vec4 mgl_Color; +attribute HIGHP vec4 mgl_MultiTexCoord0; +attribute HIGHP vec4 mgl_MultiTexCoord1; +attribute HIGHP vec4 mgl_MultiTexCoord2; +attribute HIGHP vec4 mgl_MultiTexCoord3; +attribute HIGHP vec4 mgl_MultiTexCoord4; +attribute HIGHP vec4 mgl_MultiTexCoord5; +attribute HIGHP vec4 mgl_MultiTexCoord6; +attribute HIGHP vec4 mgl_MultiTexCoord7; + +#endif // mgl_attribute_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_const.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_const.glsl new file mode 100644 index 000000000..1a464a1cb --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_const.glsl @@ -0,0 +1,10 @@ + +#ifndef mgl_const_glsl +#define mgl_const_glsl + +#include es_precision.glsl + +const LOWP int MAX_TEXTURE_UNITS = 8; // <=gl_MaxTextureImageUnits +const LOWP int MAX_LIGHTS = 8; + +#endif // mgl_const_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_lightdef.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_lightdef.glsl new file mode 100644 index 000000000..98e214139 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_lightdef.glsl @@ -0,0 +1,26 @@ +#ifndef mgl_lightdef_glsl +#define mgl_lightdef_glsl + +struct mgl_LightSourceParameters { + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 position; + // vec4 halfVector; // is computed here + vec3 spotDirection; + float spotExponent; + float spotCutoff; // (range: [0.0,90.0], 180.0) + //float spotCosCutoff; // (range: [1.0,0.0],-1.0) + float constantAttenuation; + float linearAttenuation; + float quadraticAttenuation; +}; +struct mgl_MaterialParameters { + vec4 ambient; + vec4 diffuse; + vec4 specular; + vec4 emission; + float shininess; +}; + +#endif // mgl_lightdef_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_settexcoord.vp b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_settexcoord.vp new file mode 100644 index 000000000..1efe328d0 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_settexcoord.vp @@ -0,0 +1,35 @@ +#ifndef mgl_settexcoord_vp +#define mgl_settexcoord_vp + +#include es_precision.glsl + +#include mgl_const.glsl +#include mgl_uniform.glsl +#include mgl_attribute.glsl +#include mgl_varying.glsl + +void setTexCoord(in vec4 defpos) { + /** + * bitwise operator not supported on APX 2500 ES 2.0 + * + mgl_TexCoords[0] = ( 0 != (mgl_TexCoordEnabled & 1) ) ? mgl_MultiTexCoord0 : defpos; + mgl_TexCoords[1] = ( 0 != (mgl_TexCoordEnabled & 2) ) ? mgl_MultiTexCoord1 : defpos; + mgl_TexCoords[2] = ( 0 != (mgl_TexCoordEnabled & 4) ) ? mgl_MultiTexCoord2 : defpos; + mgl_TexCoords[3] = ( 0 != (mgl_TexCoordEnabled & 8) ) ? mgl_MultiTexCoord3 : defpos; + mgl_TexCoords[4] = ( 0 != (mgl_TexCoordEnabled & 16) ) ? mgl_MultiTexCoord4 : defpos; + mgl_TexCoords[5] = ( 0 != (mgl_TexCoordEnabled & 32) ) ? mgl_MultiTexCoord5 : defpos; + mgl_TexCoords[6] = ( 0 != (mgl_TexCoordEnabled & 64) ) ? mgl_MultiTexCoord6 : defpos; + mgl_TexCoords[7] = ( 0 != (mgl_TexCoordEnabled & 128) ) ? mgl_MultiTexCoord7 : defpos; + */ + + mgl_TexCoords[0] = ( 0 != mgl_TexCoordEnabled[0] ) ? mgl_MultiTexCoord0 : defpos; + mgl_TexCoords[1] = ( 0 != mgl_TexCoordEnabled[1] ) ? mgl_MultiTexCoord1 : defpos; + mgl_TexCoords[2] = ( 0 != mgl_TexCoordEnabled[2] ) ? mgl_MultiTexCoord2 : defpos; + mgl_TexCoords[3] = ( 0 != mgl_TexCoordEnabled[3] ) ? mgl_MultiTexCoord3 : defpos; + mgl_TexCoords[4] = ( 0 != mgl_TexCoordEnabled[4] ) ? mgl_MultiTexCoord4 : defpos; + mgl_TexCoords[5] = ( 0 != mgl_TexCoordEnabled[5] ) ? mgl_MultiTexCoord5 : defpos; + mgl_TexCoords[6] = ( 0 != mgl_TexCoordEnabled[6] ) ? mgl_MultiTexCoord6 : defpos; + mgl_TexCoords[7] = ( 0 != mgl_TexCoordEnabled[7] ) ? mgl_MultiTexCoord7 : defpos; +} + +#endif // mgl_settexcoord_vp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform.glsl new file mode 100644 index 000000000..d8b3c7f95 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform.glsl @@ -0,0 +1,18 @@ + +#ifndef mgl_uniform_glsl +#define mgl_uniform_glsl + +#include es_precision.glsl + +#include mgl_const.glsl + +uniform HIGHP mat4 mgl_PMVMatrix[3]; // P, Mv, and Mvi +uniform HIGHP mat3 mgl_NormalMatrix; // transpose(inverse(ModelView)).3x3 +uniform LOWP int mgl_ColorEnabled; +uniform HIGHP vec4 mgl_ColorStatic; +uniform LOWP int mgl_TexCoordEnabled[MAX_TEXTURE_UNITS]; +uniform sampler2D mgl_ActiveTexture; +uniform LOWP int mgl_ActiveTextureIdx; +uniform LOWP int mgl_CullFace; + +#endif // mgl_uniform_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform_light.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform_light.glsl new file mode 100644 index 000000000..0dedb5d5d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_uniform_light.glsl @@ -0,0 +1,15 @@ + +#ifndef mgl_uniform_light_glsl +#define mgl_uniform_light_glsl + +#include es_precision.glsl + +#include mgl_const.glsl +#include mgl_lightdef.glsl + +uniform LOWP int mgl_LightsEnabled[MAX_LIGHTS]; + +uniform mgl_LightSourceParameters mgl_LightSource[MAX_LIGHTS]; +uniform mgl_MaterialParameters mgl_FrontMaterial; + +#endif // mgl_uniform_light_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_varying.glsl b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_varying.glsl new file mode 100644 index 000000000..fc9f735d1 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/mgl_varying.glsl @@ -0,0 +1,12 @@ + +#ifndef mgl_varying_glsl +#define mgl_varying_glsl + +#include es_precision.glsl + +#include mgl_const.glsl + +varying vec4 frontColor; +varying vec4 mgl_TexCoords[MAX_TEXTURE_UNITS]; + +#endif // mgl_varying_glsl diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc-ff.bat b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc-ff.bat new file mode 100755 index 000000000..8a2114e07 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc-ff.bat @@ -0,0 +1,9 @@ +REM +REM You have to call it from the 'shaders' directory, e.g.: +REM scripts\nvidia-apx\glslc-ff.bat +REM +IF !"%JOGLDIR%"==""! GOTO YESPATH +set JOGLDIR=..\lib +:YESPATH + +java -cp %JOGLDIR%\jogl.core.jar;%JOGLDIR%\jogl.gles2.jar;%JOGLDIR%\jogl.fixed.jar;%JOGLDIR%\jogl.sdk.jar com.jogamp.opengl.util.glsl.sdk.CompileShaderNVidia FixedFuncColor.fp FixedFuncColorTexture.fp FixedFuncColorLight.vp FixedFuncColor.vp diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc.bat b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc.bat new file mode 100755 index 000000000..c7ca0a8b7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/fixedfunc/impl/shaders/scripts/nvidia-apx/glslc.bat @@ -0,0 +1,9 @@ +REM +REM You have to call it from the 'shaders' directory, e.g.: +REM scripts\nvidia-apx\glslc.bat <FileName> +REM +IF !"%JOGLDIR%"==""! GOTO YESPATH +set JOGLDIR=..\lib +:YESPATH + +java -cp %JOGLDIR%\jogl.core.jar;%JOGLDIR%\jogl.gles2.jar;%JOGLDIR%\jogl.fixed.jar;%JOGLDIR%\jogl.sdk.jar com.jogamp.opengl.util.glsl.sdk.CompileShaderNVidia %1 diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java new file mode 100755 index 000000000..a0eed50ea --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShader.java @@ -0,0 +1,185 @@ +package com.jogamp.opengl.util.glsl.sdk; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.glsl.*; + +import java.io.*; +import java.net.*; + +/** + * Precompiles a shader into a vendor binary format. Input is the + * resource name of the shader, such as + * "com/jogamp/opengl/impl/glsl/fixed/shader/a.fp". + * Output is "com/jogamp/opengl/impl/glsl/fixed/shader/bin/nvidia/a.bfp". + * + * All path and suffixes are determined by the ShaderCode class, + * which ensures runtime compatibility. + * + * @see com.jogamp.opengl.util.glsl.ShaderCode + */ + +public abstract class CompileShader { + + public abstract int getBinaryFormat(); + + public abstract File getSDKCompilerDir(); + + public abstract String getVertexShaderCompiler(); + + public abstract String getFragmentShaderCompiler(); + + public void processOneShader(String resourceName) + throws IOException, UnsupportedEncodingException, InterruptedException + { + int type = -1; + String outName=null; + int suffixLen = -1; + if(resourceName.endsWith(ShaderCode.getFileSuffix(false, GL2ES2.GL_FRAGMENT_SHADER))) { + suffixLen = 2; + type = GL2ES2.GL_FRAGMENT_SHADER; + } else if(resourceName.endsWith(".frag")) { + suffixLen = 4; + type = GL2ES2.GL_FRAGMENT_SHADER; + } else if(resourceName.endsWith(ShaderCode.getFileSuffix(false, GL2ES2.GL_VERTEX_SHADER))) { + suffixLen = 2; + type = GL2ES2.GL_VERTEX_SHADER; + } else if(resourceName.endsWith(".vert")) { + suffixLen = 4; + type = GL2ES2.GL_VERTEX_SHADER; + } + String justName = basename(resourceName); + outName = justName.substring(0, justName.length() - suffixLen) + + ShaderCode.getFileSuffix(true, type); + URL resourceURL = Locator.getResource(null, resourceName); + String dirName = dirname(resourceURL.getPath()); + + outName = dirName + File.separator + "bin" + File.separator + + ShaderCode.getBinarySubPath(getBinaryFormat()) + File.separator + + outName; + processOneShader(resourceName, outName, type); + } + + public void processOneShader(String resourceName, String outName, int type) + throws IOException, UnsupportedEncodingException, InterruptedException + { + URL resourceURL = Locator.getResource(null, resourceName); + String dirName = dirname(resourceURL.getPath()); + + String shader = ShaderCode.readShaderSource(null, resourceName); + if(null==shader) { + System.err.println("Can't find shader source " + resourceName + " - ignored"); + return; + } + System.err.println("Preprocessing: "+ resourceName+", in dir: "+dirName); + String justName = basename(resourceName); + String processor; + switch (type) { + case GL2ES2.GL_VERTEX_SHADER: + processor = getVertexShaderCompiler(); + break; + case GL2ES2.GL_FRAGMENT_SHADER: + processor = getFragmentShaderCompiler(); + break; + default: + throw new GLException("Unknown shader type: "+type); + } + File outputFile = new File(outName); + + // Write shader to a file in java.io.tmpdir + File tmpDir = new File(dirName+File.separator+"tmp"); + tmpDir.mkdirs(); + File tmpFile = new File(tmpDir, justName); + Writer writer = new BufferedWriter(new FileWriter(tmpFile)); + writer.write(shader, 0, shader.length()); + writer.flush(); + writer.close(); + System.err.println("Preprocessed: "+ tmpFile.getAbsolutePath()); + + File processorDir = getSDKCompilerDir(); + + System.err.println("SDK: "+ processorDir.getAbsolutePath() + ", compiler: "+processor); + + System.err.println("Output: "+ outputFile.getAbsolutePath()); + + // Run the tool + Process process = Runtime.getRuntime().exec(new String[] { + processorDir.getAbsolutePath() + File.separator + processor, + tmpFile.getAbsolutePath(), + outputFile.getAbsolutePath() + }); // , null, processorDir); + new StreamMonitor(process.getInputStream()); + new StreamMonitor(process.getErrorStream()); + process.waitFor(); + // Delete the temporary file + // tmpFile.delete(); + } + + protected static String basename(String path) { + int lastSlash = path.lastIndexOf("/"); + if (lastSlash < 0) { + lastSlash = path.lastIndexOf("\\"); + } + String basename; + if (lastSlash < 0) { + basename = path; + } else { + basename = path.substring(lastSlash + 1); + } + return basename; + } + + protected static String dirname(String path) { + int lastSlash = path.lastIndexOf("/"); + if (lastSlash < 0) { + lastSlash = path.lastIndexOf("\\"); + } + String dirname; + if (lastSlash < 0) { + dirname = new String(); + } else { + dirname = path.substring(0, lastSlash + 1); + } + return dirname; + } + + public void run(String[] args) { + try { + for (int i = 0; i < args.length; i++) { + processOneShader(args[i]); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static class StreamMonitor implements Runnable { + private InputStream istream; + public StreamMonitor(InputStream stream) { + istream = stream; + new Thread(this, "Output Reader Thread").start(); + } + + public void run() + { + byte[] buffer = new byte[4096]; + try { + int numRead = 0; + do { + numRead = istream.read(buffer); + if (numRead > 0) { + System.out.write(buffer, 0, numRead); + System.out.flush(); + } + } while (numRead >= 0); + } + catch (IOException e) { + try { + istream.close(); + } catch (IOException e2) { + } + // Should allow clean exit when process shuts down + } + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java new file mode 100755 index 000000000..8eb9ef579 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/sdk/CompileShaderNVidia.java @@ -0,0 +1,53 @@ +package com.jogamp.opengl.util.glsl.sdk; + +import javax.media.opengl.*; + +import java.io.*; + +/** Precompiles a shader into NVidia binary format. Input is the + resource name of the shader, such as + "com/jogamp/opengl/impl/glsl/fixed/shader/a.fp". + Output is "com/jogamp/opengl/impl/glsl/fixed/shader/bin/nvidia/a.bfp". */ + +public class CompileShaderNVidia extends CompileShader { + private static final String NVAPSDK; + + static { + String nvapSDKProp = System.getProperty("NVAPSDK"); + if (nvapSDKProp != null) { + NVAPSDK = nvapSDKProp; + } else { + NVAPSDK = "C:\\nvap_sdk_0_3_x"; + } + } + + public int getBinaryFormat() { + return GLES2.GL_NVIDIA_PLATFORM_BINARY_NV; + } + + public File getSDKCompilerDir() { + File compilerDir = new File( NVAPSDK + File.separator + "tools" + File.separator ); + File compilerFile = new File( compilerDir, getVertexShaderCompiler()); + if(!compilerFile.exists()) { + compilerDir = new File( NVAPSDK ); + compilerFile = new File( compilerDir, getVertexShaderCompiler()); + } + if(!compilerFile.exists()) { + throw new GLException("Can't find compiler: "+getVertexShaderCompiler() + " in : " + + NVAPSDK+", "+NVAPSDK + File.separator + "tools"); + } + return compilerDir; + } + + public String getVertexShaderCompiler() { + return "glslv.bat"; + } + + public String getFragmentShaderCompiler() { + return "glslf.bat"; + } + + public static void main(String[] args) { + new CompileShaderNVidia().run(args); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java new file mode 100755 index 000000000..7b6a1b479 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/BackingStoreManager.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +/** This interface must be implemented by the end user and is called + in response to events like addition of rectangles into the + RectanglePacker. It is used both when a full re-layout must be + done as well as when the data in the backing store must be copied + to a new one. */ + +public interface BackingStoreManager { + public Object allocateBackingStore(int w, int h); + public void deleteBackingStore(Object backingStore); + + /** Indication whether this BackingStoreManager supports compaction; + in other words, the allocation of a new backing store and + movement of the contents of the backing store from the old to + the new one. If it does not, then RectanglePacker.add() may + throw an exception if additionFailed() can not make enough room + available. If an implementation returns false, this also implies + that the backing store can not grow, so that preExpand() will + never be called. */ + public boolean canCompact(); + + /** Notification that expansion of the backing store is about to be + done due to addition of the given rectangle. Gives the manager a + chance to do some compaction and potentially remove old entries + from the backing store, if it acts like a least-recently-used + cache. This method receives as argument the number of attempts + so far to add the given rectangle. Manager should return true if + the RectanglePacker should retry the addition (which may result + in this method being called again, with an increased attempt + number) or false if the RectanglePacker should just expand the + backing store. The caller should not call RectanglePacker.add() + in its preExpand() method. */ + public boolean preExpand(Rect cause, int attemptNumber); + + /** Notification that addition of the given Rect failed because a + maximum size was set in the RectanglePacker and the backing + store could not be expanded, or because compaction (and, + therefore, implicitly expansion) was not supported. Should + return false if the manager can do nothing more to handle the + failed addition, which will cause a RuntimeException to be + thrown from the RectanglePacker. */ + public boolean additionFailed(Rect cause, int attemptNumber); + + /** Notification that movement is starting. */ + public void beginMovement(Object oldBackingStore, Object newBackingStore); + + /** Tells the manager to move the contents of the given rect from + the old location on the old backing store to the new location on + the new backing store. The backing stores can be identical in + the case of compacting the existing backing store instead of + reallocating it. */ + public void move(Object oldBackingStore, + Rect oldLocation, + Object newBackingStore, + Rect newLocation); + + /** Notification that movement is ending. */ + public void endMovement(Object oldBackingStore, Object newBackingStore); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java new file mode 100755 index 000000000..5ba3f7330 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/Level.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +import java.util.*; + +public class Level { + private int width; + private int height; + private int yPos; + private LevelSet holder; + + private List/*<Rect>*/ rects = new ArrayList/*<Rect>*/(); + private List/*<Rect>*/ freeList; + private int nextAddX; + + static class RectXComparator implements Comparator { + public int compare(Object o1, Object o2) { + Rect r1 = (Rect) o1; + Rect r2 = (Rect) o2; + return r1.x() - r2.x(); + } + + public boolean equals(Object obj) { + return this == obj; + } + } + private static final Comparator rectXComparator = new RectXComparator(); + + public Level(int width, int height, int yPos, LevelSet holder) { + this.width = width; + this.height = height; + this.yPos = yPos; + this.holder = holder; + } + + public int w() { return width; } + public int h() { return height; } + public int yPos() { return yPos; } + + /** Tries to add the given rectangle to this level only allowing + non-disruptive changes like trivial expansion of the last level + in the RectanglePacker and allocation from the free list. More + disruptive changes like compaction of the level must be + requested explicitly. */ + public boolean add(Rect rect) { + if (rect.h() > height) { + // See whether it's worth trying to expand vertically + if (nextAddX + rect.w() > width) { + return false; + } + + // See whether we're the last level and can expand + if (!holder.canExpand(this, rect.h())) { + return false; + } + + // Trivially expand and try the allocation + holder.expand(this, height, rect.h()); + height = rect.h(); + } + + // See whether we can add at the end + if (nextAddX + rect.w() <= width) { + rect.setPosition(nextAddX, yPos); + rects.add(rect); + nextAddX += rect.w(); + return true; + } + + // See whether we can add from the free list + if (freeList != null) { + Rect candidate = null; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + if (cur.canContain(rect)) { + candidate = cur; + break; + } + } + + if (candidate != null) { + // Remove the candidate from the free list + freeList.remove(candidate); + // Set up and add the real rect + rect.setPosition(candidate.x(), candidate.y()); + rects.add(rect); + // Re-add any remaining free space + if (candidate.w() > rect.w()) { + candidate.setPosition(candidate.x() + rect.w(), candidate.y()); + candidate.setSize(candidate.w() - rect.w(), height); + freeList.add(candidate); + } + + coalesceFreeList(); + + return true; + } + } + + return false; + } + + /** Removes the given Rect from this Level. */ + public boolean remove(Rect rect) { + if (!rects.remove(rect)) + return false; + + // If this is the rightmost rectangle, instead of adding its space + // to the free list, we can just decrease the nextAddX + if (rect.maxX() + 1 == nextAddX) { + nextAddX -= rect.w(); + } else { + if (freeList == null) { + freeList = new ArrayList/*<Rect>*/(); + } + freeList.add(new Rect(rect.x(), rect.y(), rect.w(), height, null)); + coalesceFreeList(); + } + + return true; + } + + /** Indicates whether this Level contains no rectangles. */ + public boolean isEmpty() { + return rects.isEmpty(); + } + + /** Indicates whether this Level could satisfy an allocation request + if it were compacted. */ + public boolean couldAllocateIfCompacted(Rect rect) { + if (rect.h() > height) + return false; + if (freeList == null) + return false; + int freeListWidth = 0; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + freeListWidth += cur.w(); + } + // Add on the remaining space at the end + freeListWidth += (width - nextAddX); + return (freeListWidth >= rect.w()); + } + + public void compact(Object backingStore, BackingStoreManager manager) { + Collections.sort(rects, rectXComparator); + int nextCompactionDest = 0; + manager.beginMovement(backingStore, backingStore); + for (Iterator iter = rects.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + if (cur.x() != nextCompactionDest) { + manager.move(backingStore, cur, + backingStore, new Rect(nextCompactionDest, cur.y(), cur.w(), cur.h(), null)); + cur.setPosition(nextCompactionDest, cur.y()); + } + nextCompactionDest += cur.w(); + } + nextAddX = nextCompactionDest; + freeList.clear(); + manager.endMovement(backingStore, backingStore); + } + + public Iterator iterator() { + return rects.iterator(); + } + + /** Visits all Rects contained in this Level. */ + public void visit(RectVisitor visitor) { + for (Iterator iter = rects.iterator(); iter.hasNext(); ) { + Rect rect = (Rect) iter.next(); + visitor.visit(rect); + } + } + + /** Updates the references to the Rect objects in this Level with + the "next locations" of those Rects. This is actually used to + update the new Rects in a newly laid-out LevelSet with the + original Rects. */ + public void updateRectangleReferences() { + for (int i = 0; i < rects.size(); i++) { + Rect cur = (Rect) rects.get(i); + Rect next = cur.getNextLocation(); + next.setPosition(cur.x(), cur.y()); + if (cur.w() != next.w() || cur.h() != next.h()) + throw new RuntimeException("Unexpected disparity in rectangle sizes during updateRectangleReferences"); + rects.set(i, next); + } + } + + private void coalesceFreeList() { + if (freeList == null) + return; + if (freeList.isEmpty()) + return; + + // Try to coalesce adjacent free blocks in the free list + Collections.sort(freeList, rectXComparator); + int i = 0; + while (i < freeList.size() - 1) { + Rect r1 = (Rect) freeList.get(i); + Rect r2 = (Rect) freeList.get(i+1); + if (r1.maxX() + 1 == r2.x()) { + // Coalesce r1 and r2 into one block + freeList.remove(i+1); + r1.setSize(r1.w() + r2.w(), r1.h()); + } else { + ++i; + } + } + // See whether the last block bumps up against the addition point + Rect last = (Rect) freeList.get(freeList.size() - 1); + if (last.maxX() + 1 == nextAddX) { + nextAddX -= last.w(); + freeList.remove(freeList.size() - 1); + } + if (freeList.isEmpty()) { + freeList = null; + } + } + + //---------------------------------------------------------------------- + // Debugging functionality + // + + public void dumpFreeSpace() { + int freeListWidth = 0; + for (Iterator iter = freeList.iterator(); iter.hasNext(); ) { + Rect cur = (Rect) iter.next(); + System.err.println(" Free rectangle at " + cur); + freeListWidth += cur.w(); + } + // Add on the remaining space at the end + System.err.println(" Remaining free space " + (width - nextAddX)); + freeListWidth += (width - nextAddX); + System.err.println(" Total free space " + freeListWidth); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java new file mode 100755 index 000000000..6783aec3b --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/LevelSet.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +import java.util.*; + +/** Manages a list of Levels; this is the core data structure + contained within the RectanglePacker and encompasses the storage + algorithm for the contained Rects. */ + +public class LevelSet { + // Maintained in sorted order by increasing Y coordinate + private List/*<Level>*/ levels = new ArrayList/*<Level>*/(); + private int nextAddY; + private int w; + private int h; + + /** A LevelSet manages all of the backing store for a region of a + specified width and height. */ + public LevelSet(int w, int h) { + this.w = w; + this.h = h; + } + + public int w() { return w; } + public int h() { return h; } + + /** Returns true if the given rectangle was successfully added to + the LevelSet given its current dimensions, false if not. Caller + is responsible for performing compaction, expansion, etc. as a + consequence. */ + public boolean add(Rect rect) { + if (rect.w() > w) + return false; + + // Go in reverse order through the levels seeing whether we can + // trivially satisfy the allocation request + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.add(rect)) + return true; + } + + // See whether compaction could satisfy this allocation. This + // increases the computational complexity of the addition process, + // but prevents us from expanding unnecessarily. + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.couldAllocateIfCompacted(rect)) + return false; + } + + // OK, we need to either add a new Level or expand the backing + // store. Try to add a new Level. + if (nextAddY + rect.h() > h) + return false; + + Level newLevel = new Level(w, rect.h(), nextAddY, this); + levels.add(newLevel); + nextAddY += rect.h(); + boolean res = newLevel.add(rect); + if (!res) + throw new RuntimeException("Unexpected failure in addition to new Level"); + return true; + } + + /** Removes the given Rect from this LevelSet. */ + public boolean remove(Rect rect) { + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.remove(rect)) + return true; + } + + return false; + } + + /** Allocates the given Rectangle, performing compaction of a Level + if necessary. This is the correct fallback path to {@link + #add(Rect)} above. Returns true if allocated successfully, false + otherwise (indicating the need to expand the backing store). */ + public boolean compactAndAdd(Rect rect, + Object backingStore, + BackingStoreManager manager) { + for (int i = levels.size() - 1; i >= 0; --i) { + Level level = (Level) levels.get(i); + if (level.couldAllocateIfCompacted(rect)) { + level.compact(backingStore, manager); + boolean res = level.add(rect); + if (!res) + throw new RuntimeException("Unexpected failure to add after compaction"); + return true; + } + } + + return false; + } + + /** Indicates whether it's legal to trivially increase the height of + the given Level. This is only possible if it's the last Level + added and there's enough room in the backing store. */ + public boolean canExpand(Level level, int height) { + if (levels.isEmpty()) + return false; // Should not happen + if (levels.get(levels.size() - 1) == level && + (h - nextAddY >= height - level.h())) + return true; + return false; + } + + public void expand(Level level, int oldHeight, int newHeight) { + nextAddY += (newHeight - oldHeight); + } + + /** Gets the used height of the levels in this LevelSet. */ + public int getUsedHeight() { + return nextAddY; + } + + /** Sets the height of this LevelSet. It is only legal to reduce the + height to greater than or equal to the currently used height. */ + public void setHeight(int height) throws IllegalArgumentException { + if (height < getUsedHeight()) { + throw new IllegalArgumentException("May not reduce height below currently used height"); + } + h = height; + } + + /** Returns the vertical fragmentation ratio of this LevelSet. This + is defined as the ratio of the sum of the heights of all + completely empty Levels divided by the overall used height of + the LevelSet. A high vertical fragmentation ratio indicates that + it may be profitable to perform a compaction. */ + public float verticalFragmentationRatio() { + int freeHeight = 0; + int usedHeight = getUsedHeight(); + if (usedHeight == 0) + return 0.0f; + for (Iterator iter = iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + if (level.isEmpty()) { + freeHeight += level.h(); + } + } + return (float) freeHeight / (float) usedHeight; + } + + public Iterator iterator() { + return levels.iterator(); + } + + /** Visits all Rects contained in this LevelSet. */ + public void visit(RectVisitor visitor) { + for (Iterator iter = levels.iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + level.visit(visitor); + } + } + + /** Updates the references to the Rect objects in this LevelSet with + the "next locations" of those Rects. This is actually used to + update the new Rects in a newly laid-out LevelSet with the + original Rects. */ + public void updateRectangleReferences() { + for (Iterator iter = levels.iterator(); iter.hasNext(); ) { + Level level = (Level) iter.next(); + level.updateRectangleReferences(); + } + } + + /** Clears out all Levels stored in this LevelSet. */ + public void clear() { + levels.clear(); + nextAddY = 0; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java new file mode 100755 index 000000000..6206c4a11 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/Rect.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +/** Represents a rectangular region on the backing store. The edges of + the rectangle are the infinitely thin region between adjacent + pixels on the screen. The origin of the rectangle is its + upper-left corner. It is inclusive of the pixels on the top and + left edges and exclusive of the pixels on the bottom and right + edges. For example, a rect at position (0, 0) and of size (1, 1) + would include only the pixel at (0, 0). <P> + + Negative coordinates and sizes are not supported, since they make + no sense in the context of the packer, which deals only with + positively sized regions. <P> + + This class contains a user data field for efficient hookup to + external data structures as well as enough other hooks to + efficiently plug into the rectangle packer. */ + +public class Rect { + private int x; + private int y; + private int w; + private int h; + + // The level we're currently installed in in the parent + // RectanglePacker, or null if not hooked in to the table yet + private Level level; + + // The user's object this rectangle represents. + private Object userData; + + // Used transiently during re-layout of the backing store (when + // there is no room left due either to fragmentation or just being + // out of space) + private Rect nextLocation; + + public Rect() { + this(null); + } + + public Rect(Object userData) { + this(0, 0, 0, 0, userData); + } + + public Rect(int x, int y, int w, int h, Object userData) { + setPosition(x, y); + setSize(w, h); + setUserData(userData); + } + + public int x() { return x; } + public int y() { return y; } + public int w() { return w; } + public int h() { return h; } + public Object getUserData() { return userData; } + public Rect getNextLocation() { return nextLocation; } + + public void setPosition(int x, int y) { + if (x < 0) + throw new IllegalArgumentException("Negative x"); + if (y < 0) + throw new IllegalArgumentException("Negative y"); + this.x = x; + this.y = y; + } + + public void setSize(int w, int h) throws IllegalArgumentException { + if (w < 0) + throw new IllegalArgumentException("Negative width"); + if (h < 0) + throw new IllegalArgumentException("Negative height"); + this.w = w; + this.h = h; + } + + public void setUserData(Object obj) { userData = obj; } + public void setNextLocation(Rect nextLocation) { this.nextLocation = nextLocation; } + + // Helpers for computations. + + /** Returns the maximum x-coordinate contained within this + rectangle. Note that this returns a different result than Java + 2D's rectangles; for a rectangle of position (0, 0) and size (1, + 1) this will return 0, not 1. Returns -1 if the width of this + rectangle is 0. */ + public int maxX() { + if (w() < 1) + return -1; + return x() + w() - 1; + } + + /** Returns the maximum y-coordinate contained within this + rectangle. Note that this returns a different result than Java + 2D's rectangles; for a rectangle of position (0, 0) and size (1, + 1) this will return 0, not 1. Returns -1 if the height of this + rectangle is 0. */ + public int maxY() { + if (h() < 1) + return -1; + return y() + h() - 1; + } + + public boolean canContain(Rect other) { + return (w() >= other.w() && + h() >= other.h()); + } + + public String toString() { + return "[Rect x: " + x() + " y: " + y() + " w: " + w() + " h: " + h() + "]"; + } + + // Unclear whether it's a good idea to override hashCode and equals + // for these objects + /* + public boolean equals(Object other) { + if (other == null || (!(other instanceof Rect))) { + return false; + } + + Rect r = (Rect) other; + return (this.x() == r.x() && + this.y() == r.y() && + this.w() == r.w() && + this.h() == r.h()); + } + + public int hashCode() { + return (x + y * 13 + w * 17 + h * 23); + } + */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java new file mode 100755 index 000000000..49cfc82e6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectVisitor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +/** Iteration construct without exposing the internals of the + RectanglePacker and without implementing a complex Iterator. */ + +public interface RectVisitor { + public void visit(Rect rect); +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java new file mode 100755 index 000000000..1496a04a6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/RectanglePacker.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.packrect; + +import java.util.*; + +/** Packs rectangles supplied by the user (typically representing + image regions) into a larger backing store rectangle (typically + representing a large texture). Supports automatic compaction of + the space on the backing store, and automatic expansion of the + backing store, when necessary. */ + +public class RectanglePacker { + private BackingStoreManager manager; + private Object backingStore; + private LevelSet levels; + private float EXPANSION_FACTOR = 0.5f; + private float SHRINK_FACTOR = 0.3f; + + private int initialWidth; + private int initialHeight; + + private int maxWidth = -1; + private int maxHeight = -1; + + static class RectHComparator implements Comparator { + public int compare(Object o1, Object o2) { + Rect r1 = (Rect) o1; + Rect r2 = (Rect) o2; + return r2.h() - r1.h(); + } + + public boolean equals(Object obj) { + return this == obj; + } + } + private static final Comparator rectHComparator = new RectHComparator(); + + public RectanglePacker(BackingStoreManager manager, + int initialWidth, + int initialHeight) { + this.manager = manager; + levels = new LevelSet(initialWidth, initialHeight); + this.initialWidth = initialWidth; + this.initialHeight = initialHeight; + } + + public Object getBackingStore() { + if (backingStore == null) { + backingStore = manager.allocateBackingStore(levels.w(), levels.h()); + } + + return backingStore; + } + + /** Sets up a maximum width and height for the backing store. These + are optional and if not specified the backing store will grow as + necessary. Setting up a maximum width and height introduces the + possibility that additions will fail; these are handled with the + BackingStoreManager's allocationFailed notification. */ + public void setMaxSize(int maxWidth, int maxHeight) { + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + } + + /** Decides upon an (x, y) position for the given rectangle (leaving + its width and height unchanged) and places it on the backing + store. May provoke re-layout of other Rects already added. If + the BackingStoreManager does not support compaction, and {@link + BackingStoreManager#preExpand BackingStoreManager.preExpand} + does not clear enough space for the incoming rectangle, then + this method will throw a RuntimeException. */ + public void add(Rect rect) throws RuntimeException { + // Allocate backing store if we don't have any yet + if (backingStore == null) + backingStore = manager.allocateBackingStore(levels.w(), levels.h()); + + int attemptNumber = 0; + boolean tryAgain = false; + + do { + // Try to allocate + if (levels.add(rect)) + return; + + if (manager.canCompact()) { + // Try to allocate with horizontal compaction + if (levels.compactAndAdd(rect, backingStore, manager)) + return; + // Let the manager have a chance at potentially evicting some entries + tryAgain = manager.preExpand(rect, attemptNumber++); + } else { + tryAgain = manager.additionFailed(rect, attemptNumber++); + } + } while (tryAgain); + + if (!manager.canCompact()) { + throw new RuntimeException("BackingStoreManager does not support compaction or expansion, and didn't clear space for new rectangle"); + } + + compactImpl(rect); + + // Retry the addition of the incoming rectangle + add(rect); + // Done + } + + /** Removes the given rectangle from this RectanglePacker. */ + public void remove(Rect rect) { + levels.remove(rect); + } + + /** Visits all Rects contained in this RectanglePacker. */ + public void visit(RectVisitor visitor) { + levels.visit(visitor); + } + + /** Returns the vertical fragmentation ratio of this + RectanglePacker. This is defined as the ratio of the sum of the + heights of all completely empty Levels divided by the overall + used height of the LevelSet. A high vertical fragmentation ratio + indicates that it may be profitable to perform a compaction. */ + public float verticalFragmentationRatio() { + return levels.verticalFragmentationRatio(); + } + + /** Forces a compaction cycle, which typically results in allocating + a new backing store and copying all entries to it. */ + public void compact() { + compactImpl(null); + } + + // The "cause" rect may be null + private void compactImpl(Rect cause) { + // Have to either expand, compact or both. Need to figure out what + // direction to go. Prefer to expand vertically. Expand + // horizontally only if rectangle being added is too wide. FIXME: + // may want to consider rebalancing the width and height to be + // more equal if it turns out we keep expanding in the vertical + // direction. + boolean done = false; + int newWidth = levels.w(); + int newHeight = levels.h(); + LevelSet nextLevelSet = null; + int attemptNumber = 0; + boolean needAdditionFailureNotification = false; + + while (!done) { + if (cause != null) { + if (cause.w() > newWidth) { + newWidth = cause.w(); + } else { + newHeight = (int) (newHeight * (1.0f + EXPANSION_FACTOR)); + } + } + + // Clamp to maximum values + needAdditionFailureNotification = false; + if (maxWidth > 0 && newWidth > maxWidth) { + newWidth = maxWidth; + needAdditionFailureNotification = true; + } + if (maxHeight > 0 && newHeight > maxHeight) { + newHeight = maxHeight; + needAdditionFailureNotification = true; + } + + nextLevelSet = new LevelSet(newWidth, newHeight); + + // Make copies of all existing rectangles + List/*<Rect>*/ newRects = new ArrayList/*<Rect>*/(); + for (Iterator i1 = levels.iterator(); i1.hasNext(); ) { + Level level = (Level) i1.next(); + for (Iterator i2 = level.iterator(); i2.hasNext(); ) { + Rect cur = (Rect) i2.next(); + Rect newRect = new Rect(0, 0, cur.w(), cur.h(), null); + cur.setNextLocation(newRect); + // Hook up the reverse mapping too for easier replacement + newRect.setNextLocation(cur); + newRects.add(newRect); + } + } + // Sort them by decreasing height (note: this isn't really + // guaranteed to improve the chances of a successful layout) + Collections.sort(newRects, rectHComparator); + // Try putting all of these rectangles into the new level set + done = true; + for (Iterator iter = newRects.iterator(); iter.hasNext(); ) { + if (!nextLevelSet.add((Rect) iter.next())) { + done = false; + break; + } + } + + if (done && cause != null) { + // Try to add the new rectangle as well + if (nextLevelSet.add(cause)) { + // We're OK + } else { + done = false; + } + } + + // Don't send addition failure notifications if we're only doing + // a compaction + if (!done && needAdditionFailureNotification && cause != null) { + manager.additionFailed(cause, attemptNumber); + } + ++attemptNumber; + } + + // See whether the implicit compaction that just occurred has + // yielded excess empty space. + if (nextLevelSet.getUsedHeight() > 0 && + nextLevelSet.getUsedHeight() < nextLevelSet.h() * SHRINK_FACTOR) { + int shrunkHeight = Math.max(initialHeight, + (int) (nextLevelSet.getUsedHeight() * (1.0f + EXPANSION_FACTOR))); + if (maxHeight > 0 && shrunkHeight > maxHeight) { + shrunkHeight = maxHeight; + } + nextLevelSet.setHeight(shrunkHeight); + } + + // If we temporarily added the new rectangle to the new LevelSet, + // take it out since we don't "really" add it here but in add(), above + if (cause != null) { + nextLevelSet.remove(cause); + } + + // OK, now we have a new layout and a mapping from the old to the + // new locations of rectangles on the backing store. Allocate a + // new backing store, move the contents over and deallocate the + // old one. + Object newBackingStore = manager.allocateBackingStore(nextLevelSet.w(), + nextLevelSet.h()); + manager.beginMovement(backingStore, newBackingStore); + for (Iterator i1 = levels.iterator(); i1.hasNext(); ) { + Level level = (Level) i1.next(); + for (Iterator i2 = level.iterator(); i2.hasNext(); ) { + Rect cur = (Rect) i2.next(); + manager.move(backingStore, cur, + newBackingStore, cur.getNextLocation()); + } + } + // Replace references to temporary rectangles with original ones + nextLevelSet.updateRectangleReferences(); + manager.endMovement(backingStore, newBackingStore); + // Now delete the old backing store + manager.deleteBackingStore(backingStore); + // Update to new versions of backing store and LevelSet + backingStore = newBackingStore; + levels = nextLevelSet; + } + + /** Clears all Rects contained in this RectanglePacker. */ + public void clear() { + levels.clear(); + } + + /** Disposes the backing store allocated by the + BackingStoreManager. This RectanglePacker may no longer be used + after calling this method. */ + public void dispose() { + if (backingStore != null) + manager.deleteBackingStore(backingStore); + backingStore = null; + levels = null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/packrect/package.html b/src/jogl/classes/com/jogamp/opengl/util/packrect/package.html new file mode 100755 index 000000000..c1c5db477 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/packrect/package.html @@ -0,0 +1,9 @@ +<BODY> +This package implements a rectangle packing algorithm suitable for +tracking the placement of multiple rectangles inside a larger one. It +is useful for cases such as placing the contents of multiple windows +on a larger backing store texture for a compositing window manager; +placing multiple rasterized strings in a texture map for quick +rendering to the screen; and many other situations where it is useful +to carve up a larger texture into smaller pieces dynamically. <P> +</BODY> diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java new file mode 100755 index 000000000..57ac0d45a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/Texture.java @@ -0,0 +1,1120 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util.texture; + +import java.nio.*; +import java.security.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import javax.media.nativewindow.NativeWindowFactory; +import com.jogamp.opengl.impl.*; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.spi.*; + +/** + * Represents an OpenGL texture object. Contains convenience routines + * for enabling/disabling OpenGL texture state, binding this texture, + * and computing texture coordinates for both the entire image as well + * as a sub-image. + * + * <p><a name="nonpow2"><b>Non-power-of-two restrictions</b></a> + * <br> When creating an OpenGL texture object, the Texture class will + * attempt to leverage the <a + * href="http://www.opengl.org/registry/specs/ARB/texture_non_power_of_two.txt">GL_ARB_texture_non_power_of_two</a> + * and <a + * href="http://www.opengl.org/registry/specs/ARB/texture_rectangle.txt">GL_ARB_texture_rectangle</a> + * extensions (in that order) whenever possible. If neither extension + * is available, the Texture class will simply upload a non-pow2-sized + * image into a standard pow2-sized texture (without any special + * scaling). Since the choice of extension (or whether one is used at + * all) depends on the user's machine configuration, developers are + * recommended to use {@link #getImageTexCoords} and {@link + * #getSubImageTexCoords}, as those methods will calculate the + * appropriate texture coordinates for the situation. + * + * <p>One caveat in this approach is that certain texture wrap modes + * (e.g. <code>GL_REPEAT</code>) are not legal when the GL_ARB_texture_rectangle + * extension is in use. Another issue to be aware of is that in the + * default pow2 scenario, if the original image does not have pow2 + * dimensions, then wrapping may not work as one might expect since + * the image does not extend to the edges of the pow2 texture. If + * texture wrapping is important, it is recommended to use only + * pow2-sized images with the Texture class. + * + * <p><a name="perftips"><b>Performance Tips</b></a> + * <br> For best performance, try to avoid calling {@link #enable} / + * {@link #bind} / {@link #disable} any more than necessary. For + * example, applications using many Texture objects in the same scene + * may want to reduce the number of calls to both {@link #enable} and + * {@link #disable}. To do this it is necessary to call {@link + * #getTarget} to make sure the OpenGL texture target is the same for + * all of the Texture objects in use; non-power-of-two textures using + * the GL_ARB_texture_rectangle extension use a different target than + * power-of-two textures using the GL_TEXTURE_2D target. Note that + * when switching between textures it is necessary to call {@link + * #bind}, but when drawing many triangles all using the same texture, + * for best performance only one call to {@link #bind} should be made. + * + * <p><a name="premult"><b>Alpha premultiplication and blending</b></a> + * <br> The mathematically correct way to perform blending in OpenGL + * (with the SrcOver "source over destination" mode, or any other + * Porter-Duff rule) is to use "premultiplied color components", which + * means the R/G/ B color components have already been multiplied by + * the alpha value. To make things easier for developers, the Texture + * class will automatically convert non-premultiplied image data into + * premultiplied data when storing it into an OpenGL texture. As a + * result, it is important to use the correct blending function; for + * example, the SrcOver rule is expressed as: +<pre> + gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); +</pre> + * Also, when using a texture function like <code>GL_MODULATE</code> where + * the current color plays a role, it is important to remember to make + * sure that the color is specified in a premultiplied form, for + * example: +<pre> + float a = ...; + float r = r * a; + float g = g * a; + float b = b * a; + gl.glColor4f(r, g, b, a); +</pre> + * + * For reference, here is a list of the Porter-Duff compositing rules + * and the associated OpenGL blend functions (source and destination + * factors) to use in the face of premultiplied alpha: + * +<CENTER> +<TABLE WIDTH="75%"> +<TR> <TD> Rule <TD> Source <TD> Dest +<TR> <TD> Clear <TD> GL_ZERO <TD> GL_ZERO +<TR> <TD> Src <TD> GL_ONE <TD> GL_ZERO +<TR> <TD> SrcOver <TD> GL_ONE <TD> GL_ONE_MINUS_SRC_ALPHA +<TR> <TD> DstOver <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE +<TR> <TD> SrcIn <TD> GL_DST_ALPHA <TD> GL_ZERO +<TR> <TD> DstIn <TD> GL_ZERO <TD> GL_SRC_ALPHA +<TR> <TD> SrcOut <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ZERO +<TR> <TD> DstOut <TD> GL_ZERO <TD> GL_ONE_MINUS_SRC_ALPHA +<TR> <TD> Dst <TD> GL_ZERO <TD> GL_ONE +<TR> <TD> SrcAtop <TD> GL_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA +<TR> <TD> DstAtop <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_SRC_ALPHA +<TR> <TD> AlphaXor <TD> GL_ONE_MINUS_DST_ALPHA <TD> GL_ONE_MINUS_SRC_ALPHA +</TABLE> +</CENTER> + * + * @author Chris Campbell + * @author Kenneth Russell + */ +public class Texture { + /** The GL target type. */ + private int target; + /** The GL texture ID. */ + private int texID; + /** The width of the texture. */ + private int texWidth; + /** The height of the texture. */ + private int texHeight; + /** The width of the image. */ + private int imgWidth; + /** The height of the image. */ + private int imgHeight; + /** The original aspect ratio of the image, before any rescaling + that might have occurred due to using the GLU mipmap routines. */ + private float aspectRatio; + /** Indicates whether the TextureData requires a vertical flip of + the texture coords. */ + private boolean mustFlipVertically; + /** Indicates whether we're using automatic mipmap generation + support (GL_GENERATE_MIPMAP). */ + private boolean usingAutoMipmapGeneration; + + /** The texture coordinates corresponding to the entire image. */ + private TextureCoords coords; + + /** An estimate of the amount of texture memory this texture consumes. */ + private int estimatedMemorySize; + + private static final AccessControlContext localACC = AccessController.getContext(); + + private static final boolean DEBUG = Debug.debug("Texture"); + private static final boolean VERBOSE = Debug.verbose(); + + // For testing alternate code paths on more capable hardware + private static final boolean disableNPOT = Debug.isPropertyDefined("jogl.texture.nonpot", true, localACC); + private static final boolean disableTexRect = Debug.isPropertyDefined("jogl.texture.notexrect", true, localACC); + + public Texture(TextureData data) throws GLException { + texID = 0; + updateImage(data); + } + + // Constructor for use when creating e.g. cube maps, where there is + // no initial texture data + public Texture(int target) throws GLException { + texID = 0; + this.target = target; + } + + // Package-private constructor for creating a texture object which wraps + // an existing texture ID from another package + Texture(int textureID, + int target, + int texWidth, + int texHeight, + int imgWidth, + int imgHeight, + boolean mustFlipVertically) { + this.texID = textureID; + this.target = target; + this.mustFlipVertically = mustFlipVertically; + this.texWidth = texWidth; + this.texHeight = texHeight; + setImageSize(imgWidth, imgHeight, target); + } + + /** + * Enables this texture's target (e.g., GL_TEXTURE_2D) in the + * current GL context's state. This method is a shorthand equivalent + * of the following OpenGL code: + <pre> + gl.glEnable(texture.getTarget()); + </pre> + * + * See the <a href="#perftips">performance tips</a> above for hints + * on how to maximize performance when using many Texture objects. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void enable() throws GLException { + GLContext.getCurrentGL().glEnable(target); + } + + /** + * Disables this texture's target (e.g., GL_TEXTURE_2D) in the + * current GL context's state. This method is a shorthand equivalent + * of the following OpenGL code: + <pre> + gl.glDisable(texture.getTarget()); + </pre> + * + * See the <a href="#perftips">performance tips</a> above for hints + * on how to maximize performance when using many Texture objects. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void disable() throws GLException { + GLContext.getCurrentGL().glDisable(target); + } + + /** + * Binds this texture to the current GL context. This method is a + * shorthand equivalent of the following OpenGL code: + <pre> + gl.glBindTexture(texture.getTarget(), texture.getTextureObject()); + </pre> + * + * See the <a href="#perftips">performance tips</a> above for hints + * on how to maximize performance when using many Texture objects. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void bind() throws GLException { + validateTexID(null, true); + GLContext.getCurrentGL().glBindTexture(target, texID); + } + + /** + * Disposes the native resources used by this texture object. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + * @deprecated use destroy(GL) + */ + public void dispose() throws GLException { + destroy(GLContext.getCurrentGL()); + } + + /** + * Disposes the native resources used by this texture object. + * + * @throws GLException if any OpenGL-related errors occurred + * @deprecated use destroy(GL) + */ + public void dispose(GL gl) throws GLException { + destroy(gl); + } + + /** + * Destroys the native resources used by this texture object. + * + * @throws GLException if any OpenGL-related errors occurred + */ + public void destroy(GL gl) throws GLException { + if(0<texID) { + gl.glDeleteTextures(1, new int[] {texID}, 0); + texID = 0; + } + } + + /** + * Returns the OpenGL "target" of this texture. + * + * @return the OpenGL target of this texture + * @see javax.media.opengl.GL#GL_TEXTURE_2D + * @see javax.media.opengl.GL2#GL_TEXTURE_RECTANGLE_ARB + */ + public int getTarget() { + return target; + } + + /** + * Returns the width of the allocated OpenGL texture in pixels. + * Note that the texture width will be greater than or equal to the + * width of the image contained within. + * + * @return the width of the texture + */ + public int getWidth() { + return texWidth; + } + + /** + * Returns the height of the allocated OpenGL texture in pixels. + * Note that the texture height will be greater than or equal to the + * height of the image contained within. + * + * @return the height of the texture + */ + public int getHeight() { + return texHeight; + } + + /** + * Returns the width of the image contained within this texture. + * Note that for non-power-of-two textures in particular this may + * not be equal to the result of {@link #getWidth}. It is + * recommended that applications call {@link #getImageTexCoords} and + * {@link #getSubImageTexCoords} rather than using this API + * directly. + * + * @return the width of the image + */ + public int getImageWidth() { + return imgWidth; + } + + /** + * Returns the height of the image contained within this texture. + * Note that for non-power-of-two textures in particular this may + * not be equal to the result of {@link #getHeight}. It is + * recommended that applications call {@link #getImageTexCoords} and + * {@link #getSubImageTexCoords} rather than using this API + * directly. + * + * @return the height of the image + */ + public int getImageHeight() { + return imgHeight; + } + + /** + * Returns the original aspect ratio of the image, defined as (image + * width) / (image height), before any scaling that might have + * occurred as a result of using the GLU mipmap routines. + */ + public float getAspectRatio() { + return aspectRatio; + } + + /** + * Returns the set of texture coordinates corresponding to the + * entire image. If the TextureData indicated that the texture + * coordinates must be flipped vertically, the returned + * TextureCoords will take that into account. + * + * @return the texture coordinates corresponding to the entire image + */ + public TextureCoords getImageTexCoords() { + return coords; + } + + /** + * Returns the set of texture coordinates corresponding to the + * specified sub-image. The (x1, y1) and (x2, y2) points are + * specified in terms of pixels starting from the lower-left of the + * image. (x1, y1) should specify the lower-left corner of the + * sub-image and (x2, y2) the upper-right corner of the sub-image. + * If the TextureData indicated that the texture coordinates must be + * flipped vertically, the returned TextureCoords will take that + * into account; this should not be handled by the end user in the + * specification of the y1 and y2 coordinates. + * + * @return the texture coordinates corresponding to the specified sub-image + */ + public TextureCoords getSubImageTexCoords(int x1, int y1, int x2, int y2) { + if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if (mustFlipVertically) { + return new TextureCoords(x1, texHeight - y1, x2, texHeight - y2); + } else { + return new TextureCoords(x1, y1, x2, y2); + } + } else { + float tx1 = (float)x1 / (float)texWidth; + float ty1 = (float)y1 / (float)texHeight; + float tx2 = (float)x2 / (float)texWidth; + float ty2 = (float)y2 / (float)texHeight; + if (mustFlipVertically) { + float yMax = (float) imgHeight / (float) texHeight; + return new TextureCoords(tx1, yMax - ty1, tx2, yMax - ty2); + } else { + return new TextureCoords(tx1, ty1, tx2, ty2); + } + } + } + + /** + * Updates the entire content area of this texture using the data in + * the given image. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void updateImage(TextureData data) throws GLException { + updateImage(data, 0); + } + + /** + * Indicates whether this texture's texture coordinates must be + * flipped vertically in order to properly display the texture. This + * is handled automatically by {@link #getImageTexCoords + * getImageTexCoords} and {@link #getSubImageTexCoords + * getSubImageTexCoords}, but applications may generate or otherwise + * produce texture coordinates which must be corrected. + */ + public boolean getMustFlipVertically() { + return mustFlipVertically; + } + + /** + * Updates the content area of the specified target of this texture + * using the data in the given image. In general this is intended + * for construction of cube maps. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void updateImage(TextureData data, int target) throws GLException { + GL gl = GLContext.getCurrentGL(); + validateTexID(gl, true); + + imgWidth = data.getWidth(); + imgHeight = data.getHeight(); + aspectRatio = (float) imgWidth / (float) imgHeight; + mustFlipVertically = data.getMustFlipVertically(); + + int texTarget = 0; + int texParamTarget = this.target; + + // See whether we have automatic mipmap generation support + boolean haveAutoMipmapGeneration = + (gl.isExtensionAvailable("GL_VERSION_1_4") || + gl.isExtensionAvailable("GL_SGIS_generate_mipmap")); + + // Indicate to the TextureData what functionality is available + data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); + data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + + // Indicates whether both width and height are power of two + boolean isPOT = isPowerOfTwo(imgWidth) && isPowerOfTwo(imgHeight); + + // Note that automatic mipmap generation doesn't work for + // GL_ARB_texture_rectangle + if (!isPOT && !haveNPOT(gl)) { + haveAutoMipmapGeneration = false; + } + + boolean expandingCompressedTexture = false; + boolean done = false; + if (data.getMipmap() && !haveAutoMipmapGeneration) { + // GLU always scales the texture's dimensions to be powers of + // two. It also doesn't really matter exactly what the texture + // width and height are because the texture coords are always + // between 0.0 and 1.0. + imgWidth = nextPowerOfTwo(imgWidth); + imgHeight = nextPowerOfTwo(imgHeight); + texWidth = imgWidth; + texHeight = imgHeight; + texTarget = GL.GL_TEXTURE_2D; + done = true; + } + + if (!done && preferTexRect(gl) && !isPOT && + haveTexRect(gl) && !data.isDataCompressed() && !gl.isGL3() && !gl.isGLES()) { + // GL_ARB_texture_rectangle does not work for compressed textures + if (DEBUG) { + System.err.println("Using GL_ARB_texture_rectangle preferentially on this hardware"); + } + + texWidth = imgWidth; + texHeight = imgHeight; + texTarget = GL2.GL_TEXTURE_RECTANGLE_ARB; + done = true; + } + + if (!done && (isPOT || haveNPOT(gl))) { + if (DEBUG) { + if (isPOT) { + System.err.println("Power-of-two texture"); + } else { + System.err.println("Using GL_ARB_texture_non_power_of_two"); + } + } + + texWidth = imgWidth; + texHeight = imgHeight; + texTarget = GL.GL_TEXTURE_2D; + done = true; + } + + if (!done && haveTexRect(gl) && !data.isDataCompressed() && !gl.isGL3() && !gl.isGLES()) { + // GL_ARB_texture_rectangle does not work for compressed textures + if (DEBUG) { + System.err.println("Using GL_ARB_texture_rectangle"); + } + + texWidth = imgWidth; + texHeight = imgHeight; + texTarget = GL2.GL_TEXTURE_RECTANGLE_ARB; + done = true; + } + + if (!done) { + // If we receive non-power-of-two compressed texture data and + // don't have true hardware support for compressed textures, we + // can fake this support by producing an empty "compressed" + // texture image, using glCompressedTexImage2D with that to + // allocate the texture, and glCompressedTexSubImage2D with the + // incoming data. + if (data.isDataCompressed()) { + if (data.getMipmapData() != null) { + + // We don't currently support expanding of compressed, + // mipmapped non-power-of-two textures to the nearest power + // of two; the obvious port of the non-mipmapped code didn't + // work + throw new GLException("Mipmapped non-power-of-two compressed textures only supported on OpenGL 2.0 hardware (GL_ARB_texture_non_power_of_two)"); + } + + expandingCompressedTexture = true; + } + + if (DEBUG) { + System.err.println("Expanding texture to power-of-two dimensions"); + } + + if (data.getBorder() != 0) { + throw new RuntimeException("Scaling up a non-power-of-two texture which has a border won't work"); + } + texWidth = nextPowerOfTwo(imgWidth); + texHeight = nextPowerOfTwo(imgHeight); + texTarget = GL.GL_TEXTURE_2D; + } + + texParamTarget = texTarget; + setImageSize(imgWidth, imgHeight, texTarget); + + if (target != 0) { + // Allow user to override auto detection and skip bind step (for + // cubemap construction) + texTarget = target; + if (this.target == 0) { + throw new GLException("Override of target failed; no target specified yet"); + } + texParamTarget = this.target; + gl.glBindTexture(texParamTarget, texID); + } else { + gl.glBindTexture(texTarget, texID); + } + + if (data.getMipmap() && !haveAutoMipmapGeneration) { + int[] align = new int[1]; + gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment()); + + if (data.isDataCompressed()) { + throw new GLException("May not request mipmap generation for compressed textures"); + } + + try { + // FIXME: may need check for GLUnsupportedException + GLU glu = GLU.createGLU(gl); + glu.gluBuild2DMipmaps(texTarget, data.getInternalFormat(), + data.getWidth(), data.getHeight(), + data.getPixelFormat(), data.getPixelType(), data.getBuffer()); + } finally { + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment + } + } else { + checkCompressedTextureExtensions(data); + Buffer[] mipmapData = data.getMipmapData(); + if (mipmapData != null) { + int width = texWidth; + int height = texHeight; + for (int i = 0; i < mipmapData.length; i++) { + if (data.isDataCompressed()) { + // Need to use glCompressedTexImage2D directly to allocate and fill this image + // Avoid spurious memory allocation when possible + gl.glCompressedTexImage2D(texTarget, i, data.getInternalFormat(), + width, height, data.getBorder(), + mipmapData[i].remaining(), mipmapData[i]); + } else { + // Allocate texture image at this level + gl.glTexImage2D(texTarget, i, data.getInternalFormat(), + width, height, data.getBorder(), + data.getPixelFormat(), data.getPixelType(), null); + updateSubImageImpl(data, texTarget, i, 0, 0, 0, 0, data.getWidth(), data.getHeight()); + } + + width = Math.max(width / 2, 1); + height = Math.max(height / 2, 1); + } + } else { + if (data.isDataCompressed()) { + if (!expandingCompressedTexture) { + // Need to use glCompressedTexImage2D directly to allocate and fill this image + // Avoid spurious memory allocation when possible + gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(), + texWidth, texHeight, data.getBorder(), + data.getBuffer().capacity(), data.getBuffer()); + } else { + ByteBuffer buf = DDSImage.allocateBlankBuffer(texWidth, + texHeight, + data.getInternalFormat()); + gl.glCompressedTexImage2D(texTarget, 0, data.getInternalFormat(), + texWidth, texHeight, data.getBorder(), + buf.capacity(), buf); + updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight()); + } + } else { + if (data.getMipmap() && haveAutoMipmapGeneration && gl.isGL2ES1()) { + // For now, only use hardware mipmapping for uncompressed 2D + // textures where the user hasn't explicitly specified + // mipmap data; don't know about interactions between + // GL_GENERATE_MIPMAP and glCompressedTexImage2D + gl.glTexParameteri(texParamTarget, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE); + usingAutoMipmapGeneration = true; + } + + gl.glTexImage2D(texTarget, 0, data.getInternalFormat(), + texWidth, texHeight, data.getBorder(), + data.getPixelFormat(), data.getPixelType(), null); + updateSubImageImpl(data, texTarget, 0, 0, 0, 0, 0, data.getWidth(), data.getHeight()); + } + } + } + + int minFilter = (data.getMipmap() ? GL.GL_LINEAR_MIPMAP_LINEAR : GL.GL_LINEAR); + int magFilter = GL.GL_LINEAR; + int wrapMode = (gl.isExtensionAvailable("GL_VERSION_1_2") || !gl.isGL2()) ? GL.GL_CLAMP_TO_EDGE : GL2.GL_CLAMP; + + // REMIND: figure out what to do for GL_TEXTURE_RECTANGLE_ARB + if (texTarget != GL2.GL_TEXTURE_RECTANGLE_ARB) { + gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MIN_FILTER, minFilter); + gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_MAG_FILTER, magFilter); + gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_S, wrapMode); + gl.glTexParameteri(texParamTarget, GL.GL_TEXTURE_WRAP_T, wrapMode); + if (this.target == GL2.GL_TEXTURE_CUBE_MAP) { + gl.glTexParameteri(texParamTarget, GL2.GL_TEXTURE_WRAP_R, wrapMode); + } + } + + // Don't overwrite target if we're loading e.g. faces of a cube + // map + if ((this.target == 0) || + (this.target == GL.GL_TEXTURE_2D) || + (this.target == GL2.GL_TEXTURE_RECTANGLE_ARB)) { + this.target = texTarget; + } + + // This estimate will be wrong for cube maps + estimatedMemorySize = data.getEstimatedMemorySize(); + } + + /** + * Updates a subregion of the content area of this texture using the + * given data. If automatic mipmap generation is in use (see {@link + * #isUsingAutoMipmapGeneration isUsingAutoMipmapGeneration}), + * updates to the base (level 0) mipmap will cause the lower-level + * mipmaps to be regenerated, and updates to other mipmap levels + * will be ignored. Otherwise, if automatic mipmap generation is not + * in use, only updates the specified mipmap level and does not + * re-generate mipmaps if they were originally produced or loaded. + * + * @param data the image data to be uploaded to this texture + * @param mipmapLevel the mipmap level of the texture to set. If + * this is non-zero and the TextureData contains mipmap data, the + * appropriate mipmap level will be selected. + * @param x the x offset (in pixels) relative to the lower-left corner + * of this texture + * @param y the y offset (in pixels) relative to the lower-left corner + * of this texture + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void updateSubImage(TextureData data, int mipmapLevel, int x, int y) throws GLException { + if (usingAutoMipmapGeneration && mipmapLevel != 0) { + // When we're using mipmap generation via GL_GENERATE_MIPMAP, we + // don't need to update other mipmap levels + return; + } + bind(); + updateSubImageImpl(data, target, mipmapLevel, x, y, 0, 0, data.getWidth(), data.getHeight()); + } + + /** + * Updates a subregion of the content area of this texture using the + * specified sub-region of the given data. If automatic mipmap + * generation is in use (see {@link #isUsingAutoMipmapGeneration + * isUsingAutoMipmapGeneration}), updates to the base (level 0) + * mipmap will cause the lower-level mipmaps to be regenerated, and + * updates to other mipmap levels will be ignored. Otherwise, if + * automatic mipmap generation is not in use, only updates the + * specified mipmap level and does not re-generate mipmaps if they + * were originally produced or loaded. This method is only supported + * for uncompressed TextureData sources. + * + * @param data the image data to be uploaded to this texture + * @param mipmapLevel the mipmap level of the texture to set. If + * this is non-zero and the TextureData contains mipmap data, the + * appropriate mipmap level will be selected. + * @param dstx the x offset (in pixels) relative to the lower-left corner + * of this texture where the update will be applied + * @param dsty the y offset (in pixels) relative to the lower-left corner + * of this texture where the update will be applied + * @param srcx the x offset (in pixels) relative to the lower-left corner + * of the supplied TextureData from which to fetch the update rectangle + * @param srcy the y offset (in pixels) relative to the lower-left corner + * of the supplied TextureData from which to fetch the update rectangle + * @param width the width (in pixels) of the rectangle to be updated + * @param height the height (in pixels) of the rectangle to be updated + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void updateSubImage(TextureData data, int mipmapLevel, + int dstx, int dsty, + int srcx, int srcy, + int width, int height) throws GLException { + if (data.isDataCompressed()) { + throw new GLException("updateSubImage specifying a sub-rectangle is not supported for compressed TextureData"); + } + if (usingAutoMipmapGeneration && mipmapLevel != 0) { + // When we're using mipmap generation via GL_GENERATE_MIPMAP, we + // don't need to update other mipmap levels + return; + } + bind(); + updateSubImageImpl(data, target, mipmapLevel, dstx, dsty, srcx, srcy, width, height); + } + + /** + * Sets the OpenGL floating-point texture parameter for the + * texture's target. This gives control over parameters such as + * GL_TEXTURE_MAX_ANISOTROPY_EXT. Causes this texture to be bound to + * the current texture state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameterf(int parameterName, + float value) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameterf(target, parameterName, value); + } + + /** + * Sets the OpenGL multi-floating-point texture parameter for the + * texture's target. Causes this texture to be bound to the current + * texture state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameterfv(int parameterName, + FloatBuffer params) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameterfv(target, parameterName, params); + } + + /** + * Sets the OpenGL multi-floating-point texture parameter for the + * texture's target. Causes this texture to be bound to the current + * texture state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameterfv(int parameterName, + float[] params, int params_offset) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameterfv(target, parameterName, params, params_offset); + } + + /** + * Sets the OpenGL integer texture parameter for the texture's + * target. This gives control over parameters such as + * GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T, which by default are set + * to GL_CLAMP_TO_EDGE if OpenGL 1.2 is supported on the current + * platform and GL_CLAMP if not. Causes this texture to be bound to + * the current texture state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameteri(int parameterName, + int value) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameteri(target, parameterName, value); + } + + /** + * Sets the OpenGL multi-integer texture parameter for the texture's + * target. Causes this texture to be bound to the current texture + * state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameteriv(int parameterName, + IntBuffer params) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameteriv(target, parameterName, params); + } + + /** + * Sets the OpenGL multi-integer texture parameter for the texture's + * target. Causes this texture to be bound to the current texture + * state. + * + * @throws GLException if no OpenGL context was current or if any + * OpenGL-related errors occurred + */ + public void setTexParameteriv(int parameterName, + int[] params, int params_offset) { + bind(); + GL gl = GLContext.getCurrentGL(); + gl.glTexParameteriv(target, parameterName, params, params_offset); + } + + /** + * Returns the underlying OpenGL texture object for this texture. + * Most applications will not need to access this, since it is + * handled automatically by the bind() and dispose() APIs. + */ + public int getTextureObject() { + validateTexID(null, false); + return texID; + } + + /** Returns an estimate of the amount of texture memory in bytes + this Texture consumes. It should only be treated as an estimate; + most applications should not need to query this but instead let + the OpenGL implementation page textures in and out as + necessary. */ + public int getEstimatedMemorySize() { + return estimatedMemorySize; + } + + /** Indicates whether this Texture is using automatic mipmap + generation (via the OpenGL texture parameter + GL_GENERATE_MIPMAP). This will automatically be used when + mipmapping is requested via the TextureData and either OpenGL + 1.4 or the GL_SGIS_generate_mipmap extension is available. If + so, updates to the base image (mipmap level 0) will + automatically propagate down to the lower mipmap levels. Manual + updates of the mipmap data at these lower levels will be + ignored. */ + public boolean isUsingAutoMipmapGeneration() { + return usingAutoMipmapGeneration; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + /** + * Returns true if the given value is a power of two. + * + * @return true if the given value is a power of two, false otherwise + */ + private static boolean isPowerOfTwo(int val) { + return ((val & (val - 1)) == 0); + } + + /** + * Returns the nearest power of two that is larger than the given value. + * If the given value is already a power of two, this method will simply + * return that value. + * + * @param val the value + * @return the next power of two + */ + private static int nextPowerOfTwo(int val) { + int ret = 1; + while (ret < val) { + ret <<= 1; + } + return ret; + } + + /** + * Updates the actual image dimensions; usually only called from + * <code>updateImage</code>. + */ + private void setImageSize(int width, int height, int target) { + imgWidth = width; + imgHeight = height; + if (target == GL2.GL_TEXTURE_RECTANGLE_ARB) { + if (mustFlipVertically) { + coords = new TextureCoords(0, imgHeight, imgWidth, 0); + } else { + coords = new TextureCoords(0, 0, imgWidth, imgHeight); + } + } else { + if (mustFlipVertically) { + coords = new TextureCoords(0, (float) imgHeight / (float) texHeight, + (float) imgWidth / (float) texWidth, 0); + } else { + coords = new TextureCoords(0, 0, + (float) imgWidth / (float) texWidth, + (float) imgHeight / (float) texHeight); + } + } + } + + private void updateSubImageImpl(TextureData data, int newTarget, int mipmapLevel, + int dstx, int dsty, + int srcx, int srcy, int width, int height) throws GLException { + GL gl = GLContext.getCurrentGL(); + data.setHaveEXTABGR(gl.isExtensionAvailable("GL_EXT_abgr")); + data.setHaveGL12(gl.isExtensionAvailable("GL_VERSION_1_2")); + + Buffer buffer = data.getBuffer(); + if (buffer == null && data.getMipmapData() == null) { + // Assume user just wanted to get the Texture object allocated + return; + } + + int rowlen = data.getRowLength(); + int dataWidth = data.getWidth(); + int dataHeight = data.getHeight(); + if (data.getMipmapData() != null) { + // Compute the width, height and row length at the specified mipmap level + // Note we do not support specification of the row length for + // mipmapped textures at this point + for (int i = 0; i < mipmapLevel; i++) { + width = Math.max(width / 2, 1); + height = Math.max(height / 2, 1); + + dataWidth = Math.max(dataWidth / 2, 1); + dataHeight = Math.max(dataHeight / 2, 1); + } + rowlen = 0; + buffer = data.getMipmapData()[mipmapLevel]; + } + + // Clip incoming rectangles to what is available both on this + // texture and in the incoming TextureData + if (srcx < 0) { + width += srcx; + srcx = 0; + } + if (srcy < 0) { + height += srcy; + srcy = 0; + } + // NOTE: not sure whether the following two are the correct thing to do + if (dstx < 0) { + width += dstx; + dstx = 0; + } + if (dsty < 0) { + height += dsty; + dsty = 0; + } + + if (srcx + width > dataWidth) { + width = dataWidth - srcx; + } + if (srcy + height > dataHeight) { + height = dataHeight - srcy; + } + if (dstx + width > texWidth) { + width = texWidth - dstx; + } + if (dsty + height > texHeight) { + height = texHeight - dsty; + } + + checkCompressedTextureExtensions(data); + + if (data.isDataCompressed()) { + gl.glCompressedTexSubImage2D(newTarget, mipmapLevel, + dstx, dsty, width, height, + data.getInternalFormat(), + buffer.remaining(), buffer); + } else { + int[] align = { 0 }; + int[] rowLength = { 0 }; + int[] skipRows = { 0 }; + int[] skipPixels = { 0 }; + gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0); // save alignment + if(gl.isGL2GL3()) { + gl.glGetIntegerv(GL2GL3.GL_UNPACK_ROW_LENGTH, rowLength, 0); // save row length + gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_ROWS, skipRows, 0); // save skipped rows + gl.glGetIntegerv(GL2GL3.GL_UNPACK_SKIP_PIXELS, skipPixels, 0); // save skipped pixels + } + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, data.getAlignment()); + if (DEBUG && VERBOSE) { + System.out.println("Row length = " + rowlen); + System.out.println("skip pixels = " + srcx); + System.out.println("skip rows = " + srcy); + System.out.println("dstx = " + dstx); + System.out.println("dsty = " + dsty); + System.out.println("width = " + width); + System.out.println("height = " + height); + } + if(gl.isGL2GL3()) { + gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, rowlen); + gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, srcy); + gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, srcx); + } else { + if ( rowlen!=0 && rowlen!=width && + srcy!=0 && srcx!=0 ) { + throw new GLException("rowlen and/or x/y offset only available for GL2"); + } + } + + gl.glTexSubImage2D(newTarget, mipmapLevel, + dstx, dsty, width, height, + data.getPixelFormat(), data.getPixelType(), + buffer); + gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]); // restore alignment + if(gl.isGL2GL3()) { + gl.glPixelStorei(GL2GL3.GL_UNPACK_ROW_LENGTH, rowLength[0]); // restore row length + gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_ROWS, skipRows[0]); // restore skipped rows + gl.glPixelStorei(GL2GL3.GL_UNPACK_SKIP_PIXELS, skipPixels[0]); // restore skipped pixels + } + } + } + + private void checkCompressedTextureExtensions(TextureData data) { + GL gl = GLContext.getCurrentGL(); + if (data.isDataCompressed()) { + switch (data.getInternalFormat()) { + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + if (!gl.isExtensionAvailable("GL_EXT_texture_compression_s3tc") && + !gl.isExtensionAvailable("GL_NV_texture_compression_vtc")) { + throw new GLException("DXTn compressed textures not supported by this graphics card"); + } + break; + default: + // FI1027GXME: should test availability of more texture + // compression extensions here + break; + } + } + } + + private void validateTexID(GL gl, boolean throwException) { + if( 0 < texID ) return; + if(null==gl) { + GLContext ctx = GLContext.getCurrent(); + if(null!=ctx) { + gl = ctx.getGL(); + } else if(throwException) { + throw new GLException("No context current, can't create texture ID"); + } + } + + if(null!=gl) { + int[] tmp = new int[1]; + gl.glGenTextures(1, tmp, 0); + texID = tmp[0]; + } + } + + // Helper routines for disabling certain codepaths + private static boolean haveNPOT(GL gl) { + return (!disableNPOT && + ( gl.isGLES2() || + gl.isExtensionAvailable("GL_ARB_texture_non_power_of_two") ) ); + } + + private static boolean haveTexRect(GL gl) { + return (!disableTexRect && + TextureIO.isTexRectEnabled() && + gl.isExtensionAvailable("GL_ARB_texture_rectangle")); + } + + private static boolean preferTexRect(GL gl) { + // Prefer GL_ARB_texture_rectangle on ATI hardware on Mac OS X + // due to software fallbacks + + if (NativeWindowFactory.TYPE_MACOSX.equals(NativeWindowFactory.getNativeWindowType(false))) { + String vendor = gl.glGetString(GL.GL_VENDOR); + if (vendor != null && vendor.startsWith("ATI")) { + return true; + } + } + + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java new file mode 100755 index 000000000..8d8b3679d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureCoords.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util.texture; + +/** Specifies texture coordinates for a rectangular area of a + texture. Note that some textures are inherently flipped vertically + from OpenGL's standard coordinate system. This class takes care of + this vertical flip so that the "bottom" and "top" coordinates may + sometimes be reversed. From the point of view of code rendering + textured polygons, it can always map the bottom and left texture + coordinates from the TextureCoords to the lower left point of the + textured polygon and achieve correct results. */ + +public class TextureCoords { + // These represent the lower-left point + private float left; + private float bottom; + // These represent the upper-right point + private float right; + private float top; + + public TextureCoords(float left, float bottom, + float right, float top) { + this.left = left; + this.bottom = bottom; + this.right = right; + this.top = top; + } + + /** Returns the leftmost (x) texture coordinate of this + rectangle. */ + public float left() { return left; } + + /** Returns the rightmost (x) texture coordinate of this + rectangle. */ + public float right() { return right; } + + /** Returns the bottommost (y) texture coordinate of this + rectangle. */ + public float bottom() { return bottom; } + + /** Returns the topmost (y) texture coordinate of this + rectangle. */ + public float top() { return top; } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java new file mode 100755 index 000000000..f598422bf --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureData.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util.texture; + +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; + +/** + * Represents the data for an OpenGL texture. This is separated from + * the notion of a Texture to support things like streaming in of + * textures in a background thread without requiring an OpenGL context + * to be current on that thread. + * + * @author Chris Campbell + * @author Kenneth Russell + * @author Sven Gothel + */ + +public class TextureData { + protected int width; + protected int height; + private int border; + protected int pixelFormat; + protected int pixelType; + protected int internalFormat; // perhaps inferred from pixelFormat? + protected boolean mipmap; // indicates whether mipmaps should be generated + // (ignored if mipmaps are supplied from the file) + private boolean dataIsCompressed; + protected boolean mustFlipVertically; // Must flip texture coordinates + // vertically to get OpenGL output + // to look correct + protected Buffer buffer; // the actual data... + private Buffer[] mipmapData; // ...or a series of mipmaps + private Flusher flusher; + protected int rowLength; + protected int alignment; // 1, 2, or 4 bytes + protected int estimatedMemorySize; + + // These booleans are a concession to the AWTTextureData subclass + protected boolean haveEXTABGR; + protected boolean haveGL12; + protected GLProfile glProfile; + + /** + * Constructs a new TextureData object with the specified parameters + * and data contained in the given Buffer. The optional Flusher can + * be used to clean up native resources associated with this + * TextureData when processing is complete; for example, closing of + * memory-mapped files that might otherwise require a garbage + * collection to reclaim and close. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param internalFormat the OpenGL internal format for the + * resulting texture; must be specified, may + * not be 0 + * @param width the width in pixels of the texture + * @param height the height in pixels of the texture + * @param border the number of pixels of border this texture + * data has (0 or 1) + * @param pixelFormat the OpenGL pixel format for the + * resulting texture; must be specified, may + * not be 0 + * @param pixelType the OpenGL type of the pixels of the texture + * @param mipmap indicates whether mipmaps should be + * autogenerated (using GLU) for the resulting + * texture. Currently if mipmap is true then + * dataIsCompressed may not be true. + * @param dataIsCompressed indicates whether the texture data is in + * compressed form + * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT) + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + * @param buffer the buffer containing the texture data + * @param flusher optional flusher to perform cleanup tasks + * upon call to flush() + * + * @throws IllegalArgumentException if any parameters of the texture + * data were invalid, such as requesting mipmap generation for a + * compressed texture + */ + public TextureData(GLProfile glp, + int internalFormat, + int width, + int height, + int border, + int pixelFormat, + int pixelType, + boolean mipmap, + boolean dataIsCompressed, + boolean mustFlipVertically, + Buffer buffer, + Flusher flusher) throws IllegalArgumentException { + if (mipmap && dataIsCompressed) { + throw new IllegalArgumentException("Can not generate mipmaps for compressed textures"); + } + + this.glProfile = glp; + this.width = width; + this.height = height; + this.border = border; + this.pixelFormat = pixelFormat; + this.pixelType = pixelType; + this.internalFormat = internalFormat; + this.mipmap = mipmap; + this.dataIsCompressed = dataIsCompressed; + this.mustFlipVertically = mustFlipVertically; + this.buffer = buffer; + this.flusher = flusher; + alignment = 1; // FIXME: is this correct enough in all situations? + estimatedMemorySize = estimatedMemorySize(buffer); + } + + /** + * Constructs a new TextureData object with the specified parameters + * and data for multiple mipmap levels contained in the given array + * of Buffers. The optional Flusher can be used to clean up native + * resources associated with this TextureData when processing is + * complete; for example, closing of memory-mapped files that might + * otherwise require a garbage collection to reclaim and close. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param internalFormat the OpenGL internal format for the + * resulting texture; must be specified, may + * not be 0 + * @param width the width in pixels of the topmost mipmap + * level of the texture + * @param height the height in pixels of the topmost mipmap + * level of the texture + * @param border the number of pixels of border this texture + * data has (0 or 1) + * @param pixelFormat the OpenGL pixel format for the + * resulting texture; must be specified, may + * not be 0 + * @param pixelType the OpenGL type of the pixels of the texture + * @param dataIsCompressed indicates whether the texture data is in + * compressed form + * (e.g. GL_COMPRESSED_RGB_S3TC_DXT1_EXT) + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + * @param mipmapData the buffers containing all mipmap levels + * of the texture's data + * @param flusher optional flusher to perform cleanup tasks + * upon call to flush() + * + * @throws IllegalArgumentException if any parameters of the texture + * data were invalid, such as requesting mipmap generation for a + * compressed texture + */ + public TextureData(GLProfile glp, + int internalFormat, + int width, + int height, + int border, + int pixelFormat, + int pixelType, + boolean dataIsCompressed, + boolean mustFlipVertically, + Buffer[] mipmapData, + Flusher flusher) throws IllegalArgumentException { + this.glProfile = glp; + this.width = width; + this.height = height; + this.border = border; + this.pixelFormat = pixelFormat; + this.pixelType = pixelType; + this.internalFormat = internalFormat; + this.dataIsCompressed = dataIsCompressed; + this.mustFlipVertically = mustFlipVertically; + this.mipmapData = (Buffer[]) mipmapData.clone(); + this.flusher = flusher; + alignment = 1; // FIXME: is this correct enough in all situations? + for (int i = 0; i < mipmapData.length; i++) { + estimatedMemorySize += estimatedMemorySize(mipmapData[i]); + } + } + + /** Used only by subclasses */ + protected TextureData(GLProfile glp) { this.glProfile = glp; } + + /** Returns the width in pixels of the texture data. */ + public int getWidth() { return width; } + /** Returns the height in pixels of the texture data. */ + public int getHeight() { return height; } + /** Returns the border in pixels of the texture data. */ + public int getBorder() { + return border; + } + /** Returns the intended OpenGL pixel format of the texture data. */ + public int getPixelFormat() { + return pixelFormat; + } + /** Returns the intended OpenGL pixel type of the texture data. */ + public int getPixelType() { + return pixelType; + } + /** Returns the intended OpenGL internal format of the texture data. */ + public int getInternalFormat() { + return internalFormat; + } + /** Returns whether mipmaps should be generated for the texture data. */ + public boolean getMipmap() { + return mipmap; + } + /** Indicates whether the texture data is in compressed form. */ + public boolean isDataCompressed() { + return dataIsCompressed; + } + /** Indicates whether the texture coordinates must be flipped + vertically for proper display. */ + public boolean getMustFlipVertically() { + return mustFlipVertically; + } + /** Returns the texture data, or null if it is specified as a set of mipmaps. */ + public Buffer getBuffer() { + return buffer; + } + /** Returns all mipmap levels for the texture data, or null if it is + specified as a single image. */ + public Buffer[] getMipmapData() { + return mipmapData; + } + /** Returns the required byte alignment for the texture data. */ + public int getAlignment() { + return alignment; + } + /** Returns the row length needed for correct GL_UNPACK_ROW_LENGTH + specification. This is currently only supported for + non-mipmapped, non-compressed textures. */ + public int getRowLength() { + return rowLength; + } + + /** Sets the width in pixels of the texture data. */ + public void setWidth(int width) { this.width = width; } + /** Sets the height in pixels of the texture data. */ + public void setHeight(int height) { this.height = height; } + /** Sets the border in pixels of the texture data. */ + public void setBorder(int border) { this.border = border; } + /** Sets the intended OpenGL pixel format of the texture data. */ + public void setPixelFormat(int pixelFormat) { this.pixelFormat = pixelFormat; } + /** Sets the intended OpenGL pixel type of the texture data. */ + public void setPixelType(int pixelType) { this.pixelType = pixelType; } + /** Sets the intended OpenGL internal format of the texture data. */ + public void setInternalFormat(int internalFormat) { this.internalFormat = internalFormat; } + /** Sets whether mipmaps should be generated for the texture data. */ + public void setMipmap(boolean mipmap) { this.mipmap = mipmap; } + /** Sets whether the texture data is in compressed form. */ + public void setIsDataCompressed(boolean compressed) { this.dataIsCompressed = compressed; } + /** Sets whether the texture coordinates must be flipped vertically + for proper display. */ + public void setMustFlipVertically(boolean mustFlipVertically) { this.mustFlipVertically = mustFlipVertically; } + /** Sets the texture data. */ + public void setBuffer(Buffer buffer) { + this.buffer = buffer; + estimatedMemorySize = estimatedMemorySize(buffer); + } + /** Sets the required byte alignment for the texture data. */ + public void setAlignment(int alignment) { this.alignment = alignment; } + /** Sets the row length needed for correct GL_UNPACK_ROW_LENGTH + specification. This is currently only supported for + non-mipmapped, non-compressed textures. */ + public void setRowLength(int rowLength) { this.rowLength = rowLength; } + /** Indicates to this TextureData whether the GL_EXT_abgr extension + is available. Used for optimization along some code paths to + avoid data copies. */ + public void setHaveEXTABGR(boolean haveEXTABGR) { + this.haveEXTABGR = haveEXTABGR; + } + /** Indicates to this TextureData whether OpenGL version 1.2 is + available. If not, falls back to relatively inefficient code + paths for several input data types (several kinds of packed + pixel formats, in particular). */ + public void setHaveGL12(boolean haveGL12) { + this.haveGL12 = haveGL12; + } + + /** Returns the GLProfile this texture data is intended and created for. */ + public GLProfile getGLProfile() { return glProfile; } + + /** Returns an estimate of the amount of memory in bytes this + TextureData will consume once uploaded to the graphics card. It + should only be treated as an estimate; most applications should + not need to query this but instead let the OpenGL implementation + page textures in and out as necessary. */ + public int getEstimatedMemorySize() { + return estimatedMemorySize; + } + + /** Flushes resources associated with this TextureData by calling + Flusher.flush(). */ + public void flush() { + if (flusher != null) { + flusher.flush(); + flusher = null; + } + } + + /** Calls flush() + * @see #flush() + */ + public void destroy() { + flush(); + } + + /** Defines a callback mechanism to allow the user to explicitly + deallocate native resources (memory-mapped files, etc.) + associated with a particular TextureData. */ + public static interface Flusher { + /** Flushes any native resources associated with this + TextureData. */ + public void flush(); + } + + public String toString() { + return "TextureData["+width+"x"+height+", internFormat "+internalFormat+", pixelFormat "+pixelFormat+", pixelType "+pixelType+", border "+border+", estSize "+estimatedMemorySize+", alignment "+alignment+", rowlen "+rowLength; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + protected static int estimatedMemorySize(Buffer buffer) { + if (buffer == null) { + return 0; + } + return buffer.capacity() * GLBuffers.sizeOfBufferElem(buffer); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javame_cdc_fp new file mode 100755 index 000000000..dbd194d21 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javame_cdc_fp @@ -0,0 +1,1256 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture; + +import java.io.*; +import java.net.*; +import java.nio.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.spi.*; + +/** <P> Provides input and output facilities for both loading OpenGL + textures from disk and streams as well as writing textures already + in memory back to disk. </P> + + <P> The TextureIO class supports an arbitrary number of plug-in + readers and writers via TextureProviders and TextureWriters. + TextureProviders know how to produce TextureData objects from + files, InputStreams and URLs. TextureWriters know how to write + TextureData objects to disk in various file formats. The + TextureData class represents the raw data of the texture before it + has been converted to an OpenGL texture object. The Texture class + represents the OpenGL texture object and provides easy facilities + for using the texture. </P> + + <P> There are several built-in TextureProviders and TextureWriters + supplied with the TextureIO implementation. The most basic + provider uses the platform's Image I/O facilities to read in a + BufferedImage and convert it to a texture. This is the baseline + provider and is registered so that it is the last one consulted. + All others are asked first to open a given file. </P> + + <P> There are three other providers registered by default as of + the time of this writing. One handles SGI RGB (".sgi", ".rgb") + images from both files and streams. One handles DirectDraw Surface + (".dds") images read from files, though can not read these images + from streams. One handles Targa (".tga") images read from both + files and streams. These providers are executed in an arbitrary + order. Some of these providers require the file's suffix to either + be specified via the newTextureData methods or for the file to be + named with the appropriate suffix. In general a file suffix should + be provided to the newTexture and newTextureData methods if at all + possible. </P> + + <P> Note that additional TextureProviders, if reading images from + InputStreams, must use the mark()/reset() methods on InputStream + when probing for e.g. magic numbers at the head of the file to + make sure not to disturb the state of the InputStream for + downstream TextureProviders. </P> + + <P> There are analogous TextureWriters provided for writing + textures back to disk if desired. As of this writing, there are + four TextureWriters registered by default: one for Targa files, + one for SGI RGB files, one for DirectDraw surface (.dds) files, + and one for ImageIO-supplied formats such as .jpg and .png. Some + of these writers have certain limitations such as only being able + to write out textures stored in GL_RGB or GL_RGBA format. The DDS + writer supports fetching and writing to disk of texture data in + DXTn compressed format. Whether this will occur is dependent on + whether the texture's internal format is one of the DXTn + compressed formats and whether the target file is .dds format. +*/ + +public class TextureIO { + /** Constant which can be used as a file suffix to indicate a + DirectDraw Surface file. */ + public static final String DDS = "dds"; + + /** Constant which can be used as a file suffix to indicate an SGI + RGB file. */ + public static final String SGI = "sgi"; + + /** Constant which can be used as a file suffix to indicate an SGI + RGB file. */ + public static final String SGI_RGB = "rgb"; + + /** Constant which can be used as a file suffix to indicate a GIF + file. */ + public static final String GIF = "gif"; + + /** Constant which can be used as a file suffix to indicate a JPEG + file. */ + public static final String JPG = "jpg"; + + /** Constant which can be used as a file suffix to indicate a PNG + file. */ + public static final String PNG = "png"; + + /** Constant which can be used as a file suffix to indicate a Targa + file. */ + public static final String TGA = "tga"; + + /** Constant which can be used as a file suffix to indicate a TIFF + file. */ + public static final String TIFF = "tiff"; + + private static final boolean DEBUG = Debug.debug("TextureIO"); + + // For manually disabling the use of the texture rectangle + // extensions so you know the texture target is GL_TEXTURE_2D; this + // is useful for shader writers (thanks to Chris Campbell for this + // observation) + private static boolean texRectEnabled = true; + + //---------------------------------------------------------------------- + // methods that *do not* require a current context + // These methods assume RGB or RGBA textures. + // Some texture providers may not recognize the file format unless + // the fileSuffix is specified, so it is strongly recommended to + // specify it wherever it is known. + // Some texture providers may also only support one kind of input, + // i.e., reading from a file as opposed to a stream. + + /** + * Creates a TextureData from the given file. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param file the file from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the file, or null if none of the + * registered texture providers could read the file + * @throws IOException if an error occurred while reading the file + */ + public static TextureData newTextureData(GLProfile glp, File file, + boolean mipmap, + String fileSuffix) throws IOException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(file); + } + return newTextureDataImpl(glp, file, 0, 0, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given stream. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param stream the stream from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the stream, or null if none of the + * registered texture providers could read the stream + * @throws IOException if an error occurred while reading the stream + */ + public static TextureData newTextureData(GLProfile glp, InputStream stream, + boolean mipmap, + String fileSuffix) throws IOException { + return newTextureDataImpl(glp, stream, 0, 0, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given URL. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param url the URL from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the URL, or null if none of the + * registered texture providers could read the URL + * @throws IOException if an error occurred while reading the URL + */ + public static TextureData newTextureData(GLProfile glp, URL url, + boolean mipmap, + String fileSuffix) throws IOException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + return newTextureDataImpl(glp, url, 0, 0, mipmap, fileSuffix); + } + + //---------------------------------------------------------------------- + // These methods make no assumption about the OpenGL internal format + // or pixel format of the texture; they must be specified by the + // user. It is not allowed to supply 0 (indicating no preference) + // for either the internalFormat or the pixelFormat; + // IllegalArgumentException will be thrown in this case. + + /** + * Creates a TextureData from the given file, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param file the file from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the file, or null if none of the + * registered texture providers could read the file + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the file + */ + public static TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(file); + } + + return newTextureDataImpl(glp, file, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given stream, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param stream the stream from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the stream, or null if none of the + * registered texture providers could read the stream + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the stream + */ + public static TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + return newTextureDataImpl(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given URL, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param url the URL from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the URL, or null if none of the + * registered texture providers could read the URL + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the URL + */ + public static TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + + return newTextureDataImpl(glp, url, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + //---------------------------------------------------------------------- + // methods that *do* require a current context + // + + /** + * Creates an OpenGL texture object from the specified TextureData + * using the current OpenGL context. + * + * @param data the texture data to turn into an OpenGL texture + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + * @throws IllegalArgumentException if the passed TextureData was null + */ + public static Texture newTexture(TextureData data) throws GLException, IllegalArgumentException { + if (data == null) { + throw new IllegalArgumentException("Null TextureData"); + } + return new Texture(data); + } + + /** + * Creates an OpenGL texture object from the specified file using + * the current OpenGL context. + * + * @param file the file from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @throws IOException if an error occurred while reading the file + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(File file, boolean mipmap) throws IOException, GLException { + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, file, mipmap, FileUtil.getFileSuffix(file)); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object from the specified stream using + * the current OpenGL context. + * + * @param stream the stream from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @throws IOException if an error occurred while reading the stream + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(InputStream stream, boolean mipmap, String fileSuffix) throws IOException, GLException { + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, stream, mipmap, fileSuffix); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object from the specified URL using the + * current OpenGL context. + * + * @param url the URL from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @throws IOException if an error occurred while reading the URL + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(URL url, boolean mipmap, String fileSuffix) throws IOException, GLException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, url, mipmap, fileSuffix); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object associated with the given OpenGL + * texture target using the current OpenGL context. The texture has + * no initial data. This is used, for example, to construct cube + * maps out of multiple TextureData objects. + * + * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D, + * GL.GL_TEXTURE_RECTANGLE_ARB + * + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(int target) throws GLException { + return new Texture(target); + } + + /** + * Wraps an OpenGL texture ID from an external library and allows + * some of the base methods from the Texture class, such as + * binding and querying of texture coordinates, to be used with + * it. Attempts to update such textures' contents will yield + * undefined results. + * + * @param textureID the OpenGL texture object to wrap + * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D, + * GL2.GL_TEXTURE_RECTANGLE + * @param texWidth the width of the texture in pixels + * @param texHeight the height of the texture in pixels + * @param imgWidth the width of the image within the texture in + * pixels (if the content is a sub-rectangle in the upper + * left corner); otherwise, pass in texWidth + * @param imgHeight the height of the image within the texture in + * pixels (if the content is a sub-rectangle in the upper + * left corner); otherwise, pass in texHeight + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + */ + public static Texture newTexture(int textureID, + int target, + int texWidth, + int texHeight, + int imgWidth, + int imgHeight, + boolean mustFlipVertically) { + return new Texture(textureID, + target, + texWidth, + texHeight, + imgWidth, + imgHeight, + mustFlipVertically); + } + + /** + * Writes the given texture to a file. The type of the file is + * inferred from its suffix. An OpenGL context must be current in + * order to fetch the texture data back from the OpenGL pipeline. + * This method causes the specified Texture to be bound to the + * GL_TEXTURE_2D state. If no suitable writer for the requested file + * format was found, throws an IOException. <P> + * + * Reasonable attempts are made to produce good results in the + * resulting images. The Targa, SGI and ImageIO writers produce + * results in the correct vertical orientation for those file + * formats. The DDS writer performs no vertical flip of the data, + * even in uncompressed mode. (It is impossible to perform such a + * vertical flip with compressed data.) Applications should keep + * this in mind when using this routine to save textures to disk for + * later re-loading. <P> + * + * Any mipmaps for the specified texture are currently discarded + * when it is written to disk, regardless of whether the underlying + * file format supports multiple mipmaps in a given file. + * + * @throws IOException if an error occurred during writing or no + * suitable writer was found + * @throws GLException if no OpenGL context was current or an + * OpenGL-related error occurred + */ + public static void write(Texture texture, File file) throws IOException, GLException { + if (texture.getTarget() != GL.GL_TEXTURE_2D) { + throw new GLException("Only GL_TEXTURE_2D textures are supported"); + } + + // First fetch the texture data + GL _gl = GLContext.getCurrentGL(); + if (!_gl.isGL2()) { + throw new GLException("Only GL2 supports fetching compressed images, GL: " + _gl); + } + GL2 gl = _gl.getGL2(); + + texture.bind(); + int internalFormat = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_INTERNAL_FORMAT); + int width = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_WIDTH); + int height = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_HEIGHT); + int border = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_BORDER); + TextureData data = null; + if (internalFormat == GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { + // Fetch using glGetCompressedTexImage + int size = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_COMPRESSED_IMAGE_SIZE); + ByteBuffer res = ByteBuffer.wrap(new byte[size]); + gl.glGetCompressedTexImage(GL.GL_TEXTURE_2D, 0, res); + data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, internalFormat, GL.GL_UNSIGNED_BYTE, + false, true, true, res, null); + } else { + int bytesPerPixel = 0; + int fetchedFormat = 0; + switch (internalFormat) { + case GL.GL_RGB: + case GL2.GL_BGR: + case GL.GL_RGB8: + bytesPerPixel = 3; + fetchedFormat = GL.GL_RGB; + break; + case GL.GL_RGBA: + case GL2.GL_BGRA: + case GL2.GL_ABGR_EXT: + case GL.GL_RGBA8: + bytesPerPixel = 4; + fetchedFormat = GL.GL_RGBA; + break; + default: + throw new IOException("Unsupported texture internal format 0x" + Integer.toHexString(internalFormat)); + } + + // Fetch using glGetTexImage + int packAlignment = glGetInteger(GL.GL_PACK_ALIGNMENT); + int packRowLength = glGetInteger(GL2.GL_PACK_ROW_LENGTH); + int packSkipRows = glGetInteger(GL2.GL_PACK_SKIP_ROWS); + int packSkipPixels = glGetInteger(GL2.GL_PACK_SKIP_PIXELS); + int packSwapBytes = glGetInteger(GL2.GL_PACK_SWAP_BYTES); + + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 0); + + ByteBuffer res = ByteBuffer.wrap(new byte[(width + (2 * border)) * + (height + (2 * border)) * + bytesPerPixel]); + if (DEBUG) { + System.out.println("Allocated buffer of size " + res.remaining() + " for fetched image (" + + ((fetchedFormat == GL.GL_RGB) ? "GL_RGB" : "GL_RGBA") + ")"); + } + gl.glGetTexImage(GL.GL_TEXTURE_2D, 0, fetchedFormat, GL.GL_UNSIGNED_BYTE, res); + + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, packAlignment); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, packRowLength); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes); + + data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, fetchedFormat, GL.GL_UNSIGNED_BYTE, + false, false, false, res, null); + + if (DEBUG) { + System.out.println("data.getPixelFormat() = " + + ((data.getPixelFormat() == GL.GL_RGB) ? "GL_RGB" : "GL_RGBA")); + } + } + + write(data, file); + } + + public static void write(TextureData data, File file) throws IOException, GLException { + for (Iterator iter = textureWriters.iterator(); iter.hasNext(); ) { + TextureWriter writer = (TextureWriter) iter.next(); + if (writer.write(file, data)) { + return; + } + } + + throw new IOException("No suitable texture writer found for "+file.getAbsolutePath()); + } + + //---------------------------------------------------------------------- + // SPI support + // + + /** Adds a TextureProvider to support reading of a new file + format. */ + public static void addTextureProvider(TextureProvider provider) { + // Must always add at the front so the ImageIO provider is last, + // so we don't accidentally use it instead of a user's possibly + // more optimal provider + textureProviders.add(0, provider); + } + + /** Adds a TextureWriter to support writing of a new file + format. */ + public static void addTextureWriter(TextureWriter writer) { + // Must always add at the front so the ImageIO writer is last, + // so we don't accidentally use it instead of a user's possibly + // more optimal writer + textureWriters.add(0, writer); + } + + //--------------------------------------------------------------------------- + // Global disabling of texture rectangle extension + // + + /** Toggles the use of the GL_ARB_texture_rectangle extension by the + TextureIO classes. By default, on hardware supporting this + extension, the TextureIO classes may use the + GL_ARB_texture_rectangle extension for non-power-of-two + textures. (If the hardware supports the + GL_ARB_texture_non_power_of_two extension, that one is + preferred.) In some situations, for example when writing + shaders, it is advantageous to force the texture target to + always be GL_TEXTURE_2D in order to have one version of the + shader, even at the expense of texture memory in the case where + NPOT textures are not supported. This method allows the use of + the GL_ARB_texture_rectangle extension to be turned off globally + for this purpose. The default is that the use of the extension + is enabled. */ + public static void setTexRectEnabled(boolean enabled) { + texRectEnabled = enabled; + } + + /** Indicates whether the GL_ARB_texture_rectangle extension is + allowed to be used for non-power-of-two textures; see {@link + #setTexRectEnabled setTexRectEnabled}. */ + public static boolean isTexRectEnabled() { + return texRectEnabled; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static List/*<TextureProvider>*/ textureProviders = new ArrayList/*<TextureProvider>*/(); + private static List/*<TextureWriter>*/ textureWriters = new ArrayList/*<TextureWriter>*/(); + + static { + /* + if(GLProfile.isAWTJOGLAvailable()) { + // ImageIO provider, the fall-back, must be the first one added + try { + // Use reflection to avoid compile-time dependencies on AWT-related classes + TextureProvider provider = (TextureProvider) + Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureProvider").newInstance(); + addTextureProvider(provider); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + } + } + */ + + // Other special-case providers + addTextureProvider(new DDSTextureProvider()); + addTextureProvider(new SGITextureProvider()); + addTextureProvider(new TGATextureProvider()); + + /* + // ImageIO writer, the fall-back, must be the first one added + if(GLProfile.isAWTJOGLAvailable()) { + try { + // Use reflection to avoid compile-time dependencies on AWT-related classes + TextureWriter writer = (TextureWriter) + Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureWriter").newInstance(); + addTextureWriter(writer); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + } + } + */ + + // Other special-case writers + addTextureWriter(new DDSTextureWriter()); + addTextureWriter(new SGITextureWriter()); + addTextureWriter(new TGATextureWriter()); + addTextureWriter(new NetPbmTextureWriter()); + } + + // Implementation methods + private static TextureData newTextureDataImpl(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (file == null) { + throw new IOException("File was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, file, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given file "+file.getAbsolutePath()); + } + + private static TextureData newTextureDataImpl(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (stream == null) { + throw new IOException("Stream was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + // Note: use of BufferedInputStream works around 4764639/4892246 + if (!(stream instanceof BufferedInputStream)) { + stream = new BufferedInputStream(stream); + } + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, stream, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given stream"); + } + + private static TextureData newTextureDataImpl(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (url == null) { + throw new IOException("URL was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, url, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given URL "+url); + } + + //---------------------------------------------------------------------- + // DDS provider -- supports files only for now + static class DDSTextureProvider implements TextureProvider { + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (DDS.equals(fileSuffix) || + DDS.equals(FileUtil.getFileSuffix(file))) { + DDSImage image = DDSImage.read(file); + return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); + } + + return null; + } + + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (DDS.equals(fileSuffix) || + DDSImage.isDDSImage(stream)) { + DDSImage image = DDSImage.read(stream); + return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); + } + + return null; + } + + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } finally { + stream.close(); + } + } + + private TextureData newTextureData(GLProfile glp, final DDSImage image, + int internalFormat, + int pixelFormat, + boolean mipmap) { + DDSImage.ImageInfo info = image.getMipMap(0); + if (pixelFormat == 0) { + switch (image.getPixelFormat()) { + case DDSImage.D3DFMT_R8G8B8: + pixelFormat = GL.GL_RGB; + break; + default: + pixelFormat = GL.GL_RGBA; + break; + } + } + if (info.isCompressed()) { + switch (info.getCompressionFormat()) { + case DDSImage.D3DFMT_DXT1: + internalFormat = GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + break; + case DDSImage.D3DFMT_DXT3: + internalFormat = GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case DDSImage.D3DFMT_DXT5: + internalFormat = GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + default: + throw new RuntimeException("Unsupported DDS compression format \"" + + DDSImage.getCompressionFormatName(info.getCompressionFormat()) + "\""); + } + } + if (internalFormat == 0) { + switch (image.getPixelFormat()) { + case DDSImage.D3DFMT_R8G8B8: + pixelFormat = GL.GL_RGB; + break; + default: + pixelFormat = GL.GL_RGBA; + break; + } + } + TextureData.Flusher flusher = new TextureData.Flusher() { + public void flush() { + image.close(); + } + }; + TextureData data; + if (mipmap && image.getNumMipMaps() > 0) { + Buffer[] mipmapData = new Buffer[image.getNumMipMaps()]; + for (int i = 0; i < image.getNumMipMaps(); i++) { + mipmapData[i] = image.getMipMap(i).getData(); + } + data = new TextureData(glp, internalFormat, + info.getWidth(), + info.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + info.isCompressed(), + true, + mipmapData, + flusher); + } else { + // Fix this up for the end user because we can't generate + // mipmaps for compressed textures + mipmap = false; + data = new TextureData(glp, internalFormat, + info.getWidth(), + info.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + info.isCompressed(), + true, + info.getData(), + flusher); + } + return data; + } + } + + //---------------------------------------------------------------------- + // Base class for SGI RGB and TGA image providers + static abstract class StreamBasedTextureProvider implements TextureProvider { + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream inStream = new BufferedInputStream(new FileInputStream(file)); + try { + // The SGIImage and TGAImage implementations use InputStreams + // anyway so there isn't much point in having a separate code + // path for files + return newTextureData(glp, inStream, + internalFormat, + pixelFormat, + mipmap, + ((fileSuffix != null) ? fileSuffix : FileUtil.getFileSuffix(file))); + } finally { + inStream.close(); + } + } + + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } finally { + stream.close(); + } + } + } + + //---------------------------------------------------------------------- + // SGI RGB image provider + static class SGITextureProvider extends StreamBasedTextureProvider { + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (SGI.equals(fileSuffix) || + SGI_RGB.equals(fileSuffix) || + SGIImage.isSGIImage(stream)) { + SGIImage image = SGIImage.read(stream); + if (pixelFormat == 0) { + pixelFormat = image.getFormat(); + } + if (internalFormat == 0) { + internalFormat = image.getFormat(); + } + return new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + false, + false, + ByteBuffer.wrap(image.getData()), + null); + } + + return null; + } + } + + //---------------------------------------------------------------------- + // TGA (Targa) image provider + static class TGATextureProvider extends StreamBasedTextureProvider { + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (TGA.equals(fileSuffix)) { + TGAImage image = TGAImage.read(stream); + if (pixelFormat == 0) { + pixelFormat = image.getGLFormat(); + } + if (internalFormat == 0) { + GL gl = GLContext.getCurrentGL(); + if(gl.isGL2()) { + internalFormat = GL.GL_RGBA8; + } else { + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + } + } + return new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + false, + false, + image.getData(), + null); + } + + return null; + } + } + + //---------------------------------------------------------------------- + // DDS texture writer + // + static class DDSTextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + if (DDS.equals(FileUtil.getFileSuffix(file))) { + // See whether the DDS writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if (pixelType != GL.GL_BYTE && + pixelType != GL.GL_UNSIGNED_BYTE) { + throw new IOException("DDS writer only supports byte / unsigned byte textures"); + } + + int d3dFormat = 0; + // FIXME: some of these are probably not completely correct and would require swizzling + switch (pixelFormat) { + case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; + case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; + default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); + } + + ByteBuffer[] mipmaps = null; + if (data.getMipmapData() != null) { + mipmaps = new ByteBuffer[data.getMipmapData().length]; + for (int i = 0; i < mipmaps.length; i++) { + mipmaps[i] = (ByteBuffer) data.getMipmapData()[i]; + } + } else { + mipmaps = new ByteBuffer[] { (ByteBuffer) data.getBuffer() }; + } + + DDSImage image = DDSImage.createFromData(d3dFormat, + data.getWidth(), + data.getHeight(), + mipmaps); + image.write(file); + return true; + } + + return false; + } + } + + //---------------------------------------------------------------------- + // SGI (rgb) texture writer + // + static class SGITextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + String fileSuffix = FileUtil.getFileSuffix(file); + if (SGI.equals(fileSuffix) || + SGI_RGB.equals(fileSuffix)) { + // See whether the SGI writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + ByteBuffer buf = ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0]); + byte[] bytes; + if (buf.hasArray()) { + bytes = buf.array(); + } else { + buf.rewind(); + bytes = new byte[buf.remaining()]; + buf.get(bytes); + buf.rewind(); + } + + SGIImage image = SGIImage.createFromData(data.getWidth(), + data.getHeight(), + (pixelFormat == GL.GL_RGBA), + bytes); + image.write(file, false); + return true; + } + + throw new IOException("SGI writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } + + return false; + } + } + + //---------------------------------------------------------------------- + // TGA (Targa) texture writer + + static class TGATextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + if (TGA.equals(FileUtil.getFileSuffix(file))) { + // See whether the TGA writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + ByteBuffer buf = ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0]); + // Must reverse order of red and blue channels to get correct results + int skip = ((pixelFormat == GL.GL_RGB) ? 3 : 4); + for (int i = 0; i < buf.remaining(); i += skip) { + byte red = buf.get(i + 0); + byte blue = buf.get(i + 2); + buf.put(i + 0, blue); + buf.put(i + 2, red); + } + + TGAImage image = TGAImage.createFromData(data.getWidth(), + data.getHeight(), + (pixelFormat == GL.GL_RGBA), + false, + ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0])); + image.write(file); + return true; + } + + throw new IOException("TGA writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } + + return false; + } + } + + //---------------------------------------------------------------------- + // Helper routines + // + + private static int glGetInteger(int pname) { + int[] tmp = new int[1]; + GL gl = GLContext.getCurrentGL(); + gl.glGetIntegerv(pname, tmp, 0); + return tmp[0]; + } + + private static int glGetTexLevelParameteri(GL2 gl, int target, int level, int pname) { + int[] tmp = new int[1]; + gl.glGetTexLevelParameteriv(target, 0, pname, tmp, 0); + return tmp[0]; + } + + private static String toLowerCase(String arg) { + if (arg == null) { + return null; + } + + return arg.toLowerCase(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javase b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javase new file mode 100755 index 000000000..3e6f66f10 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureIO.java.javase @@ -0,0 +1,1258 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture; + +import java.io.*; +import java.net.*; +import java.nio.*; +import java.util.*; + +import javax.media.opengl.*; +import javax.media.opengl.glu.*; +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.spi.*; + +/** <P> Provides input and output facilities for both loading OpenGL + textures from disk and streams as well as writing textures already + in memory back to disk. </P> + + <P> The TextureIO class supports an arbitrary number of plug-in + readers and writers via TextureProviders and TextureWriters. + TextureProviders know how to produce TextureData objects from + files, InputStreams and URLs. TextureWriters know how to write + TextureData objects to disk in various file formats. The + TextureData class represents the raw data of the texture before it + has been converted to an OpenGL texture object. The Texture class + represents the OpenGL texture object and provides easy facilities + for using the texture. </P> + + <P> There are several built-in TextureProviders and TextureWriters + supplied with the TextureIO implementation. The most basic + provider uses the platform's Image I/O facilities to read in a + BufferedImage and convert it to a texture. This is the baseline + provider and is registered so that it is the last one consulted. + All others are asked first to open a given file. </P> + + <P> There are three other providers registered by default as of + the time of this writing. One handles SGI RGB (".sgi", ".rgb") + images from both files and streams. One handles DirectDraw Surface + (".dds") images read from files, though can not read these images + from streams. One handles Targa (".tga") images read from both + files and streams. These providers are executed in an arbitrary + order. Some of these providers require the file's suffix to either + be specified via the newTextureData methods or for the file to be + named with the appropriate suffix. In general a file suffix should + be provided to the newTexture and newTextureData methods if at all + possible. </P> + + <P> Note that additional TextureProviders, if reading images from + InputStreams, must use the mark()/reset() methods on InputStream + when probing for e.g. magic numbers at the head of the file to + make sure not to disturb the state of the InputStream for + downstream TextureProviders. </P> + + <P> There are analogous TextureWriters provided for writing + textures back to disk if desired. As of this writing, there are + four TextureWriters registered by default: one for Targa files, + one for SGI RGB files, one for DirectDraw surface (.dds) files, + and one for ImageIO-supplied formats such as .jpg and .png. Some + of these writers have certain limitations such as only being able + to write out textures stored in GL_RGB or GL_RGBA format. The DDS + writer supports fetching and writing to disk of texture data in + DXTn compressed format. Whether this will occur is dependent on + whether the texture's internal format is one of the DXTn + compressed formats and whether the target file is .dds format. +*/ + +public class TextureIO { + /** Constant which can be used as a file suffix to indicate a + DirectDraw Surface file. */ + public static final String DDS = "dds"; + + /** Constant which can be used as a file suffix to indicate an SGI + RGB file. */ + public static final String SGI = "sgi"; + + /** Constant which can be used as a file suffix to indicate an SGI + RGB file. */ + public static final String SGI_RGB = "rgb"; + + /** Constant which can be used as a file suffix to indicate a GIF + file. */ + public static final String GIF = "gif"; + + /** Constant which can be used as a file suffix to indicate a JPEG + file. */ + public static final String JPG = "jpg"; + + /** Constant which can be used as a file suffix to indicate a PNG + file. */ + public static final String PNG = "png"; + + /** Constant which can be used as a file suffix to indicate a Targa + file. */ + public static final String TGA = "tga"; + + /** Constant which can be used as a file suffix to indicate a TIFF + file. */ + public static final String TIFF = "tiff"; + + private static final boolean DEBUG = Debug.debug("TextureIO"); + + // For manually disabling the use of the texture rectangle + // extensions so you know the texture target is GL_TEXTURE_2D; this + // is useful for shader writers (thanks to Chris Campbell for this + // observation) + private static boolean texRectEnabled = true; + + //---------------------------------------------------------------------- + // methods that *do not* require a current context + // These methods assume RGB or RGBA textures. + // Some texture providers may not recognize the file format unless + // the fileSuffix is specified, so it is strongly recommended to + // specify it wherever it is known. + // Some texture providers may also only support one kind of input, + // i.e., reading from a file as opposed to a stream. + + /** + * Creates a TextureData from the given file. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param file the file from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the file, or null if none of the + * registered texture providers could read the file + * @throws IOException if an error occurred while reading the file + */ + public static TextureData newTextureData(GLProfile glp, File file, + boolean mipmap, + String fileSuffix) throws IOException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(file); + } + return newTextureDataImpl(glp, file, 0, 0, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given stream. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param stream the stream from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the stream, or null if none of the + * registered texture providers could read the stream + * @throws IOException if an error occurred while reading the stream + */ + public static TextureData newTextureData(GLProfile glp, InputStream stream, + boolean mipmap, + String fileSuffix) throws IOException { + return newTextureDataImpl(glp, stream, 0, 0, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given URL. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param url the URL from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the URL, or null if none of the + * registered texture providers could read the URL + * @throws IOException if an error occurred while reading the URL + */ + public static TextureData newTextureData(GLProfile glp, URL url, + boolean mipmap, + String fileSuffix) throws IOException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + return newTextureDataImpl(glp, url, 0, 0, mipmap, fileSuffix); + } + + //---------------------------------------------------------------------- + // These methods make no assumption about the OpenGL internal format + // or pixel format of the texture; they must be specified by the + // user. It is not allowed to supply 0 (indicating no preference) + // for either the internalFormat or the pixelFormat; + // IllegalArgumentException will be thrown in this case. + + /** + * Creates a TextureData from the given file, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param file the file from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the file, or null if none of the + * registered texture providers could read the file + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the file + */ + public static TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(file); + } + + return newTextureDataImpl(glp, file, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given stream, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param stream the stream from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the stream, or null if none of the + * registered texture providers could read the stream + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the stream + */ + public static TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + return newTextureDataImpl(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + /** + * Creates a TextureData from the given URL, using the specified + * OpenGL internal format and pixel format for the texture which + * will eventually result. The internalFormat and pixelFormat must + * be specified and may not be zero; to use default values, use the + * variant of this method which does not take these arguments. Does + * no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param url the URL from which to read the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @return the texture data from the URL, or null if none of the + * registered texture providers could read the URL + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + * @throws IOException if an error occurred while reading the URL + */ + public static TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException, IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + + return newTextureDataImpl(glp, url, internalFormat, pixelFormat, mipmap, fileSuffix); + } + + //---------------------------------------------------------------------- + // methods that *do* require a current context + // + + /** + * Creates an OpenGL texture object from the specified TextureData + * using the current OpenGL context. + * + * @param data the texture data to turn into an OpenGL texture + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + * @throws IllegalArgumentException if the passed TextureData was null + */ + public static Texture newTexture(TextureData data) throws GLException, IllegalArgumentException { + if (data == null) { + throw new IllegalArgumentException("Null TextureData"); + } + return new Texture(data); + } + + /** + * Creates an OpenGL texture object from the specified file using + * the current OpenGL context. + * + * @param file the file from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @throws IOException if an error occurred while reading the file + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(File file, boolean mipmap) throws IOException, GLException { + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, file, mipmap, FileUtil.getFileSuffix(file)); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object from the specified stream using + * the current OpenGL context. + * + * @param stream the stream from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @throws IOException if an error occurred while reading the stream + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(InputStream stream, boolean mipmap, String fileSuffix) throws IOException, GLException { + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, stream, mipmap, fileSuffix); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object from the specified URL using the + * current OpenGL context. + * + * @param url the URL from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @param fileSuffix the suffix of the file name to be used as a + * hint of the file format to the underlying + * texture provider, or null if none and should be + * auto-detected (some texture providers do not + * support this) + * @throws IOException if an error occurred while reading the URL + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(URL url, boolean mipmap, String fileSuffix) throws IOException, GLException { + if (fileSuffix == null) { + fileSuffix = FileUtil.getFileSuffix(url.getPath()); + } + GLProfile glp = GLContext.getCurrentGL().getGLProfile(); + TextureData data = newTextureData(glp, url, mipmap, fileSuffix); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + /** + * Creates an OpenGL texture object associated with the given OpenGL + * texture target using the current OpenGL context. The texture has + * no initial data. This is used, for example, to construct cube + * maps out of multiple TextureData objects. + * + * @param target the OpenGL target type, eg GL.GL_TEXTURE_2D, + * GL.GL_TEXTURE_RECTANGLE_ARB + * + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(int target) throws GLException { + return new Texture(target); + } + + /** + * Wraps an OpenGL texture ID from an external library and allows + * some of the base methods from the Texture class, such as + * binding and querying of texture coordinates, to be used with + * it. Attempts to update such textures' contents will yield + * undefined results. + * + * @param textureID the OpenGL texture object to wrap + * @param target the OpenGL texture target, eg GL.GL_TEXTURE_2D, + * GL2.GL_TEXTURE_RECTANGLE + * @param texWidth the width of the texture in pixels + * @param texHeight the height of the texture in pixels + * @param imgWidth the width of the image within the texture in + * pixels (if the content is a sub-rectangle in the upper + * left corner); otherwise, pass in texWidth + * @param imgHeight the height of the image within the texture in + * pixels (if the content is a sub-rectangle in the upper + * left corner); otherwise, pass in texHeight + * @param mustFlipVertically indicates whether the texture + * coordinates must be flipped vertically + * in order to properly display the + * texture + */ + public static Texture newTexture(int textureID, + int target, + int texWidth, + int texHeight, + int imgWidth, + int imgHeight, + boolean mustFlipVertically) { + return new Texture(textureID, + target, + texWidth, + texHeight, + imgWidth, + imgHeight, + mustFlipVertically); + } + + /** + * Writes the given texture to a file. The type of the file is + * inferred from its suffix. An OpenGL context must be current in + * order to fetch the texture data back from the OpenGL pipeline. + * This method causes the specified Texture to be bound to the + * GL_TEXTURE_2D state. If no suitable writer for the requested file + * format was found, throws an IOException. <P> + * + * Reasonable attempts are made to produce good results in the + * resulting images. The Targa, SGI and ImageIO writers produce + * results in the correct vertical orientation for those file + * formats. The DDS writer performs no vertical flip of the data, + * even in uncompressed mode. (It is impossible to perform such a + * vertical flip with compressed data.) Applications should keep + * this in mind when using this routine to save textures to disk for + * later re-loading. <P> + * + * Any mipmaps for the specified texture are currently discarded + * when it is written to disk, regardless of whether the underlying + * file format supports multiple mipmaps in a given file. + * + * @throws IOException if an error occurred during writing or no + * suitable writer was found + * @throws GLException if no OpenGL context was current or an + * OpenGL-related error occurred + */ + public static void write(Texture texture, File file) throws IOException, GLException { + if (texture.getTarget() != GL.GL_TEXTURE_2D) { + throw new GLException("Only GL_TEXTURE_2D textures are supported"); + } + + // First fetch the texture data + GL _gl = GLContext.getCurrentGL(); + if (!_gl.isGL2()) { + throw new GLException("Only GL2 supports fetching compressed images, GL: " + _gl); + } + GL2 gl = _gl.getGL2(); + + texture.bind(); + int internalFormat = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_INTERNAL_FORMAT); + int width = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_WIDTH); + int height = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_HEIGHT); + int border = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_BORDER); + TextureData data = null; + if (internalFormat == GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT || + internalFormat == GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT) { + // Fetch using glGetCompressedTexImage + int size = glGetTexLevelParameteri(gl, GL.GL_TEXTURE_2D, 0, GL2.GL_TEXTURE_COMPRESSED_IMAGE_SIZE); + ByteBuffer res = ByteBuffer.allocate(size); + gl.glGetCompressedTexImage(GL.GL_TEXTURE_2D, 0, res); + data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, internalFormat, GL.GL_UNSIGNED_BYTE, + false, true, true, res, null); + } else { + int bytesPerPixel = 0; + int fetchedFormat = 0; + switch (internalFormat) { + case GL.GL_RGB: + case GL2.GL_BGR: + case GL.GL_RGB8: + bytesPerPixel = 3; + fetchedFormat = GL.GL_RGB; + break; + case GL.GL_RGBA: + case GL2.GL_BGRA: + case GL2.GL_ABGR_EXT: + case GL.GL_RGBA8: + bytesPerPixel = 4; + fetchedFormat = GL.GL_RGBA; + break; + default: + throw new IOException("Unsupported texture internal format 0x" + Integer.toHexString(internalFormat)); + } + + // Fetch using glGetTexImage + int packAlignment = glGetInteger(GL.GL_PACK_ALIGNMENT); + int packRowLength = glGetInteger(GL2.GL_PACK_ROW_LENGTH); + int packSkipRows = glGetInteger(GL2.GL_PACK_SKIP_ROWS); + int packSkipPixels = glGetInteger(GL2.GL_PACK_SKIP_PIXELS); + int packSwapBytes = glGetInteger(GL2.GL_PACK_SWAP_BYTES); + + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, 0); + + ByteBuffer res = ByteBuffer.allocate((width + (2 * border)) * + (height + (2 * border)) * + bytesPerPixel); + if (DEBUG) { + System.out.println("Allocated buffer of size " + res.remaining() + " for fetched image (" + + ((fetchedFormat == GL.GL_RGB) ? "GL_RGB" : "GL_RGBA") + ")"); + } + gl.glGetTexImage(GL.GL_TEXTURE_2D, 0, fetchedFormat, GL.GL_UNSIGNED_BYTE, res); + + gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, packAlignment); + gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, packRowLength); + gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, packSkipRows); + gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, packSkipPixels); + gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, packSwapBytes); + + data = new TextureData(gl.getGLProfile(), internalFormat, width, height, border, fetchedFormat, GL.GL_UNSIGNED_BYTE, + false, false, false, res, null); + + if (DEBUG) { + System.out.println("data.getPixelFormat() = " + + ((data.getPixelFormat() == GL.GL_RGB) ? "GL_RGB" : "GL_RGBA")); + } + } + + write(data, file); + } + + public static void write(TextureData data, File file) throws IOException, GLException { + for (Iterator iter = textureWriters.iterator(); iter.hasNext(); ) { + TextureWriter writer = (TextureWriter) iter.next(); + if (writer.write(file, data)) { + return; + } + } + + throw new IOException("No suitable texture writer found for "+file.getAbsolutePath()); + } + + //---------------------------------------------------------------------- + // SPI support + // + + /** Adds a TextureProvider to support reading of a new file + format. */ + public static void addTextureProvider(TextureProvider provider) { + // Must always add at the front so the ImageIO provider is last, + // so we don't accidentally use it instead of a user's possibly + // more optimal provider + textureProviders.add(0, provider); + } + + /** Adds a TextureWriter to support writing of a new file + format. */ + public static void addTextureWriter(TextureWriter writer) { + // Must always add at the front so the ImageIO writer is last, + // so we don't accidentally use it instead of a user's possibly + // more optimal writer + textureWriters.add(0, writer); + } + + //--------------------------------------------------------------------------- + // Global disabling of texture rectangle extension + // + + /** Toggles the use of the GL_ARB_texture_rectangle extension by the + TextureIO classes. By default, on hardware supporting this + extension, the TextureIO classes may use the + GL_ARB_texture_rectangle extension for non-power-of-two + textures. (If the hardware supports the + GL_ARB_texture_non_power_of_two extension, that one is + preferred.) In some situations, for example when writing + shaders, it is advantageous to force the texture target to + always be GL_TEXTURE_2D in order to have one version of the + shader, even at the expense of texture memory in the case where + NPOT textures are not supported. This method allows the use of + the GL_ARB_texture_rectangle extension to be turned off globally + for this purpose. The default is that the use of the extension + is enabled. */ + public static void setTexRectEnabled(boolean enabled) { + texRectEnabled = enabled; + } + + /** Indicates whether the GL_ARB_texture_rectangle extension is + allowed to be used for non-power-of-two textures; see {@link + #setTexRectEnabled setTexRectEnabled}. */ + public static boolean isTexRectEnabled() { + return texRectEnabled; + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static List/*<TextureProvider>*/ textureProviders = new ArrayList/*<TextureProvider>*/(); + private static List/*<TextureWriter>*/ textureWriters = new ArrayList/*<TextureWriter>*/(); + + static { + // ImageIO provider, the fall-back, must be the first one added + if(GLProfile.isAWTJOGLAvailable()) { + try { + // Use reflection to avoid compile-time dependencies on AWT-related classes + TextureProvider provider = (TextureProvider) + Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureProvider").newInstance(); + addTextureProvider(provider); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + } + } + + // Other special-case providers + addTextureProvider(new DDSTextureProvider()); + addTextureProvider(new SGITextureProvider()); + addTextureProvider(new TGATextureProvider()); + + // ImageIO writer, the fall-back, must be the first one added + if(GLProfile.isAWTJOGLAvailable()) { + try { + // Use reflection to avoid compile-time dependencies on AWT-related classes + TextureWriter writer = (TextureWriter) + Class.forName("com.jogamp.opengl.util.texture.spi.awt.IIOTextureWriter").newInstance(); + addTextureWriter(writer); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + } catch (Error e) { + if (DEBUG) { + e.printStackTrace(); + } + } + } + + // Other special-case writers + addTextureWriter(new DDSTextureWriter()); + addTextureWriter(new SGITextureWriter()); + addTextureWriter(new TGATextureWriter()); + addTextureWriter(new NetPbmTextureWriter()); + } + + // Implementation methods + private static TextureData newTextureDataImpl(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (file == null) { + throw new IOException("File was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, file, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given file "+file.getAbsolutePath()); + } + + private static TextureData newTextureDataImpl(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (stream == null) { + throw new IOException("Stream was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + // Note: use of BufferedInputStream works around 4764639/4892246 + if (!(stream instanceof BufferedInputStream)) { + stream = new BufferedInputStream(stream); + } + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, stream, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given stream"); + } + + private static TextureData newTextureDataImpl(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (url == null) { + throw new IOException("URL was null"); + } + + fileSuffix = toLowerCase(fileSuffix); + + for (Iterator iter = textureProviders.iterator(); iter.hasNext(); ) { + TextureProvider provider = (TextureProvider) iter.next(); + TextureData data = provider.newTextureData(glp, url, + internalFormat, + pixelFormat, + mipmap, + fileSuffix); + if (data != null) { + return data; + } + } + + throw new IOException("No suitable reader for given URL "+url); + } + + //---------------------------------------------------------------------- + // DDS provider -- supports files only for now + static class DDSTextureProvider implements TextureProvider { + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (DDS.equals(fileSuffix) || + DDS.equals(FileUtil.getFileSuffix(file))) { + DDSImage image = DDSImage.read(file); + return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); + } + + return null; + } + + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (DDS.equals(fileSuffix) || + DDSImage.isDDSImage(stream)) { + byte[] data = StreamUtil.readAll2Array(stream); + ByteBuffer buf = ByteBuffer.wrap(data); + DDSImage image = DDSImage.read(buf); + return newTextureData(glp, image, internalFormat, pixelFormat, mipmap); + } + + return null; + } + + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } finally { + stream.close(); + } + } + + private TextureData newTextureData(GLProfile glp, final DDSImage image, + int internalFormat, + int pixelFormat, + boolean mipmap) { + DDSImage.ImageInfo info = image.getMipMap(0); + if (pixelFormat == 0) { + switch (image.getPixelFormat()) { + case DDSImage.D3DFMT_R8G8B8: + pixelFormat = GL.GL_RGB; + break; + default: + pixelFormat = GL.GL_RGBA; + break; + } + } + if (info.isCompressed()) { + switch (info.getCompressionFormat()) { + case DDSImage.D3DFMT_DXT1: + internalFormat = GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + break; + case DDSImage.D3DFMT_DXT3: + internalFormat = GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + case DDSImage.D3DFMT_DXT5: + internalFormat = GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + default: + throw new RuntimeException("Unsupported DDS compression format \"" + + DDSImage.getCompressionFormatName(info.getCompressionFormat()) + "\""); + } + } + if (internalFormat == 0) { + switch (image.getPixelFormat()) { + case DDSImage.D3DFMT_R8G8B8: + pixelFormat = GL.GL_RGB; + break; + default: + pixelFormat = GL.GL_RGBA; + break; + } + } + TextureData.Flusher flusher = new TextureData.Flusher() { + public void flush() { + image.close(); + } + }; + TextureData data; + if (mipmap && image.getNumMipMaps() > 0) { + Buffer[] mipmapData = new Buffer[image.getNumMipMaps()]; + for (int i = 0; i < image.getNumMipMaps(); i++) { + mipmapData[i] = image.getMipMap(i).getData(); + } + data = new TextureData(glp, internalFormat, + info.getWidth(), + info.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + info.isCompressed(), + true, + mipmapData, + flusher); + } else { + // Fix this up for the end user because we can't generate + // mipmaps for compressed textures + mipmap = false; + data = new TextureData(glp, internalFormat, + info.getWidth(), + info.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + info.isCompressed(), + true, + info.getData(), + flusher); + } + return data; + } + } + + //---------------------------------------------------------------------- + // Base class for SGI RGB and TGA image providers + static abstract class StreamBasedTextureProvider implements TextureProvider { + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream inStream = new BufferedInputStream(new FileInputStream(file)); + try { + // The SGIImage and TGAImage implementations use InputStreams + // anyway so there isn't much point in having a separate code + // path for files + return newTextureData(glp, inStream, + internalFormat, + pixelFormat, + mipmap, + ((fileSuffix != null) ? fileSuffix : FileUtil.getFileSuffix(file))); + } finally { + inStream.close(); + } + } + + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream stream = new BufferedInputStream(url.openStream()); + try { + return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } finally { + stream.close(); + } + } + } + + //---------------------------------------------------------------------- + // SGI RGB image provider + static class SGITextureProvider extends StreamBasedTextureProvider { + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (SGI.equals(fileSuffix) || + SGI_RGB.equals(fileSuffix) || + SGIImage.isSGIImage(stream)) { + SGIImage image = SGIImage.read(stream); + if (pixelFormat == 0) { + pixelFormat = image.getFormat(); + } + if (internalFormat == 0) { + internalFormat = image.getFormat(); + } + return new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + false, + false, + ByteBuffer.wrap(image.getData()), + null); + } + + return null; + } + } + + //---------------------------------------------------------------------- + // TGA (Targa) image provider + static class TGATextureProvider extends StreamBasedTextureProvider { + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + if (TGA.equals(fileSuffix)) { + TGAImage image = TGAImage.read(stream); + if (pixelFormat == 0) { + pixelFormat = image.getGLFormat(); + } + if (internalFormat == 0) { + GL gl = GLContext.getCurrentGL(); + if(gl.isGL2()) { + internalFormat = GL.GL_RGBA8; + } else { + internalFormat = (image.getBytesPerPixel()==4)?GL.GL_RGBA:GL.GL_RGB; + } + } + return new TextureData(glp, internalFormat, + image.getWidth(), + image.getHeight(), + 0, + pixelFormat, + GL.GL_UNSIGNED_BYTE, + mipmap, + false, + false, + image.getData(), + null); + } + + return null; + } + } + + //---------------------------------------------------------------------- + // DDS texture writer + // + static class DDSTextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + if (DDS.equals(FileUtil.getFileSuffix(file))) { + // See whether the DDS writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if (pixelType != GL.GL_BYTE && + pixelType != GL.GL_UNSIGNED_BYTE) { + throw new IOException("DDS writer only supports byte / unsigned byte textures"); + } + + int d3dFormat = 0; + // FIXME: some of these are probably not completely correct and would require swizzling + switch (pixelFormat) { + case GL.GL_RGB: d3dFormat = DDSImage.D3DFMT_R8G8B8; break; + case GL.GL_RGBA: d3dFormat = DDSImage.D3DFMT_A8R8G8B8; break; + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: d3dFormat = DDSImage.D3DFMT_DXT1; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: throw new IOException("RGBA DXT1 not yet supported"); + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: d3dFormat = DDSImage.D3DFMT_DXT3; break; + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: d3dFormat = DDSImage.D3DFMT_DXT5; break; + default: throw new IOException("Unsupported pixel format 0x" + Integer.toHexString(pixelFormat) + " by DDS writer"); + } + + ByteBuffer[] mipmaps = null; + if (data.getMipmapData() != null) { + mipmaps = new ByteBuffer[data.getMipmapData().length]; + for (int i = 0; i < mipmaps.length; i++) { + mipmaps[i] = (ByteBuffer) data.getMipmapData()[i]; + } + } else { + mipmaps = new ByteBuffer[] { (ByteBuffer) data.getBuffer() }; + } + + DDSImage image = DDSImage.createFromData(d3dFormat, + data.getWidth(), + data.getHeight(), + mipmaps); + image.write(file); + return true; + } + + return false; + } + } + + //---------------------------------------------------------------------- + // SGI (rgb) texture writer + // + static class SGITextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + String fileSuffix = FileUtil.getFileSuffix(file); + if (SGI.equals(fileSuffix) || + SGI_RGB.equals(fileSuffix)) { + // See whether the SGI writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + ByteBuffer buf = ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0]); + byte[] bytes; + if (buf.hasArray()) { + bytes = buf.array(); + } else { + buf.rewind(); + bytes = new byte[buf.remaining()]; + buf.get(bytes); + buf.rewind(); + } + + SGIImage image = SGIImage.createFromData(data.getWidth(), + data.getHeight(), + (pixelFormat == GL.GL_RGBA), + bytes); + image.write(file, false); + return true; + } + + throw new IOException("SGI writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } + + return false; + } + } + + //---------------------------------------------------------------------- + // TGA (Targa) texture writer + + static class TGATextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + if (TGA.equals(FileUtil.getFileSuffix(file))) { + // See whether the TGA writer can handle this TextureData + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + ByteBuffer buf = ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0]); + // Must reverse order of red and blue channels to get correct results + int skip = ((pixelFormat == GL.GL_RGB) ? 3 : 4); + for (int i = 0; i < buf.remaining(); i += skip) { + byte red = buf.get(i + 0); + byte blue = buf.get(i + 2); + buf.put(i + 0, blue); + buf.put(i + 2, red); + } + + TGAImage image = TGAImage.createFromData(data.getWidth(), + data.getHeight(), + (pixelFormat == GL.GL_RGBA), + false, + ((data.getBuffer() != null) ? + (ByteBuffer) data.getBuffer() : + (ByteBuffer) data.getMipmapData()[0])); + image.write(file); + return true; + } + + throw new IOException("TGA writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } + + return false; + } + } + + //---------------------------------------------------------------------- + // Helper routines + // + + private static int glGetInteger(int pname) { + int[] tmp = new int[1]; + GL gl = GLContext.getCurrentGL(); + gl.glGetIntegerv(pname, tmp, 0); + return tmp[0]; + } + + private static int glGetTexLevelParameteri(GL2 gl, int target, int level, int pname) { + int[] tmp = new int[1]; + gl.glGetTexLevelParameteriv(target, 0, pname, tmp, 0); + return tmp[0]; + } + + private static String toLowerCase(String arg) { + if (arg == null) { + return null; + } + + return arg.toLowerCase(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java new file mode 100755 index 000000000..39ec74b97 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureData.java @@ -0,0 +1,498 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + */ + +package com.jogamp.opengl.util.texture.awt; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Transparency; +import java.awt.color.*; +import java.awt.image.*; +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.texture.*; + +public class AWTTextureData extends TextureData { + // Mechanism for lazily converting input BufferedImages with custom + // ColorModels to standard ones for uploading to OpenGL, as well as + // backing off from the optimizations of hoping that either + // GL_EXT_abgr or OpenGL 1.2 are present + private BufferedImage imageForLazyCustomConversion; + private boolean expectingEXTABGR; + private boolean expectingGL12; + + private static final ColorModel rgbaColorModel = + new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + new int[] {8, 8, 8, 8}, true, true, + Transparency.TRANSLUCENT, + DataBuffer.TYPE_BYTE); + private static final ColorModel rgbColorModel = + new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + new int[] {8, 8, 8, 0}, false, false, + Transparency.OPAQUE, + DataBuffer.TYPE_BYTE); + + + /** + * Constructs a new TextureData object with the specified parameters + * and data contained in the given BufferedImage. The resulting + * TextureData "wraps" the contents of the BufferedImage, so if a + * modification is made to the BufferedImage between the time the + * TextureData is constructed and when a Texture is made from the + * TextureData, that modification will be visible in the resulting + * Texture. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param internalFormat the OpenGL internal format for the + * resulting texture; may be 0, in which case + * it is inferred from the image's type + * @param pixelFormat the OpenGL internal format for the + * resulting texture; may be 0, in which case + * it is inferred from the image's type (note: + * this argument is currently always ignored) + * @param mipmap indicates whether mipmaps should be + * autogenerated (using GLU) for the resulting + * texture + * @param image the image containing the texture data + */ + public AWTTextureData(GLProfile glp, + int internalFormat, + int pixelFormat, + boolean mipmap, + BufferedImage image) { + super(glp); + if (internalFormat == 0) { + this.internalFormat = image.getColorModel().hasAlpha() ? GL.GL_RGBA : GL.GL_RGB; + } else { + this.internalFormat = internalFormat; + } + createFromImage(glp, image); + this.mipmap = mipmap; + if (buffer != null) { + estimatedMemorySize = estimatedMemorySize(buffer); + } else { + // In the lazy custom conversion case we don't yet have a buffer + if (imageForLazyCustomConversion != null) { + estimatedMemorySize = estimatedMemorySize(wrapImageDataBuffer(imageForLazyCustomConversion)); + } + } + } + + /** Returns the intended OpenGL pixel format of the texture data. */ + public int getPixelFormat() { + if (imageForLazyCustomConversion != null) { + if (!((expectingEXTABGR && haveEXTABGR) || + (expectingGL12 && haveGL12))) { + revertPixelFormatAndType(); + } + } + return pixelFormat; + } + /** Returns the intended OpenGL pixel type of the texture data. */ + public int getPixelType() { + if (imageForLazyCustomConversion != null) { + if (!((expectingEXTABGR && haveEXTABGR) || + (expectingGL12 && haveGL12))) { + revertPixelFormatAndType(); + } + } + return pixelType; + } + + /** Returns the texture data, or null if it is specified as a set of mipmaps. */ + public Buffer getBuffer() { + if (imageForLazyCustomConversion != null) { + if (!((expectingEXTABGR && haveEXTABGR) || + (expectingGL12 && haveGL12))) { + revertPixelFormatAndType(); + // Must present the illusion to the end user that we are simply + // wrapping the input BufferedImage + createFromCustom(imageForLazyCustomConversion); + } + } + return buffer; + } + + private void createFromImage(GLProfile glp, BufferedImage image) { + pixelType = 0; // Determine from image + mustFlipVertically = true; + + width = image.getWidth(); + height = image.getHeight(); + + int scanlineStride; + + SampleModel sm = image.getRaster().getSampleModel(); + if (sm instanceof SinglePixelPackedSampleModel) { + scanlineStride = + ((SinglePixelPackedSampleModel)sm).getScanlineStride(); + } else if (sm instanceof MultiPixelPackedSampleModel) { + scanlineStride = + ((MultiPixelPackedSampleModel)sm).getScanlineStride(); + } else if (sm instanceof ComponentSampleModel) { + scanlineStride = + ((ComponentSampleModel)sm).getScanlineStride(); + } else { + // This will only happen for TYPE_CUSTOM anyway + setupLazyCustomConversion(image); + return; + } + + width = image.getWidth(); + height = image.getHeight(); + + if (glp.isGL2GL3()) { + switch (image.getType()) { + case BufferedImage.TYPE_INT_RGB: + pixelFormat = GL2GL3.GL_BGRA; + pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + rowLength = scanlineStride; + alignment = 4; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_INT_ARGB_PRE: + pixelFormat = GL2GL3.GL_BGRA; + pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + rowLength = scanlineStride; + alignment = 4; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_INT_BGR: + pixelFormat = GL.GL_RGBA; + pixelType = GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; + rowLength = scanlineStride; + alignment = 4; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_3BYTE_BGR: + { + // we can pass the image data directly to OpenGL only if + // we have an integral number of pixels in each scanline + if ((scanlineStride % 3) == 0) { + pixelFormat = GL2GL3.GL_BGR; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 3; + alignment = 1; + } else { + setupLazyCustomConversion(image); + return; + } + } + break; + case BufferedImage.TYPE_4BYTE_ABGR_PRE: + { + // we can pass the image data directly to OpenGL only if + // we have an integral number of pixels in each scanline + // and only if the GL_EXT_abgr extension is present + + // NOTE: disabling this code path for now as it appears it's + // buggy at least on some NVidia drivers and doesn't perform + // the necessary byte swapping (FIXME: needs more + // investigation) + if ((scanlineStride % 4) == 0 && glp.isGL2() && false) { + pixelFormat = GL2.GL_ABGR_EXT; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 4; + alignment = 4; + + // Store a reference to the original image for later in + // case it turns out that we don't have GL_EXT_abgr at the + // time we're going to do the texture upload to OpenGL + setupLazyCustomConversion(image); + expectingEXTABGR = true; + break; + } else { + setupLazyCustomConversion(image); + return; + } + } + case BufferedImage.TYPE_USHORT_565_RGB: + pixelFormat = GL.GL_RGB; + pixelType = GL.GL_UNSIGNED_SHORT_5_6_5; + rowLength = scanlineStride; + alignment = 2; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_USHORT_555_RGB: + pixelFormat = GL2GL3.GL_BGRA; + pixelType = GL2GL3.GL_UNSIGNED_SHORT_1_5_5_5_REV; + rowLength = scanlineStride; + alignment = 2; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_BYTE_GRAY: + pixelFormat = GL.GL_LUMINANCE; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride; + alignment = 1; + break; + case BufferedImage.TYPE_USHORT_GRAY: + pixelFormat = GL.GL_LUMINANCE; + pixelType = GL.GL_UNSIGNED_SHORT; + rowLength = scanlineStride; + alignment = 2; + break; + // Note: TYPE_INT_ARGB and TYPE_4BYTE_ABGR images go down the + // custom code path to satisfy the invariant that images with an + // alpha channel always go down with premultiplied alpha. + case BufferedImage.TYPE_INT_ARGB: + case BufferedImage.TYPE_4BYTE_ABGR: + case BufferedImage.TYPE_BYTE_BINARY: + case BufferedImage.TYPE_BYTE_INDEXED: + case BufferedImage.TYPE_CUSTOM: + default: + ColorModel cm = image.getColorModel(); + if (cm.equals(rgbColorModel)) { + pixelFormat = GL.GL_RGB; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 3; + alignment = 1; + } else if (cm.equals(rgbaColorModel)) { + pixelFormat = GL.GL_RGBA; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 4; // FIXME: correct? + alignment = 4; + } else { + setupLazyCustomConversion(image); + return; + } + break; + } + } else { + switch (image.getType()) { + case BufferedImage.TYPE_INT_RGB: + pixelFormat = GL.GL_RGB; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride; + alignment = 3; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_INT_ARGB_PRE: + throw new GLException("INT_ARGB_PRE n.a."); + case BufferedImage.TYPE_INT_BGR: + throw new GLException("INT_BGR n.a."); + case BufferedImage.TYPE_3BYTE_BGR: + throw new GLException("INT_BGR n.a."); + case BufferedImage.TYPE_4BYTE_ABGR_PRE: + throw new GLException("INT_BGR n.a."); + case BufferedImage.TYPE_USHORT_565_RGB: + pixelFormat = GL.GL_RGB; + pixelType = GL.GL_UNSIGNED_SHORT_5_6_5; + rowLength = scanlineStride; + alignment = 2; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_USHORT_555_RGB: + pixelFormat = GL.GL_RGBA; + pixelType = GL.GL_UNSIGNED_SHORT_5_5_5_1; + rowLength = scanlineStride; + alignment = 2; + expectingGL12 = true; + setupLazyCustomConversion(image); + break; + case BufferedImage.TYPE_BYTE_GRAY: + pixelFormat = GL.GL_LUMINANCE; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride; + alignment = 1; + break; + case BufferedImage.TYPE_USHORT_GRAY: + throw new GLException("USHORT_GRAY n.a."); + // Note: TYPE_INT_ARGB and TYPE_4BYTE_ABGR images go down the + // custom code path to satisfy the invariant that images with an + // alpha channel always go down with premultiplied alpha. + case BufferedImage.TYPE_INT_ARGB: + case BufferedImage.TYPE_4BYTE_ABGR: + case BufferedImage.TYPE_BYTE_BINARY: + case BufferedImage.TYPE_BYTE_INDEXED: + case BufferedImage.TYPE_CUSTOM: + default: + ColorModel cm = image.getColorModel(); + if (cm.equals(rgbColorModel)) { + pixelFormat = GL.GL_RGB; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 3; + alignment = 1; + } else if (cm.equals(rgbaColorModel)) { + pixelFormat = GL.GL_RGBA; + pixelType = GL.GL_UNSIGNED_BYTE; + rowLength = scanlineStride / 4; // FIXME: correct? + alignment = 4; + } else { + setupLazyCustomConversion(image); + return; + } + break; + } + } + + createNIOBufferFromImage(image); + } + + private void setupLazyCustomConversion(BufferedImage image) { + imageForLazyCustomConversion = image; + boolean hasAlpha = image.getColorModel().hasAlpha(); + if (pixelFormat == 0) { + pixelFormat = hasAlpha ? GL.GL_RGBA : GL.GL_RGB; + } + alignment = 1; // FIXME: do we need better? + rowLength = width; // FIXME: correct in all cases? + + // Allow previously-selected pixelType (if any) to override that + // we can infer from the DataBuffer + DataBuffer data = image.getRaster().getDataBuffer(); + if (data instanceof DataBufferByte || isPackedInt(image)) { + // Don't use GL_UNSIGNED_INT for BufferedImage packed int images + if (pixelType == 0) pixelType = GL.GL_UNSIGNED_BYTE; + } else if (data instanceof DataBufferDouble) { + throw new RuntimeException("DataBufferDouble rasters not supported by OpenGL"); + } else if (data instanceof DataBufferFloat) { + if (pixelType == 0) pixelType = GL.GL_FLOAT; + } else if (data instanceof DataBufferInt) { + // FIXME: should we support signed ints? + if (pixelType == 0) pixelType = GL2GL3.GL_UNSIGNED_INT; + } else if (data instanceof DataBufferShort) { + if (pixelType == 0) pixelType = GL.GL_SHORT; + } else if (data instanceof DataBufferUShort) { + if (pixelType == 0) pixelType = GL.GL_UNSIGNED_SHORT; + } else { + throw new RuntimeException("Unexpected DataBuffer type?"); + } + } + + private void createFromCustom(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + + // create a temporary image that is compatible with OpenGL + boolean hasAlpha = image.getColorModel().hasAlpha(); + ColorModel cm = null; + int dataBufferType = image.getRaster().getDataBuffer().getDataType(); + // Don't use integer components for packed int images + if (isPackedInt(image)) { + dataBufferType = DataBuffer.TYPE_BYTE; + } + if (dataBufferType == DataBuffer.TYPE_BYTE) { + cm = hasAlpha ? rgbaColorModel : rgbColorModel; + } else { + if (hasAlpha) { + cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + null, true, true, + Transparency.TRANSLUCENT, + dataBufferType); + } else { + cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), + null, false, false, + Transparency.OPAQUE, + dataBufferType); + } + } + + boolean premult = cm.isAlphaPremultiplied(); + WritableRaster raster = + cm.createCompatibleWritableRaster(width, height); + BufferedImage texImage = new BufferedImage(cm, raster, premult, null); + + // copy the source image into the temporary image + Graphics2D g = texImage.createGraphics(); + g.setComposite(AlphaComposite.Src); + g.drawImage(image, 0, 0, null); + g.dispose(); + + // Wrap the buffer from the temporary image + createNIOBufferFromImage(texImage); + } + + private boolean isPackedInt(BufferedImage image) { + int imgType = image.getType(); + return (imgType == BufferedImage.TYPE_INT_RGB || + imgType == BufferedImage.TYPE_INT_BGR || + imgType == BufferedImage.TYPE_INT_ARGB || + imgType == BufferedImage.TYPE_INT_ARGB_PRE); + } + + private void revertPixelFormatAndType() { + // Knowing we don't have e.g. OpenGL 1.2 functionality available, + // and knowing we're in the process of doing the fallback code + // path, re-infer a vanilla pixel format and type compatible with + // OpenGL 1.1 + pixelFormat = 0; + pixelType = 0; + setupLazyCustomConversion(imageForLazyCustomConversion); + } + + private void createNIOBufferFromImage(BufferedImage image) { + buffer = wrapImageDataBuffer(image); + } + + private Buffer wrapImageDataBuffer(BufferedImage image) { + // + // Note: Grabbing the DataBuffer will defeat Java2D's image + // management mechanism (as of JDK 5/6, at least). This shouldn't + // be a problem for most JOGL apps, but those that try to upload + // the image into an OpenGL texture and then use the same image in + // Java2D rendering might find the 2D rendering is not as fast as + // it could be. + // + + DataBuffer data = image.getRaster().getDataBuffer(); + if (data instanceof DataBufferByte) { + return ByteBuffer.wrap(((DataBufferByte) data).getData()); + } else if (data instanceof DataBufferDouble) { + throw new RuntimeException("DataBufferDouble rasters not supported by OpenGL"); + } else if (data instanceof DataBufferFloat) { + return FloatBuffer.wrap(((DataBufferFloat) data).getData()); + } else if (data instanceof DataBufferInt) { + return IntBuffer.wrap(((DataBufferInt) data).getData()); + } else if (data instanceof DataBufferShort) { + return ShortBuffer.wrap(((DataBufferShort) data).getData()); + } else if (data instanceof DataBufferUShort) { + return ShortBuffer.wrap(((DataBufferUShort) data).getData()); + } else { + throw new RuntimeException("Unexpected DataBuffer type?"); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java new file mode 100644 index 000000000..fdd1365f7 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/awt/AWTTextureIO.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.awt; + +import java.awt.image.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.texture.*; + +public class AWTTextureIO extends TextureIO { + /** + * Creates a TextureData from the given BufferedImage. Does no + * OpenGL work. + * We assume a desktop GLProfile GL2GL3, otherwise use the other factory. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param image the BufferedImage containing the texture data + * @param mipmap whether mipmaps should be produced for this + * texture by autogenerating them + * @return the texture data from the image + * + * @see #newTextureData(GLProfile, BufferedImage, boolean) + */ + public static TextureData newTextureData(GLProfile glp, BufferedImage image, + boolean mipmap) { + return newTextureDataImpl(glp, image, 0, 0, mipmap); + } + + /** + * Creates a TextureData from the given BufferedImage, using the + * specified OpenGL internal format and pixel format for the texture + * which will eventually result. The internalFormat and pixelFormat + * must be specified and may not be zero; to use default values, use + * the variant of this method which does not take these + * arguments. Does no OpenGL work. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param image the BufferedImage containing the texture data + * @param internalFormat the OpenGL internal format of the texture + * which will eventually result from the TextureData + * @param pixelFormat the OpenGL pixel format of the texture + * which will eventually result from the TextureData + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * @return the texture data from the image + * @throws IllegalArgumentException if either internalFormat or + * pixelFormat was 0 + */ + public static TextureData newTextureData(GLProfile glp, BufferedImage image, + int internalFormat, + int pixelFormat, + boolean mipmap) throws IllegalArgumentException { + if ((internalFormat == 0) || (pixelFormat == 0)) { + throw new IllegalArgumentException("internalFormat and pixelFormat must be non-zero"); + } + + return newTextureDataImpl(glp, image, internalFormat, pixelFormat, mipmap); + } + + /** + * Creates an OpenGL texture object from the specified BufferedImage + * using the current OpenGL context. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param image the BufferedImage from which to read the texture data + * @param mipmap whether mipmaps should be produced for this + * texture by autogenerating them + * @throws GLException if no OpenGL context is current or if an + * OpenGL error occurred + */ + public static Texture newTexture(GLProfile glp, BufferedImage image, boolean mipmap) throws GLException { + TextureData data = newTextureData(glp, image, mipmap); + Texture texture = newTexture(data); + data.flush(); + return texture; + } + + private static TextureData newTextureDataImpl(GLProfile glp, + BufferedImage image, + int internalFormat, + int pixelFormat, + boolean mipmap) { + return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, image); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp new file mode 100755 index 000000000..b18991dfc --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp @@ -0,0 +1,889 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.*; + +/** A reader and writer for DirectDraw Surface (.dds) files, which are + used to describe textures. These files can contain multiple mipmap + levels in one file. This class is currently minimal and does not + support all of the possible file formats. */ + +public class DDSImage { + + /** Simple class describing images and data; does not encapsulate + image format information. User is responsible for transmitting + that information in another way. */ + + public static class ImageInfo { + private ByteBuffer data; + private int width; + private int height; + private boolean isCompressed; + private int compressionFormat; + + public ImageInfo(ByteBuffer data, int width, int height, boolean compressed, int compressionFormat) { + this.data = data; this.width = width; this.height = height; + this.isCompressed = compressed; this.compressionFormat = compressionFormat; + } + public int getWidth() { return width; } + public int getHeight() { return height; } + public ByteBuffer getData() { return data; } + public boolean isCompressed() { return isCompressed; } + public int getCompressionFormat() { + if (!isCompressed()) + throw new RuntimeException("Should not call unless compressed"); + return compressionFormat; + } + } + + private ByteBuffer buf; + private Header header; + + // + // Selected bits in header flags + // + + public static final int DDSD_CAPS = 0x00000001; // Capacities are valid + public static final int DDSD_HEIGHT = 0x00000002; // Height is valid + public static final int DDSD_WIDTH = 0x00000004; // Width is valid + public static final int DDSD_PITCH = 0x00000008; // Pitch is valid + public static final int DDSD_BACKBUFFERCOUNT = 0x00000020; // Back buffer count is valid + public static final int DDSD_ZBUFFERBITDEPTH = 0x00000040; // Z-buffer bit depth is valid (shouldn't be used in DDSURFACEDESC2) + public static final int DDSD_ALPHABITDEPTH = 0x00000080; // Alpha bit depth is valid + public static final int DDSD_LPSURFACE = 0x00000800; // lpSurface is valid + public static final int DDSD_PIXELFORMAT = 0x00001000; // ddpfPixelFormat is valid + public static final int DDSD_MIPMAPCOUNT = 0x00020000; // Mip map count is valid + public static final int DDSD_LINEARSIZE = 0x00080000; // dwLinearSize is valid + public static final int DDSD_DEPTH = 0x00800000; // dwDepth is valid + + public static final int DDPF_ALPHAPIXELS = 0x00000001; // Alpha channel is present + public static final int DDPF_ALPHA = 0x00000002; // Only contains alpha information + public static final int DDPF_FOURCC = 0x00000004; // FourCC code is valid + public static final int DDPF_PALETTEINDEXED4 = 0x00000008; // Surface is 4-bit color indexed + public static final int DDPF_PALETTEINDEXEDTO8 = 0x00000010; // Surface is indexed into a palette which stores indices + // into the destination surface's 8-bit palette + public static final int DDPF_PALETTEINDEXED8 = 0x00000020; // Surface is 8-bit color indexed + public static final int DDPF_RGB = 0x00000040; // RGB data is present + public static final int DDPF_COMPRESSED = 0x00000080; // Surface will accept pixel data in the format specified + // and compress it during the write + public static final int DDPF_RGBTOYUV = 0x00000100; // Surface will accept RGB data and translate it during + // the write to YUV data. The format of the data to be written + // will be contained in the pixel format structure. The DDPF_RGB + // flag will be set. + public static final int DDPF_YUV = 0x00000200; // Pixel format is YUV - YUV data in pixel format struct is valid + public static final int DDPF_ZBUFFER = 0x00000400; // Pixel format is a z buffer only surface + public static final int DDPF_PALETTEINDEXED1 = 0x00000800; // Surface is 1-bit color indexed + public static final int DDPF_PALETTEINDEXED2 = 0x00001000; // Surface is 2-bit color indexed + public static final int DDPF_ZPIXELS = 0x00002000; // Surface contains Z information in the pixels + + // Selected bits in DDS capabilities flags + public static final int DDSCAPS_TEXTURE = 0x00001000; // Can be used as a texture + public static final int DDSCAPS_MIPMAP = 0x00400000; // Is one level of a mip-map + public static final int DDSCAPS_COMPLEX = 0x00000008; // Complex surface structure, such as a cube map + + // Selected bits in DDS extended capabilities flags + public static final int DDSCAPS2_CUBEMAP = 0x00000200; + public static final int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800; + public static final int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000; + public static final int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000; + + // Known pixel formats + public static final int D3DFMT_UNKNOWN = 0; + public static final int D3DFMT_R8G8B8 = 20; + public static final int D3DFMT_A8R8G8B8 = 21; + public static final int D3DFMT_X8R8G8B8 = 22; + // The following are also valid FourCC codes + public static final int D3DFMT_DXT1 = 0x31545844; + public static final int D3DFMT_DXT2 = 0x32545844; + public static final int D3DFMT_DXT3 = 0x33545844; + public static final int D3DFMT_DXT4 = 0x34545844; + public static final int D3DFMT_DXT5 = 0x35545844; + + /** Reads a DirectDraw surface from the specified file name, + returning the resulting DDSImage. + + @param filename File name + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(String filename) throws IOException { + return read(new File(filename)); + } + + /** Reads a DirectDraw surface from the specified file, returning + the resulting DDSImage. + + @param file File object + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(File file) throws IOException { + DDSImage image = new DDSImage(); + image.readFromFile(file); + return image; + } + + /** Reads a DirectDraw surface from the specified InputStream, returning + the resulting DDSImage. + + @param input Input stream + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(InputStream input) throws IOException { + DDSImage image = new DDSImage(); + image.readFromStream(input); + return image; + } + + /** Closes open files and resources associated with the open + DDSImage. No other methods may be called on this object once + this is called. */ + public void close() { + } + + /** + * Creates a new DDSImage from data supplied by the user. The + * resulting DDSImage can be written to disk using the write() + * method. + * + * @param d3dFormat the D3DFMT_ constant describing the data; it is + * assumed that it is packed tightly + * @param width the width in pixels of the topmost mipmap image + * @param height the height in pixels of the topmost mipmap image + * @param mipmapData the data for each mipmap level of the resulting + * DDSImage; either only one mipmap level should + * be specified, or they all must be + * @throws IllegalArgumentException if the data does not match the + * specified arguments + * @return DDS image object + */ + public static DDSImage createFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + DDSImage image = new DDSImage(); + image.initFromData(d3dFormat, width, height, mipmapData); + return image; + } + + /** Determines from the magic number whether the given InputStream + points to a DDS image. The given InputStream must return true + from markSupported() and support a minimum of four bytes of + read-ahead. + + @param in Stream to check + @return true if input stream is DDS image or false otherwise + @throws java.io.IOException if an I/O exception occurred + */ + public static boolean isDDSImage(InputStream in) throws IOException { + if (!(in instanceof BufferedInputStream)) { + in = new BufferedInputStream(in); + } + if (!in.markSupported()) { + throw new IOException("Can not test non-destructively whether given InputStream is a DDS image"); + } + in.mark(4); + int magic = 0; + for (int i = 0; i < 4; i++) { + int tmp = in.read(); + if (tmp < 0) { + in.reset(); + return false; + } + magic = ((magic >>> 8) | (tmp << 24)); + } + in.reset(); + return (magic == MAGIC); + } + + /** + * Writes this DDSImage to the specified file name. + * @param filename File name to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** + * Writes this DDSImage to the specified file name. + * @param file File object to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(File file) throws IOException { + LEDataOutputStream output = + new LEDataOutputStream(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); + header.write(output); + output.write(buf.array()); + output.close(); + } + + /** Test for presence/absence of surface description flags (DDSD_*) + * @param flag DDSD_* flags set to test + * @return true if flag present or false otherwise + */ + public boolean isSurfaceDescFlagSet(int flag) { + return ((header.flags & flag) != 0); + } + + /** Test for presence/absence of pixel format flags (DDPF_*) */ + public boolean isPixelFormatFlagSet(int flag) { + return ((header.pfFlags & flag) != 0); + } + + /** Gets the pixel format of this texture (D3DFMT_*) based on some + heuristics. Returns D3DFMT_UNKNOWN if could not recognize the + pixel format. */ + public int getPixelFormat() { + if (isCompressed()) { + return getCompressionFormat(); + } else if (isPixelFormatFlagSet(DDPF_RGB)) { + if (isPixelFormatFlagSet(DDPF_ALPHAPIXELS)) { + if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF && + header.pfABitMask == 0xFF000000) { + return D3DFMT_A8R8G8B8; + } + } else { + if (getDepth() == 24 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_R8G8B8; + } else if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_X8R8G8B8; + } + } + } + + return D3DFMT_UNKNOWN; + } + + /** + * Indicates whether this texture is cubemap + * @return true if cubemap or false otherwise + */ + public boolean isCubemap() { + return ((header.ddsCaps1 & DDSCAPS_COMPLEX) != 0) && ((header.ddsCaps2 & DDSCAPS2_CUBEMAP) != 0); + } + + /** + * Indicates whethe this cubemap side present + * @param side Side to test + * @return true if side present or false otherwise + */ + public boolean isCubemapSidePresent(int side) { + return isCubemap() && (header.ddsCaps2 & side) != 0; + } + + /** Indicates whether this texture is compressed. */ + public boolean isCompressed() { + return (isPixelFormatFlagSet(DDPF_FOURCC)); + } + + /** If this surface is compressed, returns the kind of compression + used (DXT1..DXT5). */ + public int getCompressionFormat() { + return header.pfFourCC; + } + + /** Width of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getWidth() { + return header.width; + } + + /** Height of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getHeight() { + return header.height; + } + + /** Total number of bits per pixel. Only valid if DDPF_RGB is + present. For A8R8G8B8, would be 32. */ + public int getDepth() { + return header.pfRGBBitCount; + } + + /** Number of mip maps in the texture */ + public int getNumMipMaps() { + if (!isSurfaceDescFlagSet(DDSD_MIPMAPCOUNT)) { + return 0; + } + return header.mipMapCountOrAux; + } + + /** Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int map) { + return getMipMap( 0, map ); + } + + /** + * Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param side Cubemap side or 0 for 2D texture + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int side, int map) { + if (!isCubemap() && (side != 0)) { + throw new RuntimeException( "Illegal side for 2D texture: " + side ); + } + if (isCubemap() && !isCubemapSidePresent(side)) { + throw new RuntimeException( "Illegal side, side not present: " + side ); + } + if (getNumMipMaps() > 0 && + ((map < 0) || (map >= getNumMipMaps()))) { + throw new RuntimeException("Illegal mipmap number " + map + " (0.." + (getNumMipMaps() - 1) + ")"); + } + + // Figure out how far to seek + int seek = 0; + if (isCubemap()) { + seek += sideShiftInBytes(side); + } + for (int i = 0; i < map; i++) { + seek += mipMapSizeInBytes(i); + } + buf.limit(seek + mipMapSizeInBytes(map)); + buf.position(seek); + ByteBuffer next = buf.slice(); + buf.position(0); + buf.limit(buf.capacity()); + return new ImageInfo(next, mipMapWidth(map), mipMapHeight(map), isCompressed(), getCompressionFormat()); + } + + /** Returns an array of ImageInfos corresponding to all mipmap + levels of this DDS file. + @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps() { + return getAllMipMaps(0); + } + + /** + * Returns an array of ImageInfos corresponding to all mipmap + * levels of this DDS file. + * @param side Cubemap side or 0 for 2D texture + * @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps( int side ) { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + ImageInfo[] result = new ImageInfo[numLevels]; + for (int i = 0; i < numLevels; i++) { + result[i] = getMipMap(side, i); + } + return result; + } + + /** Converts e.g. DXT1 compression format constant (see {@link + #getCompressionFormat}) into "DXT1". + @param compressionFormat Compression format constant + @return String format code + */ + public static String getCompressionFormatName(int compressionFormat) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < 4; i++) { + char c = (char) (compressionFormat & 0xFF); + buf.append(c); + compressionFormat = compressionFormat >> 8; + } + return buf.toString(); + } + + /** Allocates a temporary, empty ByteBuffer suitable for use in a + call to glCompressedTexImage2D. This is used by the Texture + class to expand non-power-of-two DDS compressed textures to + power-of-two sizes on hardware not supporting OpenGL 2.0 and the + NPOT texture extension. The specified OpenGL internal format + must be one of GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, or + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT. + */ + public static ByteBuffer allocateBlankBuffer(int width, + int height, + int openGLInternalFormat) { + int size = width * height; + switch (openGLInternalFormat) { + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + size /= 2; + break; + + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + break; + + default: + throw new IllegalArgumentException("Illegal OpenGL texture internal format " + + openGLInternalFormat); + } + if (size == 0) + size = 1; + return GLBuffers.newDirectByteBuffer(size); + } + + public void debugPrint() { + PrintStream tty = System.err; + tty.println("Compressed texture: " + isCompressed()); + if (isCompressed()) { + int fmt = getCompressionFormat(); + String name = getCompressionFormatName(fmt); + tty.println("Compression format: 0x" + Integer.toHexString(fmt) + " (" + name + ")"); + } + tty.println("Width: " + header.width + " Height: " + header.height); + tty.println("header.pitchOrLinearSize: " + header.pitchOrLinearSize); + tty.println("header.pfRBitMask: 0x" + Integer.toHexString(header.pfRBitMask)); + tty.println("header.pfGBitMask: 0x" + Integer.toHexString(header.pfGBitMask)); + tty.println("header.pfBBitMask: 0x" + Integer.toHexString(header.pfBBitMask)); + tty.println("SurfaceDesc flags:"); + boolean recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_CAPS, "DDSD_CAPS"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_HEIGHT, "DDSD_HEIGHT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_WIDTH, "DDSD_WIDTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PITCH, "DDSD_PITCH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_BACKBUFFERCOUNT, "DDSD_BACKBUFFERCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ALPHABITDEPTH, "DDSD_ALPHABITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LPSURFACE, "DDSD_LPSURFACE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_MIPMAPCOUNT, "DDSD_MIPMAPCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LINEARSIZE, "DDSD_LINEARSIZE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_DEPTH, "DDSD_DEPTH"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw SurfaceDesc flags: 0x" + Integer.toHexString(header.flags)); + tty.println("Pixel format flags:"); + recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHAPIXELS, "DDPF_ALPHAPIXELS"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHA, "DDPF_ALPHA"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_FOURCC, "DDPF_FOURCC"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED4, "DDPF_PALETTEINDEXED4"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXEDTO8, "DDPF_PALETTEINDEXEDTO8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED8, "DDPF_PALETTEINDEXED8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGB, "DDPF_RGB"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_COMPRESSED, "DDPF_COMPRESSED"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGBTOYUV, "DDPF_RGBTOYUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_YUV, "DDPF_YUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZBUFFER, "DDPF_ZBUFFER"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED1, "DDPF_PALETTEINDEXED1"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED2, "DDPF_PALETTEINDEXED2"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZPIXELS, "DDPF_ZPIXELS"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw pixel format flags: 0x" + Integer.toHexString(header.pfFlags)); + tty.println("Depth: " + getDepth()); + tty.println("Number of mip maps: " + getNumMipMaps()); + int fmt = getPixelFormat(); + tty.print("Pixel format: "); + switch (fmt) { + case D3DFMT_R8G8B8: tty.println("D3DFMT_R8G8B8"); break; + case D3DFMT_A8R8G8B8: tty.println("D3DFMT_A8R8G8B8"); break; + case D3DFMT_X8R8G8B8: tty.println("D3DFMT_X8R8G8B8"); break; + case D3DFMT_DXT1: tty.println("D3DFMT_DXT1"); break; + case D3DFMT_DXT2: tty.println("D3DFMT_DXT2"); break; + case D3DFMT_DXT3: tty.println("D3DFMT_DXT3"); break; + case D3DFMT_DXT4: tty.println("D3DFMT_DXT4"); break; + case D3DFMT_DXT5: tty.println("D3DFMT_DXT5"); break; + case D3DFMT_UNKNOWN: tty.println("D3DFMT_UNKNOWN"); break; + default: tty.println("(unknown pixel format " + fmt + ")"); break; + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static final int MAGIC = 0x20534444; + + static class Header { + int size; // size of the DDSURFACEDESC structure + int flags; // determines what fields are valid + int height; // height of surface to be created + int width; // width of input surface + int pitchOrLinearSize; + int backBufferCountOrDepth; + int mipMapCountOrAux; // number of mip-map levels requested (in this context) + int alphaBitDepth; // depth of alpha buffer requested + int reserved1; // reserved + int surface; // pointer to the associated surface memory + // NOTE: following two entries are from DDCOLORKEY data structure + // Are overlaid with color for empty cubemap faces (unused in this reader) + int colorSpaceLowValue; + int colorSpaceHighValue; + int destBltColorSpaceLowValue; + int destBltColorSpaceHighValue; + int srcOverlayColorSpaceLowValue; + int srcOverlayColorSpaceHighValue; + int srcBltColorSpaceLowValue; + int srcBltColorSpaceHighValue; + // NOTE: following entries are from DDPIXELFORMAT data structure + // Are overlaid with flexible vertex format description of vertex + // buffers (unused in this reader) + int pfSize; // size of DDPIXELFORMAT structure + int pfFlags; // pixel format flags + int pfFourCC; // (FOURCC code) + // Following five entries have multiple interpretations, not just + // RGBA (but that's all we support right now) + int pfRGBBitCount; // how many bits per pixel + int pfRBitMask; // mask for red bits + int pfGBitMask; // mask for green bits + int pfBBitMask; // mask for blue bits + int pfABitMask; // mask for alpha channel + int ddsCaps1; // Texture and mip-map flags + int ddsCaps2; // Advanced capabilities including cubemap support + int ddsCapsReserved1; + int ddsCapsReserved2; + int textureStage; // stage in multitexture cascade + + void read(LEDataInputStream input) throws IOException { + int magic = input.readInt(); + if (magic != MAGIC) { + throw new IOException("Incorrect magic number 0x" + + Integer.toHexString(magic) + + " (expected " + MAGIC + ")"); + } + + size = input.readInt(); + flags = input.readInt(); + height = input.readInt(); + width = input.readInt(); + pitchOrLinearSize = input.readInt(); + backBufferCountOrDepth = input.readInt(); + mipMapCountOrAux = input.readInt(); + alphaBitDepth = input.readInt(); + reserved1 = input.readInt(); + surface = input.readInt(); + colorSpaceLowValue = input.readInt(); + colorSpaceHighValue = input.readInt(); + destBltColorSpaceLowValue = input.readInt(); + destBltColorSpaceHighValue = input.readInt(); + srcOverlayColorSpaceLowValue = input.readInt(); + srcOverlayColorSpaceHighValue = input.readInt(); + srcBltColorSpaceLowValue = input.readInt(); + srcBltColorSpaceHighValue = input.readInt(); + pfSize = input.readInt(); + pfFlags = input.readInt(); + pfFourCC = input.readInt(); + pfRGBBitCount = input.readInt(); + pfRBitMask = input.readInt(); + pfGBitMask = input.readInt(); + pfBBitMask = input.readInt(); + pfABitMask = input.readInt(); + ddsCaps1 = input.readInt(); + ddsCaps2 = input.readInt(); + ddsCapsReserved1 = input.readInt(); + ddsCapsReserved2 = input.readInt(); + textureStage = input.readInt(); + } + + // buf must be in little-endian byte order + void write(LEDataOutputStream output) throws IOException { + output.writeInt(MAGIC); + output.writeInt(size); + output.writeInt(flags); + output.writeInt(height); + output.writeInt(width); + output.writeInt(pitchOrLinearSize); + output.writeInt(backBufferCountOrDepth); + output.writeInt(mipMapCountOrAux); + output.writeInt(alphaBitDepth); + output.writeInt(reserved1); + output.writeInt(surface); + output.writeInt(colorSpaceLowValue); + output.writeInt(colorSpaceHighValue); + output.writeInt(destBltColorSpaceLowValue); + output.writeInt(destBltColorSpaceHighValue); + output.writeInt(srcOverlayColorSpaceLowValue); + output.writeInt(srcOverlayColorSpaceHighValue); + output.writeInt(srcBltColorSpaceLowValue); + output.writeInt(srcBltColorSpaceHighValue); + output.writeInt(pfSize); + output.writeInt(pfFlags); + output.writeInt(pfFourCC); + output.writeInt(pfRGBBitCount); + output.writeInt(pfRBitMask); + output.writeInt(pfGBitMask); + output.writeInt(pfBBitMask); + output.writeInt(pfABitMask); + output.writeInt(ddsCaps1); + output.writeInt(ddsCaps2); + output.writeInt(ddsCapsReserved1); + output.writeInt(ddsCapsReserved2); + output.writeInt(textureStage); + } + + private static int size() { + return 124; + } + + private static int pfSize() { + return 32; + } + + private static int writtenSize() { + return 128; + } + } + + private DDSImage() { + } + + private void readFromFile(File file) throws IOException { + readFromStream(new BufferedInputStream(new FileInputStream(file))); + } + + private void readFromStream(InputStream input) throws IOException { + LEDataInputStream leInput = new LEDataInputStream(input); + header = new Header(); + header.read(leInput); + fixupHeader(); + buf = StreamUtil.readAll2Buffer(input); + } + + private void initFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + // Check size of mipmap data compared against format, width and + // height + int topmostMipmapSize = width * height; + int pitchOrLinearSize = width; + boolean isCompressed = false; + switch (d3dFormat) { + case D3DFMT_R8G8B8: topmostMipmapSize *= 3; pitchOrLinearSize *= 3; break; + case D3DFMT_A8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_X8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + topmostMipmapSize = computeCompressedBlockSize(width, height, 1, d3dFormat); + pitchOrLinearSize = topmostMipmapSize; + isCompressed = true; + break; + default: + throw new IllegalArgumentException("d3dFormat must be one of the known formats"); + } + + // Now check the mipmaps against this size + int curSize = topmostMipmapSize; + int totalSize = 0; + for (int i = 0; i < mipmapData.length; i++) { + if (mipmapData[i].remaining() != curSize) { + throw new IllegalArgumentException("Mipmap level " + i + + " didn't match expected data size (expected " + curSize + ", got " + + mipmapData[i].remaining() + ")"); + } + curSize /= 4; + totalSize += mipmapData[i].remaining(); + } + + // OK, create one large byte array to hold all of the mipmap data + byte[] data = new byte[totalSize]; + ByteBuffer buf = ByteBuffer.wrap(data); + for (int i = 0; i < mipmapData.length; i++) { + buf.put(mipmapData[i]); + } + this.buf = buf; + + // Allocate and initialize a Header + header = new Header(); + header.size = Header.size(); + header.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + if (mipmapData.length > 1) { + header.flags |= DDSD_MIPMAPCOUNT; + header.mipMapCountOrAux = mipmapData.length; + } + header.width = width; + header.height = height; + if (isCompressed) { + header.flags |= DDSD_LINEARSIZE; + header.pfFlags |= DDPF_FOURCC; + header.pfFourCC = d3dFormat; + } else { + header.flags |= DDSD_PITCH; + // Figure out the various settings from the pixel format + header.pfFlags |= DDPF_RGB; + switch (d3dFormat) { + case D3DFMT_R8G8B8: header.pfRGBBitCount = 24; break; + case D3DFMT_A8R8G8B8: header.pfRGBBitCount = 32; header.pfFlags |= DDPF_ALPHAPIXELS; break; + case D3DFMT_X8R8G8B8: header.pfRGBBitCount = 32; break; + } + header.pfRBitMask = 0x00FF0000; + header.pfGBitMask = 0x0000FF00; + header.pfBBitMask = 0x000000FF; + if (d3dFormat == D3DFMT_A8R8G8B8) { + header.pfABitMask = 0xFF000000; + } + } + header.pitchOrLinearSize = pitchOrLinearSize; + header.pfSize = Header.pfSize(); + // Not sure whether we can get away with leaving the rest of the + // header blank + } + + // Microsoft doesn't follow their own specifications and the + // simplest conversion using the DxTex tool to e.g. a DXT3 texture + // results in an illegal .dds file without either DDSD_PITCH or + // DDSD_LINEARSIZE set in the header's flags. This code, adapted + // from the DevIL library, fixes up the header in these situations. + private void fixupHeader() { + if (isCompressed() && !isSurfaceDescFlagSet(DDSD_LINEARSIZE)) { + // Figure out how big the linear size should be + int depth = header.backBufferCountOrDepth; + if (depth == 0) { + depth = 1; + } + + header.pitchOrLinearSize = computeCompressedBlockSize(getWidth(), getHeight(), depth, getCompressionFormat()); + header.flags |= DDSD_LINEARSIZE; + } + } + + private static int computeCompressedBlockSize(int width, + int height, + int depth, + int compressionFormat) { + int blockSize = ((width + 3)/4) * ((height + 3)/4) * ((depth + 3)/4); + switch (compressionFormat) { + case D3DFMT_DXT1: blockSize *= 8; break; + default: blockSize *= 16; break; + } + return blockSize; + } + + private int mipMapWidth(int map) { + int width = getWidth(); + for (int i = 0; i < map; i++) { + width >>= 1; + } + return Math.max(width, 1); + } + + private int mipMapHeight(int map) { + int height = getHeight(); + for (int i = 0; i < map; i++) { + height >>= 1; + } + return Math.max(height, 1); + } + + private int mipMapSizeInBytes(int map) { + int width = mipMapWidth(map); + int height = mipMapHeight(map); + if (isCompressed()) { + int blockSize = (getCompressionFormat() == D3DFMT_DXT1 ? 8 : 16); + return ((width+3)/4)*((height+3)/4)*blockSize; + } else { + return width * height * (getDepth() / 8); + } + } + + private int sideSizeInBytes() { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + + int size = 0; + for (int i = 0; i < numLevels; i++) { + size += mipMapSizeInBytes(i); + } + + return size; + } + + private int sideShiftInBytes(int side) { + int[] sides = { + DDSCAPS2_CUBEMAP_POSITIVEX, + DDSCAPS2_CUBEMAP_NEGATIVEX, + DDSCAPS2_CUBEMAP_POSITIVEY, + DDSCAPS2_CUBEMAP_NEGATIVEY, + DDSCAPS2_CUBEMAP_POSITIVEZ, + DDSCAPS2_CUBEMAP_NEGATIVEZ + }; + + int shift = 0; + int sideSize = sideSizeInBytes(); + for (int i = 0; i < sides.length; i++) { + int temp = sides[i]; + if ((temp & side) != 0) { + return shift; + } + + shift += sideSize; + } + + throw new RuntimeException("Illegal side: " + side); + } + + private boolean printIfRecognized(PrintStream tty, int flags, int flag, String what) { + if ((flags & flag) != 0) { + tty.println(what); + return true; + } + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javase b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javase new file mode 100755 index 000000000..e3092162d --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/DDSImage.java.javase @@ -0,0 +1,919 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.*; + +/** A reader and writer for DirectDraw Surface (.dds) files, which are + used to describe textures. These files can contain multiple mipmap + levels in one file. This class is currently minimal and does not + support all of the possible file formats. */ + +public class DDSImage { + + /** Simple class describing images and data; does not encapsulate + image format information. User is responsible for transmitting + that information in another way. */ + + public static class ImageInfo { + private ByteBuffer data; + private int width; + private int height; + private boolean isCompressed; + private int compressionFormat; + + public ImageInfo(ByteBuffer data, int width, int height, boolean compressed, int compressionFormat) { + this.data = data; this.width = width; this.height = height; + this.isCompressed = compressed; this.compressionFormat = compressionFormat; + } + public int getWidth() { return width; } + public int getHeight() { return height; } + public ByteBuffer getData() { return data; } + public boolean isCompressed() { return isCompressed; } + public int getCompressionFormat() { + if (!isCompressed()) + throw new RuntimeException("Should not call unless compressed"); + return compressionFormat; + } + } + + private FileInputStream fis; + private FileChannel chan; + private ByteBuffer buf; + private Header header; + + // + // Selected bits in header flags + // + + public static final int DDSD_CAPS = 0x00000001; // Capacities are valid + public static final int DDSD_HEIGHT = 0x00000002; // Height is valid + public static final int DDSD_WIDTH = 0x00000004; // Width is valid + public static final int DDSD_PITCH = 0x00000008; // Pitch is valid + public static final int DDSD_BACKBUFFERCOUNT = 0x00000020; // Back buffer count is valid + public static final int DDSD_ZBUFFERBITDEPTH = 0x00000040; // Z-buffer bit depth is valid (shouldn't be used in DDSURFACEDESC2) + public static final int DDSD_ALPHABITDEPTH = 0x00000080; // Alpha bit depth is valid + public static final int DDSD_LPSURFACE = 0x00000800; // lpSurface is valid + public static final int DDSD_PIXELFORMAT = 0x00001000; // ddpfPixelFormat is valid + public static final int DDSD_MIPMAPCOUNT = 0x00020000; // Mip map count is valid + public static final int DDSD_LINEARSIZE = 0x00080000; // dwLinearSize is valid + public static final int DDSD_DEPTH = 0x00800000; // dwDepth is valid + + public static final int DDPF_ALPHAPIXELS = 0x00000001; // Alpha channel is present + public static final int DDPF_ALPHA = 0x00000002; // Only contains alpha information + public static final int DDPF_FOURCC = 0x00000004; // FourCC code is valid + public static final int DDPF_PALETTEINDEXED4 = 0x00000008; // Surface is 4-bit color indexed + public static final int DDPF_PALETTEINDEXEDTO8 = 0x00000010; // Surface is indexed into a palette which stores indices + // into the destination surface's 8-bit palette + public static final int DDPF_PALETTEINDEXED8 = 0x00000020; // Surface is 8-bit color indexed + public static final int DDPF_RGB = 0x00000040; // RGB data is present + public static final int DDPF_COMPRESSED = 0x00000080; // Surface will accept pixel data in the format specified + // and compress it during the write + public static final int DDPF_RGBTOYUV = 0x00000100; // Surface will accept RGB data and translate it during + // the write to YUV data. The format of the data to be written + // will be contained in the pixel format structure. The DDPF_RGB + // flag will be set. + public static final int DDPF_YUV = 0x00000200; // Pixel format is YUV - YUV data in pixel format struct is valid + public static final int DDPF_ZBUFFER = 0x00000400; // Pixel format is a z buffer only surface + public static final int DDPF_PALETTEINDEXED1 = 0x00000800; // Surface is 1-bit color indexed + public static final int DDPF_PALETTEINDEXED2 = 0x00001000; // Surface is 2-bit color indexed + public static final int DDPF_ZPIXELS = 0x00002000; // Surface contains Z information in the pixels + + // Selected bits in DDS capabilities flags + public static final int DDSCAPS_TEXTURE = 0x00001000; // Can be used as a texture + public static final int DDSCAPS_MIPMAP = 0x00400000; // Is one level of a mip-map + public static final int DDSCAPS_COMPLEX = 0x00000008; // Complex surface structure, such as a cube map + + // Selected bits in DDS extended capabilities flags + public static final int DDSCAPS2_CUBEMAP = 0x00000200; + public static final int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800; + public static final int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000; + public static final int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000; + + // Known pixel formats + public static final int D3DFMT_UNKNOWN = 0; + public static final int D3DFMT_R8G8B8 = 20; + public static final int D3DFMT_A8R8G8B8 = 21; + public static final int D3DFMT_X8R8G8B8 = 22; + // The following are also valid FourCC codes + public static final int D3DFMT_DXT1 = 0x31545844; + public static final int D3DFMT_DXT2 = 0x32545844; + public static final int D3DFMT_DXT3 = 0x33545844; + public static final int D3DFMT_DXT4 = 0x34545844; + public static final int D3DFMT_DXT5 = 0x35545844; + + /** Reads a DirectDraw surface from the specified file name, + returning the resulting DDSImage. + + @param filename File name + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(String filename) throws IOException { + return read(new File(filename)); + } + + /** Reads a DirectDraw surface from the specified file, returning + the resulting DDSImage. + + @param file File object + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(File file) throws IOException { + DDSImage image = new DDSImage(); + image.readFromFile(file); + return image; + } + + /** Reads a DirectDraw surface from the specified ByteBuffer, returning + the resulting DDSImage. + + @param buf Input data + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(ByteBuffer buf) throws IOException { + DDSImage image = new DDSImage(); + image.readFromBuffer(buf); + return image; + } + + /** Closes open files and resources associated with the open + DDSImage. No other methods may be called on this object once + this is called. */ + public void close() { + try { + if (chan != null) { + chan.close(); + chan = null; + } + if (fis != null) { + fis.close(); + fis = null; + } + buf = null; + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Creates a new DDSImage from data supplied by the user. The + * resulting DDSImage can be written to disk using the write() + * method. + * + * @param d3dFormat the D3DFMT_ constant describing the data; it is + * assumed that it is packed tightly + * @param width the width in pixels of the topmost mipmap image + * @param height the height in pixels of the topmost mipmap image + * @param mipmapData the data for each mipmap level of the resulting + * DDSImage; either only one mipmap level should + * be specified, or they all must be + * @throws IllegalArgumentException if the data does not match the + * specified arguments + * @return DDS image object + */ + public static DDSImage createFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + DDSImage image = new DDSImage(); + image.initFromData(d3dFormat, width, height, mipmapData); + return image; + } + + /** Determines from the magic number whether the given InputStream + points to a DDS image. The given InputStream must return true + from markSupported() and support a minimum of four bytes of + read-ahead. + + @param in Stream to check + @return true if input stream is DDS image or false otherwise + @throws java.io.IOException if an I/O exception occurred + */ + public static boolean isDDSImage(InputStream in) throws IOException { + if (!(in instanceof BufferedInputStream)) { + in = new BufferedInputStream(in); + } + if (!in.markSupported()) { + throw new IOException("Can not test non-destructively whether given InputStream is a DDS image"); + } + in.mark(4); + int magic = 0; + for (int i = 0; i < 4; i++) { + int tmp = in.read(); + if (tmp < 0) { + in.reset(); + return false; + } + magic = ((magic >>> 8) | (tmp << 24)); + } + in.reset(); + return (magic == MAGIC); + } + + /** + * Writes this DDSImage to the specified file name. + * @param filename File name to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** + * Writes this DDSImage to the specified file name. + * @param file File object to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(File file) throws IOException { + FileOutputStream stream = new FileOutputStream(file); + FileChannel chan = stream.getChannel(); + // Create ByteBuffer for header in case the start of our + // ByteBuffer isn't actually memory-mapped + ByteBuffer hdr = ByteBuffer.allocate(Header.writtenSize()); + hdr.order(ByteOrder.LITTLE_ENDIAN); + header.write(hdr); + hdr.rewind(); + chan.write(hdr); + buf.position(Header.writtenSize()); + chan.write(buf); + chan.force(true); + chan.close(); + stream.close(); + } + + /** Test for presence/absence of surface description flags (DDSD_*) + * @param flag DDSD_* flags set to test + * @return true if flag present or false otherwise + */ + public boolean isSurfaceDescFlagSet(int flag) { + return ((header.flags & flag) != 0); + } + + /** Test for presence/absence of pixel format flags (DDPF_*) */ + public boolean isPixelFormatFlagSet(int flag) { + return ((header.pfFlags & flag) != 0); + } + + /** Gets the pixel format of this texture (D3DFMT_*) based on some + heuristics. Returns D3DFMT_UNKNOWN if could not recognize the + pixel format. */ + public int getPixelFormat() { + if (isCompressed()) { + return getCompressionFormat(); + } else if (isPixelFormatFlagSet(DDPF_RGB)) { + if (isPixelFormatFlagSet(DDPF_ALPHAPIXELS)) { + if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF && + header.pfABitMask == 0xFF000000) { + return D3DFMT_A8R8G8B8; + } + } else { + if (getDepth() == 24 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_R8G8B8; + } else if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_X8R8G8B8; + } + } + } + + return D3DFMT_UNKNOWN; + } + + /** + * Indicates whether this texture is cubemap + * @return true if cubemap or false otherwise + */ + public boolean isCubemap() { + return ((header.ddsCaps1 & DDSCAPS_COMPLEX) != 0) && ((header.ddsCaps2 & DDSCAPS2_CUBEMAP) != 0); + } + + /** + * Indicates whethe this cubemap side present + * @param side Side to test + * @return true if side present or false otherwise + */ + public boolean isCubemapSidePresent(int side) { + return isCubemap() && (header.ddsCaps2 & side) != 0; + } + + /** Indicates whether this texture is compressed. */ + public boolean isCompressed() { + return (isPixelFormatFlagSet(DDPF_FOURCC)); + } + + /** If this surface is compressed, returns the kind of compression + used (DXT1..DXT5). */ + public int getCompressionFormat() { + return header.pfFourCC; + } + + /** Width of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getWidth() { + return header.width; + } + + /** Height of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getHeight() { + return header.height; + } + + /** Total number of bits per pixel. Only valid if DDPF_RGB is + present. For A8R8G8B8, would be 32. */ + public int getDepth() { + return header.pfRGBBitCount; + } + + /** Number of mip maps in the texture */ + public int getNumMipMaps() { + if (!isSurfaceDescFlagSet(DDSD_MIPMAPCOUNT)) { + return 0; + } + return header.mipMapCountOrAux; + } + + /** Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int map) { + return getMipMap( 0, map ); + } + + /** + * Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param side Cubemap side or 0 for 2D texture + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int side, int map) { + if (!isCubemap() && (side != 0)) { + throw new RuntimeException( "Illegal side for 2D texture: " + side ); + } + if (isCubemap() && !isCubemapSidePresent(side)) { + throw new RuntimeException( "Illegal side, side not present: " + side ); + } + if (getNumMipMaps() > 0 && + ((map < 0) || (map >= getNumMipMaps()))) { + throw new RuntimeException("Illegal mipmap number " + map + " (0.." + (getNumMipMaps() - 1) + ")"); + } + + // Figure out how far to seek + int seek = Header.writtenSize(); + if (isCubemap()) { + seek += sideShiftInBytes(side); + } + for (int i = 0; i < map; i++) { + seek += mipMapSizeInBytes(i); + } + buf.limit(seek + mipMapSizeInBytes(map)); + buf.position(seek); + ByteBuffer next = buf.slice(); + buf.position(0); + buf.limit(buf.capacity()); + return new ImageInfo(next, mipMapWidth(map), mipMapHeight(map), isCompressed(), getCompressionFormat()); + } + + /** Returns an array of ImageInfos corresponding to all mipmap + levels of this DDS file. + @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps() { + return getAllMipMaps(0); + } + + /** + * Returns an array of ImageInfos corresponding to all mipmap + * levels of this DDS file. + * @param side Cubemap side or 0 for 2D texture + * @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps( int side ) { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + ImageInfo[] result = new ImageInfo[numLevels]; + for (int i = 0; i < numLevels; i++) { + result[i] = getMipMap(side, i); + } + return result; + } + + /** Converts e.g. DXT1 compression format constant (see {@link + #getCompressionFormat}) into "DXT1". + @param compressionFormat Compression format constant + @return String format code + */ + public static String getCompressionFormatName(int compressionFormat) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < 4; i++) { + char c = (char) (compressionFormat & 0xFF); + buf.append(c); + compressionFormat = compressionFormat >> 8; + } + return buf.toString(); + } + + /** Allocates a temporary, empty ByteBuffer suitable for use in a + call to glCompressedTexImage2D. This is used by the Texture + class to expand non-power-of-two DDS compressed textures to + power-of-two sizes on hardware not supporting OpenGL 2.0 and the + NPOT texture extension. The specified OpenGL internal format + must be one of GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, or + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT. + */ + public static ByteBuffer allocateBlankBuffer(int width, + int height, + int openGLInternalFormat) { + int size = width * height; + switch (openGLInternalFormat) { + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + size /= 2; + break; + + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + break; + + default: + throw new IllegalArgumentException("Illegal OpenGL texture internal format " + + openGLInternalFormat); + } + if (size == 0) + size = 1; + return GLBuffers.newDirectByteBuffer(size); + } + + public void debugPrint() { + PrintStream tty = System.err; + tty.println("Compressed texture: " + isCompressed()); + if (isCompressed()) { + int fmt = getCompressionFormat(); + String name = getCompressionFormatName(fmt); + tty.println("Compression format: 0x" + Integer.toHexString(fmt) + " (" + name + ")"); + } + tty.println("Width: " + header.width + " Height: " + header.height); + tty.println("header.pitchOrLinearSize: " + header.pitchOrLinearSize); + tty.println("header.pfRBitMask: 0x" + Integer.toHexString(header.pfRBitMask)); + tty.println("header.pfGBitMask: 0x" + Integer.toHexString(header.pfGBitMask)); + tty.println("header.pfBBitMask: 0x" + Integer.toHexString(header.pfBBitMask)); + tty.println("SurfaceDesc flags:"); + boolean recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_CAPS, "DDSD_CAPS"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_HEIGHT, "DDSD_HEIGHT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_WIDTH, "DDSD_WIDTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PITCH, "DDSD_PITCH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_BACKBUFFERCOUNT, "DDSD_BACKBUFFERCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ALPHABITDEPTH, "DDSD_ALPHABITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LPSURFACE, "DDSD_LPSURFACE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_MIPMAPCOUNT, "DDSD_MIPMAPCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LINEARSIZE, "DDSD_LINEARSIZE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_DEPTH, "DDSD_DEPTH"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw SurfaceDesc flags: 0x" + Integer.toHexString(header.flags)); + tty.println("Pixel format flags:"); + recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHAPIXELS, "DDPF_ALPHAPIXELS"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHA, "DDPF_ALPHA"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_FOURCC, "DDPF_FOURCC"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED4, "DDPF_PALETTEINDEXED4"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXEDTO8, "DDPF_PALETTEINDEXEDTO8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED8, "DDPF_PALETTEINDEXED8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGB, "DDPF_RGB"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_COMPRESSED, "DDPF_COMPRESSED"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGBTOYUV, "DDPF_RGBTOYUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_YUV, "DDPF_YUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZBUFFER, "DDPF_ZBUFFER"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED1, "DDPF_PALETTEINDEXED1"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED2, "DDPF_PALETTEINDEXED2"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZPIXELS, "DDPF_ZPIXELS"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw pixel format flags: 0x" + Integer.toHexString(header.pfFlags)); + tty.println("Depth: " + getDepth()); + tty.println("Number of mip maps: " + getNumMipMaps()); + int fmt = getPixelFormat(); + tty.print("Pixel format: "); + switch (fmt) { + case D3DFMT_R8G8B8: tty.println("D3DFMT_R8G8B8"); break; + case D3DFMT_A8R8G8B8: tty.println("D3DFMT_A8R8G8B8"); break; + case D3DFMT_X8R8G8B8: tty.println("D3DFMT_X8R8G8B8"); break; + case D3DFMT_DXT1: tty.println("D3DFMT_DXT1"); break; + case D3DFMT_DXT2: tty.println("D3DFMT_DXT2"); break; + case D3DFMT_DXT3: tty.println("D3DFMT_DXT3"); break; + case D3DFMT_DXT4: tty.println("D3DFMT_DXT4"); break; + case D3DFMT_DXT5: tty.println("D3DFMT_DXT5"); break; + case D3DFMT_UNKNOWN: tty.println("D3DFMT_UNKNOWN"); break; + default: tty.println("(unknown pixel format " + fmt + ")"); break; + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static final int MAGIC = 0x20534444; + + static class Header { + int size; // size of the DDSURFACEDESC structure + int flags; // determines what fields are valid + int height; // height of surface to be created + int width; // width of input surface + int pitchOrLinearSize; + int backBufferCountOrDepth; + int mipMapCountOrAux; // number of mip-map levels requested (in this context) + int alphaBitDepth; // depth of alpha buffer requested + int reserved1; // reserved + int surface; // pointer to the associated surface memory + // NOTE: following two entries are from DDCOLORKEY data structure + // Are overlaid with color for empty cubemap faces (unused in this reader) + int colorSpaceLowValue; + int colorSpaceHighValue; + int destBltColorSpaceLowValue; + int destBltColorSpaceHighValue; + int srcOverlayColorSpaceLowValue; + int srcOverlayColorSpaceHighValue; + int srcBltColorSpaceLowValue; + int srcBltColorSpaceHighValue; + // NOTE: following entries are from DDPIXELFORMAT data structure + // Are overlaid with flexible vertex format description of vertex + // buffers (unused in this reader) + int pfSize; // size of DDPIXELFORMAT structure + int pfFlags; // pixel format flags + int pfFourCC; // (FOURCC code) + // Following five entries have multiple interpretations, not just + // RGBA (but that's all we support right now) + int pfRGBBitCount; // how many bits per pixel + int pfRBitMask; // mask for red bits + int pfGBitMask; // mask for green bits + int pfBBitMask; // mask for blue bits + int pfABitMask; // mask for alpha channel + int ddsCaps1; // Texture and mip-map flags + int ddsCaps2; // Advanced capabilities including cubemap support + int ddsCapsReserved1; + int ddsCapsReserved2; + int textureStage; // stage in multitexture cascade + + void read(ByteBuffer buf) throws IOException { + int magic = buf.getInt(); + if (magic != MAGIC) { + throw new IOException("Incorrect magic number 0x" + + Integer.toHexString(magic) + + " (expected " + MAGIC + ")"); + } + + size = buf.getInt(); + flags = buf.getInt(); + height = buf.getInt(); + width = buf.getInt(); + pitchOrLinearSize = buf.getInt(); + backBufferCountOrDepth = buf.getInt(); + mipMapCountOrAux = buf.getInt(); + alphaBitDepth = buf.getInt(); + reserved1 = buf.getInt(); + surface = buf.getInt(); + colorSpaceLowValue = buf.getInt(); + colorSpaceHighValue = buf.getInt(); + destBltColorSpaceLowValue = buf.getInt(); + destBltColorSpaceHighValue = buf.getInt(); + srcOverlayColorSpaceLowValue = buf.getInt(); + srcOverlayColorSpaceHighValue = buf.getInt(); + srcBltColorSpaceLowValue = buf.getInt(); + srcBltColorSpaceHighValue = buf.getInt(); + pfSize = buf.getInt(); + pfFlags = buf.getInt(); + pfFourCC = buf.getInt(); + pfRGBBitCount = buf.getInt(); + pfRBitMask = buf.getInt(); + pfGBitMask = buf.getInt(); + pfBBitMask = buf.getInt(); + pfABitMask = buf.getInt(); + ddsCaps1 = buf.getInt(); + ddsCaps2 = buf.getInt(); + ddsCapsReserved1 = buf.getInt(); + ddsCapsReserved2 = buf.getInt(); + textureStage = buf.getInt(); + } + + // buf must be in little-endian byte order + void write(ByteBuffer buf) { + buf.putInt(MAGIC); + buf.putInt(size); + buf.putInt(flags); + buf.putInt(height); + buf.putInt(width); + buf.putInt(pitchOrLinearSize); + buf.putInt(backBufferCountOrDepth); + buf.putInt(mipMapCountOrAux); + buf.putInt(alphaBitDepth); + buf.putInt(reserved1); + buf.putInt(surface); + buf.putInt(colorSpaceLowValue); + buf.putInt(colorSpaceHighValue); + buf.putInt(destBltColorSpaceLowValue); + buf.putInt(destBltColorSpaceHighValue); + buf.putInt(srcOverlayColorSpaceLowValue); + buf.putInt(srcOverlayColorSpaceHighValue); + buf.putInt(srcBltColorSpaceLowValue); + buf.putInt(srcBltColorSpaceHighValue); + buf.putInt(pfSize); + buf.putInt(pfFlags); + buf.putInt(pfFourCC); + buf.putInt(pfRGBBitCount); + buf.putInt(pfRBitMask); + buf.putInt(pfGBitMask); + buf.putInt(pfBBitMask); + buf.putInt(pfABitMask); + buf.putInt(ddsCaps1); + buf.putInt(ddsCaps2); + buf.putInt(ddsCapsReserved1); + buf.putInt(ddsCapsReserved2); + buf.putInt(textureStage); + } + + private static int size() { + return 124; + } + + private static int pfSize() { + return 32; + } + + private static int writtenSize() { + return 128; + } + } + + private DDSImage() { + } + + private void readFromFile(File file) throws IOException { + fis = new FileInputStream(file); + chan = fis.getChannel(); + ByteBuffer buf = chan.map(FileChannel.MapMode.READ_ONLY, + 0, (int) file.length()); + readFromBuffer(buf); + } + + private void readFromBuffer(ByteBuffer buf) throws IOException { + this.buf = buf; + buf.order(ByteOrder.LITTLE_ENDIAN); + header = new Header(); + header.read(buf); + fixupHeader(); + } + + private void initFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + // Check size of mipmap data compared against format, width and + // height + int topmostMipmapSize = width * height; + int pitchOrLinearSize = width; + boolean isCompressed = false; + switch (d3dFormat) { + case D3DFMT_R8G8B8: topmostMipmapSize *= 3; pitchOrLinearSize *= 3; break; + case D3DFMT_A8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_X8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + topmostMipmapSize = computeCompressedBlockSize(width, height, 1, d3dFormat); + pitchOrLinearSize = topmostMipmapSize; + isCompressed = true; + break; + default: + throw new IllegalArgumentException("d3dFormat must be one of the known formats"); + } + + // Now check the mipmaps against this size + int curSize = topmostMipmapSize; + int totalSize = 0; + for (int i = 0; i < mipmapData.length; i++) { + if (mipmapData[i].remaining() != curSize) { + throw new IllegalArgumentException("Mipmap level " + i + + " didn't match expected data size (expected " + curSize + ", got " + + mipmapData[i].remaining() + ")"); + } + curSize /= 4; + totalSize += mipmapData[i].remaining(); + } + + // OK, create one large ByteBuffer to hold all of the mipmap data + totalSize += Header.writtenSize(); + ByteBuffer buf = ByteBuffer.allocate(totalSize); + buf.position(Header.writtenSize()); + for (int i = 0; i < mipmapData.length; i++) { + buf.put(mipmapData[i]); + } + this.buf = buf; + + // Allocate and initialize a Header + header = new Header(); + header.size = Header.size(); + header.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + if (mipmapData.length > 1) { + header.flags |= DDSD_MIPMAPCOUNT; + header.mipMapCountOrAux = mipmapData.length; + } + header.width = width; + header.height = height; + if (isCompressed) { + header.flags |= DDSD_LINEARSIZE; + header.pfFlags |= DDPF_FOURCC; + header.pfFourCC = d3dFormat; + } else { + header.flags |= DDSD_PITCH; + // Figure out the various settings from the pixel format + header.pfFlags |= DDPF_RGB; + switch (d3dFormat) { + case D3DFMT_R8G8B8: header.pfRGBBitCount = 24; break; + case D3DFMT_A8R8G8B8: header.pfRGBBitCount = 32; header.pfFlags |= DDPF_ALPHAPIXELS; break; + case D3DFMT_X8R8G8B8: header.pfRGBBitCount = 32; break; + } + header.pfRBitMask = 0x00FF0000; + header.pfGBitMask = 0x0000FF00; + header.pfBBitMask = 0x000000FF; + if (d3dFormat == D3DFMT_A8R8G8B8) { + header.pfABitMask = 0xFF000000; + } + } + header.pitchOrLinearSize = pitchOrLinearSize; + header.pfSize = Header.pfSize(); + // Not sure whether we can get away with leaving the rest of the + // header blank + } + + // Microsoft doesn't follow their own specifications and the + // simplest conversion using the DxTex tool to e.g. a DXT3 texture + // results in an illegal .dds file without either DDSD_PITCH or + // DDSD_LINEARSIZE set in the header's flags. This code, adapted + // from the DevIL library, fixes up the header in these situations. + private void fixupHeader() { + if (isCompressed() && !isSurfaceDescFlagSet(DDSD_LINEARSIZE)) { + // Figure out how big the linear size should be + int depth = header.backBufferCountOrDepth; + if (depth == 0) { + depth = 1; + } + + header.pitchOrLinearSize = computeCompressedBlockSize(getWidth(), getHeight(), depth, getCompressionFormat()); + header.flags |= DDSD_LINEARSIZE; + } + } + + private static int computeCompressedBlockSize(int width, + int height, + int depth, + int compressionFormat) { + int blockSize = ((width + 3)/4) * ((height + 3)/4) * ((depth + 3)/4); + switch (compressionFormat) { + case D3DFMT_DXT1: blockSize *= 8; break; + default: blockSize *= 16; break; + } + return blockSize; + } + + private int mipMapWidth(int map) { + int width = getWidth(); + for (int i = 0; i < map; i++) { + width >>= 1; + } + return Math.max(width, 1); + } + + private int mipMapHeight(int map) { + int height = getHeight(); + for (int i = 0; i < map; i++) { + height >>= 1; + } + return Math.max(height, 1); + } + + private int mipMapSizeInBytes(int map) { + int width = mipMapWidth(map); + int height = mipMapHeight(map); + if (isCompressed()) { + int blockSize = (getCompressionFormat() == D3DFMT_DXT1 ? 8 : 16); + return ((width+3)/4)*((height+3)/4)*blockSize; + } else { + return width * height * (getDepth() / 8); + } + } + + private int sideSizeInBytes() { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + + int size = 0; + for (int i = 0; i < numLevels; i++) { + size += mipMapSizeInBytes(i); + } + + return size; + } + + private int sideShiftInBytes(int side) { + int[] sides = { + DDSCAPS2_CUBEMAP_POSITIVEX, + DDSCAPS2_CUBEMAP_NEGATIVEX, + DDSCAPS2_CUBEMAP_POSITIVEY, + DDSCAPS2_CUBEMAP_NEGATIVEY, + DDSCAPS2_CUBEMAP_POSITIVEZ, + DDSCAPS2_CUBEMAP_NEGATIVEZ + }; + + int shift = 0; + int sideSize = sideSizeInBytes(); + for (int i = 0; i < sides.length; i++) { + int temp = sides[i]; + if ((temp & side) != 0) { + return shift; + } + + shift += sideSize; + } + + throw new RuntimeException("Illegal side: " + side); + } + + private boolean printIfRecognized(PrintStream tty, int flags, int flag, String what) { + if ((flags & flag) != 0) { + tty.println(what); + return true; + } + return false; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java new file mode 100755 index 000000000..d5f49599c --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataInputStream.java @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.FilterInputStream; +import java.io.InputStream; +import java.io.FileInputStream; +import java.io.EOFException; +import java.io.IOException; + +/** + * Little Endian Data Input Stream. + * + * This class implements an input stream filter to allow reading + * of java native datatypes from an input stream which has those + * native datatypes stored in a little endian byte order.<p> + * + * This is the sister class of the DataInputStream which allows + * for reading of java native datatypes from an input stream with + * the datatypes stored in big endian byte order.<p> + * + * This class implements the minimum required and calls DataInputStream + * for some of the required methods for DataInput.<p> + * + * Not all methods are implemented due to lack of immediatte requirement + * for that functionality. It is not clear if it is ever going to be + * functionally required to be able to read UTF data in a LittleEndianManner<p> + * + * @author Robin Luiten + * @version 1.1 15/Dec/1997 + */ +public class LEDataInputStream extends FilterInputStream implements DataInput +{ + /** + * To reuse some of the non endian dependent methods from + * DataInputStreams methods. + */ + DataInputStream dataIn; + + public LEDataInputStream(InputStream in) + { + super(in); + dataIn = new DataInputStream(in); + } + + public void close() throws IOException + { + dataIn.close(); // better close as we create it. + // this will close underlying as well. + } + + public synchronized final int read(byte b[]) throws IOException + { + return dataIn.read(b, 0, b.length); + } + + public synchronized final int read(byte b[], int off, int len) throws IOException + { + int rl = dataIn.read(b, off, len); + return rl; + } + + public final void readFully(byte b[]) throws IOException + { + dataIn.readFully(b, 0, b.length); + } + + public final void readFully(byte b[], int off, int len) throws IOException + { + dataIn.readFully(b, off, len); + } + + public final int skipBytes(int n) throws IOException + { + return dataIn.skipBytes(n); + } + + public final boolean readBoolean() throws IOException + { + int ch = dataIn.read(); + if (ch < 0) + throw new EOFException(); + return (ch != 0); + } + + public final byte readByte() throws IOException + { + int ch = dataIn.read(); + if (ch < 0) + throw new EOFException(); + return (byte)(ch); + } + + public final int readUnsignedByte() throws IOException + { + int ch = dataIn.read(); + if (ch < 0) + throw new EOFException(); + return ch; + } + + public final short readShort() throws IOException + { + int ch1 = dataIn.read(); + int ch2 = dataIn.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (short)((ch1 << 0) + (ch2 << 8)); + } + + public final int readUnsignedShort() throws IOException + { + int ch1 = dataIn.read(); + int ch2 = dataIn.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (ch1 << 0) + (ch2 << 8); + } + + public final char readChar() throws IOException + { + int ch1 = dataIn.read(); + int ch2 = dataIn.read(); + if ((ch1 | ch2) < 0) + throw new EOFException(); + return (char)((ch1 << 0) + (ch2 << 8)); + } + + public final int readInt() throws IOException + { + int ch1 = dataIn.read(); + int ch2 = dataIn.read(); + int ch3 = dataIn.read(); + int ch4 = dataIn.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) + throw new EOFException(); + return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24)); + } + + public final long readLong() throws IOException + { + int i1 = readInt(); + int i2 = readInt(); + return ((long)(i1) & 0xFFFFFFFFL) + (i2 << 32); + } + + public final float readFloat() throws IOException + { + return Float.intBitsToFloat(readInt()); + } + + public final double readDouble() throws IOException + { + return Double.longBitsToDouble(readLong()); + } + + /** + * dont call this it is not implemented. + * @return empty new string + **/ + public final String readLine() throws IOException + { + return new String(); + } + + /** + * dont call this it is not implemented + * @return empty new string + **/ + public final String readUTF() throws IOException + { + return new String(); + } + + /** + * dont call this it is not implemented + * @return empty new string + **/ + public final static String readUTF(DataInput in) throws IOException + { + return new String(); + } +} + diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java new file mode 100755 index 000000000..e1e1ca924 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/LEDataOutputStream.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.FilterOutputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * Little Endian Data Output Stream. + * + * This class implements an output stream filter to allow writing + * of java native datatypes to an output stream which has those + * native datatypes stored in a little endian byte order.<p> + * + * This is the sister class of the DataOutputStream which allows + * for writing of java native datatypes to an output stream with + * the datatypes stored in big endian byte order.<p> + * + * This class implements the minimum required and calls DataOutputStream + * for some of the required methods for DataOutput.<p> + * + * Not all methods are implemented due to lack of immediate requirement + * for that functionality. It is not clear if it is ever going to be + * functionally required to be able to read UTF data in a LittleEndianManner<p> + * + */ +public class LEDataOutputStream extends FilterOutputStream implements DataOutput +{ + /** + * To reuse some of the non endian dependent methods from + * DataOutputStream's methods. + */ + DataOutputStream dataOut; + + public LEDataOutputStream(OutputStream out) + { + super(out); + dataOut = new DataOutputStream(out); + } + + public void close() throws IOException + { + dataOut.close(); // better close as we create it. + // this will close underlying as well. + } + + public synchronized final void write(byte b[]) throws IOException + { + dataOut.write(b, 0, b.length); + } + + public synchronized final void write(byte b[], int off, int len) throws IOException + { + dataOut.write(b, off, len); + } + + public final void write(int b) throws IOException + { + dataOut.write(b); + } + + public final void writeBoolean(boolean v) throws IOException + { + dataOut.writeBoolean(v); + } + + public final void writeByte(int v) throws IOException + { + dataOut.writeByte(v); + } + + /** Don't call this -- not implemented */ + public final void writeBytes(String s) throws IOException + { + throw new UnsupportedOperationException(); + } + + public final void writeChar(int v) throws IOException + { + dataOut.writeChar(((v >> 8) & 0xff) | + ((v & 0xff) << 8)); + } + + /** Don't call this -- not implemented */ + public final void writeChars(String s) throws IOException + { + throw new UnsupportedOperationException(); + } + + public final void writeDouble(double v) throws IOException + { + writeLong(Double.doubleToRawLongBits(v)); + } + + public final void writeFloat(float v) throws IOException + { + writeInt(Float.floatToRawIntBits(v)); + } + + public final void writeInt(int v) throws IOException + { + dataOut.writeInt((v >>> 24) | + ((v >>> 8) & 0xff00) | + ((v << 8) & 0x00ff00) | + (v << 24)); + } + + public final void writeLong(long v) throws IOException + { + writeInt((int) v); + writeInt((int) (v >>> 32)); + } + + public final void writeShort(int v) throws IOException + { + dataOut.writeShort(((v >> 8) & 0xff) | + ((v & 0xff) << 8)); + } + + /** Don't call this -- not implemented */ + public final void writeUTF(String s) throws IOException + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java new file mode 100644 index 000000000..499dce7fb --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/NetPbmTextureWriter.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.net.*; +import java.nio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.spi.*; + +public class NetPbmTextureWriter implements TextureWriter { + int magic; + + public NetPbmTextureWriter() { + this(0); // auto + } + + /** + * supported magic values are:<br> + * <pre> + * magic 0 - detect by file suffix (TextureIO compliant) + * magic 6 - PPM binary RGB + * magic 7 - PAM binary RGB or RGBA + * </pre> + */ + public NetPbmTextureWriter(int magic) { + switch(magic) { + case 0: + case 6: + case 7: + break; + default: + throw new GLException("Unsupported magic: "+magic+", should be 0 (auto), 6 (PPM) or 7 (PAM)"); + } + this.magic = magic; + } + + public int getMagic() { return magic; } + + public static final String PPM = "ppm"; + public static final String PAM = "pam"; + + public String getSuffix() { return (magic==6)?PPM:PAM; } + + public boolean write(File file, + TextureData data) throws IOException { + + // file suffix selection + if (0==magic) { + if (PPM.equals(FileUtil.getFileSuffix(file))) { + magic = 6; + } else if (PAM.equals(FileUtil.getFileSuffix(file))) { + magic = 7; + } else { + return false; + } + } + + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + + int comps = ( pixelFormat == GL.GL_RGBA ) ? 4 : 3 ; + + if(magic==6 && comps==4) { + throw new IOException("NetPbmTextureWriter magic 6 (PPM) doesn't RGBA pixel format, use magic 7 (PAM)"); + } + + FileOutputStream fos = new FileOutputStream(file); + + StringBuffer header = new StringBuffer(); + header.append("P"); + header.append(magic); + header.append("\n"); + if(7==magic) { + header.append("WIDTH "); + } + header.append(data.getWidth()); + if(7==magic) { + header.append("\nHEIGHT "); + } else { + header.append(" "); + } + header.append(data.getHeight()); + if(7==magic) { + header.append("\nDEPTH "); + header.append(comps); + header.append("\nMAXVAL 255\nTUPLTYPE "); + if(pixelFormat == GL.GL_RGBA) { + header.append("RGB_ALPHA"); + } else { + header.append("RGB"); + } + header.append("\nENDHDR\n"); + } else { + header.append("\n255\n"); + } + + fos.write(header.toString().getBytes()); + + ByteBuffer buf = (ByteBuffer) data.getBuffer(); + if (buf == null) { + buf = (ByteBuffer) data.getMipmapData()[0]; + } + buf.rewind(); + + byte[] bufArray = null; + + try { + bufArray = buf.array(); + } catch (Throwable t) {} + if(null==bufArray) { + bufArray = new byte[data.getWidth()*data.getHeight()*comps]; + buf.get(bufArray); + buf.rewind(); + } + + fos.write(bufArray); + fos.close(); + + return true; + } + + throw new IOException("NetPbmTextureWriter writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java new file mode 100755 index 000000000..bb5040a31 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/SGIImage.java @@ -0,0 +1,670 @@ +/* + * Portions Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; + +/** <p> Reads and writes SGI RGB/RGBA images. </p> + + <p> Written from <a href = + "http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/">Paul + Bourke's adaptation</a> of the <a href = + "http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html">SGI + specification</a>. </p> +*/ + +public class SGIImage { + private Header header; + private int format; + private byte[] data; + // Used for decoding RLE-compressed images + private int[] rowStart; + private int[] rowSize; + private int rleEnd; + private byte[] tmpData; + private byte[] tmpRead; + + private static final int MAGIC = 474; + + static class Header { + short magic; // IRIS image file magic number + // This should be decimal 474 + byte storage; // Storage format + // 0 for uncompressed + // 1 for RLE compression + byte bpc; // Number of bytes per pixel channel + // Legally 1 or 2 + short dimension; // Number of dimensions + // Legally 1, 2, or 3 + // 1 means a single row, XSIZE long + // 2 means a single 2D image + // 3 means multiple 2D images + short xsize; // X size in pixels + short ysize; // Y size in pixels + short zsize; // Number of channels + // 1 indicates greyscale + // 3 indicates RGB + // 4 indicates RGB and Alpha + int pixmin; // Minimum pixel value + // This is the lowest pixel value in the image + int pixmax; // Maximum pixel value + // This is the highest pixel value in the image + int dummy; // Ignored + // Normally set to 0 + String imagename; // Image name; 80 bytes long + // Must be null terminated, therefore at most 79 bytes + int colormap; // Colormap ID + // 0 - normal mode + // 1 - dithered, 3 mits for red and green, 2 for blue, obsolete + // 2 - index colour, obsolete + // 3 - not an image but a colourmap + // 404 bytes char DUMMY Ignored + // Should be set to 0, makes the header 512 bytes. + + Header() { + magic = MAGIC; + } + + Header(DataInputStream in) throws IOException { + magic = in.readShort(); + storage = in.readByte(); + bpc = in.readByte(); + dimension = in.readShort(); + xsize = in.readShort(); + ysize = in.readShort(); + zsize = in.readShort(); + pixmin = in.readInt(); + pixmax = in.readInt(); + dummy = in.readInt(); + byte[] tmpname = new byte[80]; + in.read(tmpname); + int numChars = 0; + while (tmpname[numChars++] != 0); + imagename = new String(tmpname, 0, numChars); + colormap = in.readInt(); + byte[] tmp = new byte[404]; + in.read(tmp); + } + + public String toString() { + return ("magic: " + magic + + " storage: " + (int) storage + + " bpc: " + (int) bpc + + " dimension: " + dimension + + " xsize: " + xsize + + " ysize: " + ysize + + " zsize: " + zsize + + " pixmin: " + pixmin + + " pixmax: " + pixmax + + " imagename: " + imagename + + " colormap: " + colormap); + } + } + + private SGIImage(Header header) { + this.header = header; + } + + /** Reads an SGI image from the specified file. */ + public static SGIImage read(String filename) throws IOException { + return read(new FileInputStream(filename)); + } + + /** Reads an SGI image from the specified InputStream. */ + public static SGIImage read(InputStream in) throws IOException { + DataInputStream dIn = new DataInputStream(new BufferedInputStream(in)); + + Header header = new Header(dIn); + SGIImage res = new SGIImage(header); + res.decodeImage(dIn); + return res; + } + + /** Writes this SGIImage to the specified file name. If + flipVertically is set, outputs the scanlines from top to bottom + rather than the default bottom to top order. */ + public void write(String filename, boolean flipVertically) throws IOException { + write(new File(filename), flipVertically); + } + + /** Writes this SGIImage to the specified file. If flipVertically is + set, outputs the scanlines from top to bottom rather than the + default bottom to top order. */ + public void write(File file, boolean flipVertically) throws IOException { + writeImage(file, data, header.xsize, header.ysize, header.zsize, flipVertically); + } + + /** Creates an SGIImage from the specified data in either RGB or + RGBA format. */ + public static SGIImage createFromData(int width, + int height, + boolean hasAlpha, + byte[] data) { + Header header = new Header(); + header.xsize = (short) width; + header.ysize = (short) height; + header.zsize = (short) (hasAlpha ? 4 : 3); + SGIImage image = new SGIImage(header); + image.data = data; + return image; + } + + /** Determines from the magic number whether the given InputStream + points to an SGI RGB image. The given InputStream must return + true from markSupported() and support a minimum of two bytes + of read-ahead. */ + public static boolean isSGIImage(InputStream in) throws IOException { + if (!(in instanceof BufferedInputStream)) { + in = new BufferedInputStream(in); + } + if (!in.markSupported()) { + throw new IOException("Can not test non-destructively whether given InputStream is an SGI RGB image"); + } + DataInputStream dIn = new DataInputStream(in); + dIn.mark(4); + short magic = dIn.readShort(); + dIn.reset(); + return (magic == MAGIC); + } + + /** Returns the width of the image. */ + public int getWidth() { + return header.xsize; + } + + /** Returns the height of the image. */ + public int getHeight() { + return header.ysize; + } + + /** Returns the OpenGL format for this texture; e.g. GL.GL_RGB or GL.GL_RGBA. */ + public int getFormat() { + return format; + } + + /** Returns the raw data for this texture in the correct + (bottom-to-top) order for calls to glTexImage2D. */ + public byte[] getData() { return data; } + + public String toString() { + return header.toString(); + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private void decodeImage(DataInputStream in) throws IOException { + if (header.storage == 1) { + // Read RLE compression data; row starts and sizes + int x = header.ysize * header.zsize; + rowStart = new int[x]; + rowSize = new int[x]; + rleEnd = 4 * 2 * x + 512; + for (int i = 0; i < x; i++) { + rowStart[i] = in.readInt(); + } + for (int i = 0; i < x; i++) { + rowSize[i] = in.readInt(); + } + tmpRead = new byte[header.xsize * 256]; + } + tmpData = readAll(in); + + int xsize = header.xsize; + int ysize = header.ysize; + int zsize = header.zsize; + int lptr = 0; + + data = new byte[xsize * ysize * 4]; + byte[] rbuf = new byte[xsize]; + byte[] gbuf = new byte[xsize]; + byte[] bbuf = new byte[xsize]; + byte[] abuf = new byte[xsize]; + for (int y = 0; y < ysize; y++) { + if (zsize >= 4) { + getRow(rbuf, y, 0); + getRow(gbuf, y, 1); + getRow(bbuf, y, 2); + getRow(abuf, y, 3); + rgbatorgba(rbuf, gbuf, bbuf, abuf, data, lptr); + } else if (zsize == 3) { + getRow(rbuf, y, 0); + getRow(gbuf, y, 1); + getRow(bbuf, y, 2); + rgbtorgba(rbuf, gbuf, bbuf, data, lptr); + } else if (zsize == 2) { + getRow(rbuf, y, 0); + getRow(abuf, y, 1); + latorgba(rbuf, abuf, data, lptr); + } else { + getRow(rbuf, y, 0); + bwtorgba(rbuf, data, lptr); + } + lptr += 4 * xsize; + } + rowStart = null; + rowSize = null; + tmpData = null; + tmpRead = null; + format = GL.GL_RGBA; + header.zsize = 4; + } + + private void getRow(byte[] buf, int y, int z) { + if (header.storage == 1) { + int offs = rowStart[y + z * header.ysize] - rleEnd; + System.arraycopy(tmpData, offs, tmpRead, 0, rowSize[y + z * header.ysize]); + int iPtr = 0; + int oPtr = 0; + for (;;) { + byte pixel = tmpRead[iPtr++]; + int count = (int) (pixel & 0x7F); + if (count == 0) { + return; + } + if ((pixel & 0x80) != 0) { + while ((count--) > 0) { + buf[oPtr++] = tmpRead[iPtr++]; + } + } else { + pixel = tmpRead[iPtr++]; + while ((count--) > 0) { + buf[oPtr++] = pixel; + } + } + } + } else { + int offs = (y * header.xsize) + (z * header.xsize * header.ysize); + System.arraycopy(tmpData, offs, buf, 0, header.xsize); + } + } + + private void bwtorgba(byte[] b, byte[] dest, int lptr) { + for (int i = 0; i < b.length; i++) { + dest[4 * i + lptr + 0] = b[i]; + dest[4 * i + lptr + 1] = b[i]; + dest[4 * i + lptr + 2] = b[i]; + dest[4 * i + lptr + 3] = (byte) 0xFF; + } + } + + private void latorgba(byte[] b, byte[] a, byte[] dest, int lptr) { + for (int i = 0; i < b.length; i++) { + dest[4 * i + lptr + 0] = b[i]; + dest[4 * i + lptr + 1] = b[i]; + dest[4 * i + lptr + 2] = b[i]; + dest[4 * i + lptr + 3] = a[i]; + } + } + + private void rgbtorgba(byte[] r, byte[] g, byte[] b, byte[] dest, int lptr) { + for (int i = 0; i < b.length; i++) { + dest[4 * i + lptr + 0] = r[i]; + dest[4 * i + lptr + 1] = g[i]; + dest[4 * i + lptr + 2] = b[i]; + dest[4 * i + lptr + 3] = (byte) 0xFF; + } + } + + private void rgbatorgba(byte[] r, byte[] g, byte[] b, byte[] a, byte[] dest, int lptr) { + for (int i = 0; i < b.length; i++) { + dest[4 * i + lptr + 0] = r[i]; + dest[4 * i + lptr + 1] = g[i]; + dest[4 * i + lptr + 2] = b[i]; + dest[4 * i + lptr + 3] = a[i]; + } + } + + private static byte imgref(byte[] i, + int x, + int y, + int z, + int xs, + int ys, + int zs) { + return i[(xs*ys*z)+(xs*y)+x]; + } + + + private void writeHeader(DataOutputStream stream, + int xsize, int ysize, int zsize, boolean rle) throws IOException { + // effects: outputs the 512-byte IRIS RGB header to STREAM, using xsize, + // ysize, and depth as the dimensions of the image. NOTE that + // the following defaults are used: + // STORAGE = 1 (storage format = RLE) + // BPC = 1 (# bytes/channel) + // DIMENSION = 3 + // PIXMIN = 0 + // PIXMAX = 255 + // IMAGENAME = <80 nulls> + // COLORMAP = 0 + // See ftp://ftp.sgi.com/pub/sgi/SGIIMAGESPEC for more details. + + // write out MAGIC, STORAGE, BPC + stream.writeShort(474); + stream.write((rle ? 1 : 0)); + stream.write(1); + + // write out DIMENSION + stream.writeShort(3); + + // write XSIZE, YSIZE, ZSIZE + stream.writeShort(xsize); + stream.writeShort(ysize); + stream.writeShort(zsize); + + // write PIXMIN, PIXMAX + stream.writeInt(0); + stream.writeInt(255); + + // write DUMMY + stream.writeInt(0); + + // write IMAGENAME + for (int i = 0; i < 80; i++) + stream.write(0); + + // write COLORMAP + stream.writeInt(0); + + // write DUMMY (404 bytes) + for (int i = 0; i < 404; i++) + stream.write(0); + } + + private void writeImage(File file, + byte[] data, + int xsize, + int ysize, + int zsize, + boolean yflip) throws IOException { + // Input data is in RGBRGBRGB or RGBARGBARGBA format; first unswizzle it + byte[] tmpData = new byte[xsize * ysize * zsize]; + int dest = 0; + for (int i = 0; i < zsize; i++) { + for (int j = i; j < (xsize * ysize * zsize); j += zsize) { + tmpData[dest++] = data[j]; + } + } + data = tmpData; + + // requires: DATA must be an array of size XSIZE * YSIZE * ZSIZE, + // indexed in the following manner: + // data[0] ...data[xsize-1] == first row of first channel + // data[xsize]...data[2*xsize-1] == second row of first channel + // ... data[(ysize - 1) * xsize]...data[(ysize * xsize) - 1] == + // last row of first channel + // Later channels follow the same format. + // *** NOTE that "first row" is defined by the BOTTOM ROW of + // the image. That is, the origin is in the lower left corner. + // effects: writes out an SGI image to FILE, RLE-compressed, INCLUDING + // header, of dimensions (xsize, ysize, zsize), and containing + // the data in DATA. If YFLIP is set, outputs the data in DATA + // in reverse order vertically (equivalent to a flip about the + // x axis). + + // Build the offset tables + int[] starttab = new int[ysize * zsize]; + int[] lengthtab = new int[ysize * zsize]; + + // Temporary buffer for holding RLE data. + // Note that this makes the assumption that RLE-compressed data will + // never exceed twice the size of the input data. + // There are surely formal proofs about how big the RLE buffer should + // be, as well as what the optimal look-ahead size is (i.e. don't switch + // copy/repeat modes for less than N repeats). However, I'm going from + // empirical evidence here; the break-even point seems to be a look- + // ahead of 3. (That is, if the three values following this one are all + // the same as the current value, switch to repeat mode.) + int lookahead = 3; + byte[] rlebuf = new byte[2 * xsize * ysize * zsize]; + + int cur_loc = 0; // current offset location. + int ptr = 0; + int total_size = 0; + int ystart = 0; + int yincr = 1; + int yend = ysize; + + if (yflip) { + ystart = ysize - 1; + yend = -1; + yincr = -1; + } + + boolean DEBUG = false; + + for (int z = 0; z < zsize; z++) { + for (int y = ystart; y != yend; y += yincr) { + // RLE-compress each row. + + int x = 0; + byte count = 0; + boolean repeat_mode = false; + boolean should_switch = false; + int start_ptr = ptr; + int num_ptr = ptr++; + byte repeat_val = 0; + + while (x < xsize) { + // see if we should switch modes + should_switch = false; + if (repeat_mode) { + if (imgref(data, x, y, z, xsize, ysize, zsize) != repeat_val) { + should_switch = true; + } + } else { + // look ahead to see if we should switch to repeat mode. + // stay within the scanline for the lookahead + if ((x + lookahead) < xsize) { + should_switch = true; + for (int i = 1; i <= lookahead; i++) { + if (DEBUG) + System.err.println("left side was " + ((int) imgref(data, x, y, z, xsize, ysize, zsize)) + + ", right side was " + (int)imgref(data, x+i, y, z, xsize, ysize, zsize)); + + if (imgref(data, x, y, z, xsize, ysize, zsize) != + imgref(data, x+i, y, z, xsize, ysize, zsize)) + should_switch = false; + } + } + } + + if (should_switch || (count == 127)) { + // update the number of elements we repeated/copied + if (x > 0) { + if (repeat_mode) + rlebuf[num_ptr] = count; + else + rlebuf[num_ptr] = (byte) (count | 0x80); + } + // perform mode switch if necessary; output repeat_val if + // switching FROM repeat mode, and set it if switching + // TO repeat mode. + if (repeat_mode) { + if (should_switch) + repeat_mode = false; + rlebuf[ptr++] = repeat_val; + } else { + if (should_switch) + repeat_mode = true; + repeat_val = imgref(data, x, y, z, xsize, ysize, zsize); + } + + if (x > 0) { + // reset the number pointer + num_ptr = ptr++; + // reset number of bytes copied + count = 0; + } + } + + // if not in repeat mode, copy element to ptr + if (!repeat_mode) { + rlebuf[ptr++] = imgref(data, x, y, z, xsize, ysize, zsize); + } + count++; + + if (x == xsize - 1) { + // Need to store the number of pixels we copied/repeated. + if (repeat_mode) { + rlebuf[num_ptr] = count; + // If we ended the row in repeat mode, store the + // repeated value + rlebuf[ptr++] = repeat_val; + } + else + rlebuf[num_ptr] = (byte) (count | 0x80); + + // output zero counter for the last value in the row + rlebuf[ptr++] = 0; + } + + x++; + } + // output this row's length into the length table + int rowlen = ptr - start_ptr; + if (yflip) + lengthtab[ysize*z+(ysize-y-1)] = rowlen; + else + lengthtab[ysize*z+y] = rowlen; + // add to the start table, and update the current offset + if (yflip) + starttab[ysize*z+(ysize-y-1)] = cur_loc; + else + starttab[ysize*z+y] = cur_loc; + cur_loc += rowlen; + } + } + + // Now we have the offset tables computed, as well as the RLE data. + // Output this information to the file. + total_size = ptr; + + if (DEBUG) + System.err.println("total_size was " + total_size); + + DataOutputStream stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + + writeHeader(stream, xsize, ysize, zsize, true); + + int SIZEOF_INT = 4; + for (int i = 0; i < (ysize * zsize); i++) + stream.writeInt(starttab[i] + 512 + (2 * ysize * zsize * SIZEOF_INT)); + for (int i = 0; i < (ysize * zsize); i++) + stream.writeInt(lengthtab[i]); + for (int i = 0; i < total_size; i++) + stream.write(rlebuf[i]); + + stream.close(); + } + + private byte[] readAll(DataInputStream in) throws IOException { + byte[] dest = new byte[16384]; + int pos = 0; + int numRead = 0; + + boolean done = false; + + do { + numRead = in.read(dest, pos, dest.length - pos); + if (pos == dest.length) { + // Resize destination buffer + byte[] newDest = new byte[2 * dest.length]; + System.arraycopy(dest, 0, newDest, 0, pos); + dest = newDest; + } + if (numRead > 0) { + pos += numRead; + } + + done = ((numRead == -1) || (in.available() == 0)); + } while (!done); + + // Trim destination buffer + if (pos != dest.length) { + byte[] finalDest = new byte[pos]; + System.arraycopy(dest, 0, finalDest, 0, pos); + dest = finalDest; + } + + return dest; + } + + // Test case + /* + import java.awt.image.*; + import javax.swing.*; + + public static void main(String[] args) { + for (int i = 0; i < args.length; i++) { + try { + System.out.println(args[i] + ":"); + SGIImage image = SGIImage.read(args[i]); + System.out.println(image); + BufferedImage img = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR); + WritableRaster raster = img.getRaster(); + DataBufferByte db = (DataBufferByte) raster.getDataBuffer(); + byte[] src = image.getData(); + byte[] dest = db.getData(); + for (int j = 0; j < src.length; j += 4) { + dest[j + 0] = src[j + 3]; + dest[j + 1] = src[j + 2]; + dest[j + 2] = src[j + 1]; + dest[j + 3] = src[j + 0]; + } + // System.arraycopy(src, 0, dest, 0, src.length); + ImageIcon icon = new ImageIcon(img); + JLabel label = new JLabel(); + label.setIcon(icon); + JFrame frame = new JFrame(args[i]); + frame.getContentPane().add(label); + frame.pack(); + frame.show(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + */ +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp new file mode 100755 index 000000000..6e6e4ab04 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.spi.*; +import com.jogamp.opengl.util.texture.*; + +/** + * Targa image reader and writer adapted from sources of the <a href = + * "http://java.sun.com/products/jimi/">Jimi</a> image I/O class library. + * + * <P> + * + * Image decoder for image data stored in TGA file format. + * Currently only the original TGA file format is supported. This is + * because the new TGA format has data at the end of the file, getting + * to the end of a file in an InputStream orient environment presents + * several difficulties which are avoided at the moment. + * + * <P> + * + * This is a simple decoder and is only setup to load a single image + * from the input stream + * + * <P> + * + * @author Robin Luiten + * @author Kenneth Russell + * @version $Revision: 1768 $ + */ + +public class TGAImage { + private Header header; + private int format; + private int bpp; + private ByteBuffer data; + + private TGAImage(Header header) { + this.header = header; + } + + /** + * This class reads in all of the TGA image header in addition it also + * reads in the imageID field as it is convenient to handle that here. + * + * @author Robin Luiten + * @version 1.1 + */ + public static class Header { + /** Set of possible file format TGA types */ + public final static int TYPE_NEW = 0; + public final static int TYPE_OLD = 1; + public final static int TYPE_UNK = 2; // cant rewind stream so unknown for now. + + /** Set of possible image types in TGA file */ + public final static int NO_IMAGE = 0; // no image data + public final static int UCOLORMAPPED = 1; // uncompressed color mapped image + public final static int UTRUECOLOR = 2; // uncompressed true color image + public final static int UBLACKWHITE = 3; // uncompressed black and white image + public final static int COLORMAPPED = 9; // compressed color mapped image + public final static int TRUECOLOR = 10; // compressed true color image + public final static int BLACKWHITE = 11; // compressed black and white image + + /** Field image descriptor bitfield values definitions */ + public final static int ID_ATTRIBPERPIXEL = 0xF; + public final static int ID_RIGHTTOLEFT = 0x10; + public final static int ID_TOPTOBOTTOM = 0x20; + public final static int ID_INTERLEAVE = 0xC0; + + /** Field image descriptor / interleave values */ + public final static int I_NOTINTERLEAVED = 0; + public final static int I_TWOWAY = 1; + public final static int I_FOURWAY = 2; + + /** Type of this TGA file format */ + private int tgaType; + + /** initial TGA image data fields */ + private int idLength; // byte value + private int colorMapType; // byte value + private int imageType; // byte value + + /** TGA image colour map fields */ + private int firstEntryIndex; + private int colorMapLength; + private byte colorMapEntrySize; + + /** TGA image specification fields */ + private int xOrigin; + private int yOrigin; + private int width; + private int height; + private byte pixelDepth; + private byte imageDescriptor; + + private byte[] imageIDbuf; + private String imageID; + + // For construction from user data + Header() { + tgaType = TYPE_OLD; // dont try and get footer. + } + + Header(LEDataInputStream in) throws IOException { + int ret; + + tgaType = TYPE_OLD; // dont try and get footer. + + // initial header fields + idLength = in.readUnsignedByte(); + colorMapType = in.readUnsignedByte(); + imageType = in.readUnsignedByte(); + + // color map header fields + firstEntryIndex = in.readUnsignedShort(); + colorMapLength = in.readUnsignedShort(); + colorMapEntrySize = in.readByte(); + + // TGA image specification fields + xOrigin = in.readUnsignedShort(); + yOrigin = in.readUnsignedShort(); + width = in.readUnsignedShort(); + height = in.readUnsignedShort(); + pixelDepth = in.readByte(); + imageDescriptor = in.readByte(); + + if (idLength > 0) { + imageIDbuf = new byte[idLength]; + in.read(imageIDbuf, 0, idLength); + imageID = new String(imageIDbuf, "US-ASCII"); + } + } + + public int tgaType() { return tgaType; } + + /** initial TGA image data fields */ + public int idLength() { return idLength; } + public int colorMapType() { return colorMapType; } + public int imageType() { return imageType; } + + /** TGA image colour map fields */ + public int firstEntryIndex() { return firstEntryIndex; } + public int colorMapLength() { return colorMapLength; } + public byte colorMapEntrySize() { return colorMapEntrySize; } + + /** TGA image specification fields */ + public int xOrigin() { return xOrigin; } + public int yOrigin() { return yOrigin; } + public int width() { return width; } + public int height() { return height; } + public byte pixelDepth() { return pixelDepth; } + public byte imageDescriptor() { return imageDescriptor; } + + /** bitfields in imageDescriptor */ + public byte attribPerPixel() { return (byte)(imageDescriptor & ID_ATTRIBPERPIXEL); } + public boolean rightToLeft() { return ((imageDescriptor & ID_RIGHTTOLEFT) != 0); } + public boolean topToBottom() { return ((imageDescriptor & ID_TOPTOBOTTOM) != 0); } + public byte interleave() { return (byte)((imageDescriptor & ID_INTERLEAVE) >> 6); } + + public byte[] imageIDbuf() { return imageIDbuf; } + public String imageID() { return imageID; } + + public String toString() { + return "TGA Header " + + " id length: " + idLength + + " color map type: "+ colorMapType + + " image type: "+ imageType + + " first entry index: " + firstEntryIndex + + " color map length: " + colorMapLength + + " color map entry size: " + colorMapEntrySize + + " x Origin: " + xOrigin + + " y Origin: " + yOrigin + + " width: "+ width + + " height: "+ height + + " pixel depth: "+ pixelDepth + + " image descriptor: "+ imageDescriptor + + (imageIDbuf == null ? "" : (" ID String: " + imageID)); + } + + public int size() { return 18 + idLength; } + + private void write(LEDataOutputStream output) throws IOException { + output.write(idLength); + output.write(colorMapType); + output.write(imageType); + output.writeShort(firstEntryIndex); + output.writeShort(colorMapLength); + output.write(colorMapEntrySize); + output.writeShort(xOrigin); + output.writeShort(yOrigin); + output.writeShort(width); + output.writeShort(height); + output.write(pixelDepth); + output.write(imageDescriptor); + if (idLength > 0) { + try { + byte[] chars = imageID.getBytes("US-ASCII"); + output.write(chars); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + } + } + + + /** + * Identifies the image type of the tga image data and loads + * it into the JimiImage structure. This was taken from the + * prototype and modified for the new Jimi structure + */ + private void decodeImage(LEDataInputStream dIn) throws IOException { + switch (header.imageType()) { + case Header.UCOLORMAPPED: + throw new IOException("TGADecoder Uncompressed Colormapped images not supported"); + + case Header.UTRUECOLOR: // pixelDepth 15, 16, 24 and 32 + switch (header.pixelDepth) { + case 16: + throw new IOException("TGADecoder Compressed 16-bit True Color images not supported"); + + case 24: + case 32: + decodeRGBImageU24_32(dIn); + break; + } + break; + + case Header.UBLACKWHITE: + throw new IOException("TGADecoder Uncompressed Grayscale images not supported"); + + case Header.COLORMAPPED: + throw new IOException("TGADecoder Compressed Colormapped images not supported"); + + case Header.TRUECOLOR: + throw new IOException("TGADecoder Compressed True Color images not supported"); + + case Header.BLACKWHITE: + throw new IOException("TGADecoder Compressed Grayscale images not supported"); + } + } + + /** + * This assumes that the body is for a 24 bit or 32 bit for a + * RGB or ARGB image respectively. + */ + private void decodeRGBImageU24_32(LEDataInputStream dIn) throws IOException { + int i; // row index + int j; // column index + int y; // output row index + int raw; // index through the raw input buffer + int rawWidth = header.width() * (header.pixelDepth() / 8); + byte[] rawBuf = new byte[rawWidth]; + byte[] tmpData = new byte[rawWidth * header.height()]; + + for (i = 0; i < header.height(); ++i) { + dIn.readFully(rawBuf, 0, rawWidth); + + if (header.topToBottom()) + y = header.height - i - 1; // range 0 to (header.height - 1) + else + y = i; + + System.arraycopy(rawBuf, 0, tmpData, y * rawWidth, rawBuf.length); + } + + GL gl = GLContext.getCurrentGL(); + if (header.pixelDepth() == 24) { + bpp=3; + if(gl.isGL2GL3()) { + format = GL2GL3.GL_BGR; + } else { + format = GL.GL_RGB; + swapBGR(tmpData, rawWidth, header.height(), bpp); + } + } else { + assert header.pixelDepth() == 32; + bpp=4; + + if(gl.isGL2GL3()) { + format = GL2GL3.GL_BGRA; + } else { + format = GL.GL_RGBA; + swapBGR(tmpData, rawWidth, header.height(), bpp); + } + } + + data = ByteBuffer.wrap(tmpData); + } + + private static void swapBGR(byte[] data, int bWidth, int height, int bpp) { + byte r,b; + int k; + for(int i=0; i<height; ++i) { + for(int j=0; j<bWidth; j+=bpp) { + k=i*bWidth+j; + b=data[k+0]; + r=data[k+2]; + data[k+0]=r; + data[k+2]=b; + } + } + } + + /** Returns the width of the image. */ + public int getWidth() { return header.width(); } + + /** Returns the height of the image. */ + public int getHeight() { return header.height(); } + + /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ + public int getGLFormat() { return format; } + + /** Returns the bytes per pixel */ + public int getBytesPerPixel() { return bpp; } + + /** Returns the raw data for this texture in the correct + (bottom-to-top) order for calls to glTexImage2D. */ + public ByteBuffer getData() { return data; } + + /** Reads a Targa image from the specified file. */ + public static TGAImage read(String filename) throws IOException { + return read(new FileInputStream(filename)); + } + + /** Reads a Targa image from the specified InputStream. */ + public static TGAImage read(InputStream in) throws IOException { + LEDataInputStream dIn = new LEDataInputStream(new BufferedInputStream(in)); + + Header header = new Header(dIn); + TGAImage res = new TGAImage(header); + res.decodeImage(dIn); + return res; + } + + /** Writes the image in Targa format to the specified file name. */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** Writes the image in Targa format to the specified file. */ + public void write(File file) throws IOException { + LEDataOutputStream output = + new LEDataOutputStream(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); + header.write(output); + if (!data.isDirect()) { + output.write(data.array()); + } else { + for (int i = 0; i < data.limit(); i++) { + output.write(data.get(i)); + } + } + output.close(); + } + + /** Creates a TGAImage 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., BGR or + BGRA. */ + public static TGAImage createFromData(int width, + int height, + boolean hasAlpha, + boolean topToBottom, + ByteBuffer data) { + Header header = new Header(); + header.imageType = Header.UTRUECOLOR; + header.width = width; + header.height = height; + header.pixelDepth = (byte) (hasAlpha ? 32 : 24); + header.imageDescriptor = (byte) (topToBottom ? Header.ID_TOPTOBOTTOM : 0); + // Note ID not supported + TGAImage ret = new TGAImage(header); + ret.data = data; + return ret; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javase b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javase new file mode 100755 index 000000000..16ba538b5 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TGAImage.java.javase @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.texture.spi.*; +import com.jogamp.opengl.util.texture.*; + +/** + * Targa image reader and writer adapted from sources of the <a href = + * "http://java.sun.com/products/jimi/">Jimi</a> image I/O class library. + * + * <P> + * + * Image decoder for image data stored in TGA file format. + * Currently only the original TGA file format is supported. This is + * because the new TGA format has data at the end of the file, getting + * to the end of a file in an InputStream orient environment presents + * several difficulties which are avoided at the moment. + * + * <P> + * + * This is a simple decoder and is only setup to load a single image + * from the input stream + * + * <P> + * + * @author Robin Luiten + * @author Kenneth Russell + * @version $Revision: 1768 $ + */ + +public class TGAImage { + private Header header; + private int format; + private int bpp; + private ByteBuffer data; + + private TGAImage(Header header) { + this.header = header; + } + + /** + * This class reads in all of the TGA image header in addition it also + * reads in the imageID field as it is convenient to handle that here. + * + * @author Robin Luiten + * @version 1.1 + */ + public static class Header { + /** Set of possible file format TGA types */ + public final static int TYPE_NEW = 0; + public final static int TYPE_OLD = 1; + public final static int TYPE_UNK = 2; // cant rewind stream so unknown for now. + + /** Set of possible image types in TGA file */ + public final static int NO_IMAGE = 0; // no image data + public final static int UCOLORMAPPED = 1; // uncompressed color mapped image + public final static int UTRUECOLOR = 2; // uncompressed true color image + public final static int UBLACKWHITE = 3; // uncompressed black and white image + public final static int COLORMAPPED = 9; // compressed color mapped image + public final static int TRUECOLOR = 10; // compressed true color image + public final static int BLACKWHITE = 11; // compressed black and white image + + /** Field image descriptor bitfield values definitions */ + public final static int ID_ATTRIBPERPIXEL = 0xF; + public final static int ID_RIGHTTOLEFT = 0x10; + public final static int ID_TOPTOBOTTOM = 0x20; + public final static int ID_INTERLEAVE = 0xC0; + + /** Field image descriptor / interleave values */ + public final static int I_NOTINTERLEAVED = 0; + public final static int I_TWOWAY = 1; + public final static int I_FOURWAY = 2; + + /** Type of this TGA file format */ + private int tgaType; + + /** initial TGA image data fields */ + private int idLength; // byte value + private int colorMapType; // byte value + private int imageType; // byte value + + /** TGA image colour map fields */ + private int firstEntryIndex; + private int colorMapLength; + private byte colorMapEntrySize; + + /** TGA image specification fields */ + private int xOrigin; + private int yOrigin; + private int width; + private int height; + private byte pixelDepth; + private byte imageDescriptor; + + private byte[] imageIDbuf; + private String imageID; + + // For construction from user data + Header() { + tgaType = TYPE_OLD; // dont try and get footer. + } + + Header(LEDataInputStream in) throws IOException { + int ret; + + tgaType = TYPE_OLD; // dont try and get footer. + + // initial header fields + idLength = in.readUnsignedByte(); + colorMapType = in.readUnsignedByte(); + imageType = in.readUnsignedByte(); + + // color map header fields + firstEntryIndex = in.readUnsignedShort(); + colorMapLength = in.readUnsignedShort(); + colorMapEntrySize = in.readByte(); + + // TGA image specification fields + xOrigin = in.readUnsignedShort(); + yOrigin = in.readUnsignedShort(); + width = in.readUnsignedShort(); + height = in.readUnsignedShort(); + pixelDepth = in.readByte(); + imageDescriptor = in.readByte(); + + if (idLength > 0) { + imageIDbuf = new byte[idLength]; + in.read(imageIDbuf, 0, idLength); + imageID = new String(imageIDbuf, "US-ASCII"); + } + } + + public int tgaType() { return tgaType; } + + /** initial TGA image data fields */ + public int idLength() { return idLength; } + public int colorMapType() { return colorMapType; } + public int imageType() { return imageType; } + + /** TGA image colour map fields */ + public int firstEntryIndex() { return firstEntryIndex; } + public int colorMapLength() { return colorMapLength; } + public byte colorMapEntrySize() { return colorMapEntrySize; } + + /** TGA image specification fields */ + public int xOrigin() { return xOrigin; } + public int yOrigin() { return yOrigin; } + public int width() { return width; } + public int height() { return height; } + public byte pixelDepth() { return pixelDepth; } + public byte imageDescriptor() { return imageDescriptor; } + + /** bitfields in imageDescriptor */ + public byte attribPerPixel() { return (byte)(imageDescriptor & ID_ATTRIBPERPIXEL); } + public boolean rightToLeft() { return ((imageDescriptor & ID_RIGHTTOLEFT) != 0); } + public boolean topToBottom() { return ((imageDescriptor & ID_TOPTOBOTTOM) != 0); } + public byte interleave() { return (byte)((imageDescriptor & ID_INTERLEAVE) >> 6); } + + public byte[] imageIDbuf() { return imageIDbuf; } + public String imageID() { return imageID; } + + public String toString() { + return "TGA Header " + + " id length: " + idLength + + " color map type: "+ colorMapType + + " image type: "+ imageType + + " first entry index: " + firstEntryIndex + + " color map length: " + colorMapLength + + " color map entry size: " + colorMapEntrySize + + " x Origin: " + xOrigin + + " y Origin: " + yOrigin + + " width: "+ width + + " height: "+ height + + " pixel depth: "+ pixelDepth + + " image descriptor: "+ imageDescriptor + + (imageIDbuf == null ? "" : (" ID String: " + imageID)); + } + + public int size() { return 18 + idLength; } + + // buf must be in little-endian byte order + private void write(ByteBuffer buf) { + buf.put((byte) idLength); + buf.put((byte) colorMapType); + buf.put((byte) imageType); + buf.putShort((short) firstEntryIndex); + buf.putShort((short) colorMapLength); + buf.put((byte) colorMapEntrySize); + buf.putShort((short) xOrigin); + buf.putShort((short) yOrigin); + buf.putShort((short) width); + buf.putShort((short) height); + buf.put((byte) pixelDepth); + buf.put((byte) imageDescriptor); + if (idLength > 0) { + try { + byte[] chars = imageID.getBytes("US-ASCII"); + buf.put(chars); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + } + } + + + /** + * Identifies the image type of the tga image data and loads + * it into the JimiImage structure. This was taken from the + * prototype and modified for the new Jimi structure + */ + private void decodeImage(LEDataInputStream dIn) throws IOException { + switch (header.imageType()) { + case Header.UCOLORMAPPED: + throw new IOException("TGADecoder Uncompressed Colormapped images not supported"); + + case Header.UTRUECOLOR: // pixelDepth 15, 16, 24 and 32 + switch (header.pixelDepth) { + case 16: + throw new IOException("TGADecoder Compressed 16-bit True Color images not supported"); + + case 24: + case 32: + decodeRGBImageU24_32(dIn); + break; + } + break; + + case Header.UBLACKWHITE: + throw new IOException("TGADecoder Uncompressed Grayscale images not supported"); + + case Header.COLORMAPPED: + throw new IOException("TGADecoder Compressed Colormapped images not supported"); + + case Header.TRUECOLOR: + throw new IOException("TGADecoder Compressed True Color images not supported"); + + case Header.BLACKWHITE: + throw new IOException("TGADecoder Compressed Grayscale images not supported"); + } + } + + /** + * This assumes that the body is for a 24 bit or 32 bit for a + * RGB or ARGB image respectively. + */ + private void decodeRGBImageU24_32(LEDataInputStream dIn) throws IOException { + int i; // row index + int j; // column index + int y; // output row index + int raw; // index through the raw input buffer + int rawWidth = header.width() * (header.pixelDepth() / 8); + byte[] rawBuf = new byte[rawWidth]; + byte[] tmpData = new byte[rawWidth * header.height()]; + + for (i = 0; i < header.height(); ++i) { + dIn.readFully(rawBuf, 0, rawWidth); + + if (header.topToBottom()) + y = header.height - i - 1; // range 0 to (header.height - 1) + else + y = i; + + System.arraycopy(rawBuf, 0, tmpData, y * rawWidth, rawBuf.length); + } + + GL gl = GLContext.getCurrentGL(); + if (header.pixelDepth() == 24) { + bpp=3; + if(gl.isGL2GL3()) { + format = GL2GL3.GL_BGR; + } else { + format = GL.GL_RGB; + swapBGR(tmpData, rawWidth, header.height(), bpp); + } + } else { + assert header.pixelDepth() == 32; + bpp=4; + + if(gl.isGL2GL3()) { + format = GL2GL3.GL_BGRA; + } else { + format = GL.GL_RGBA; + swapBGR(tmpData, rawWidth, header.height(), bpp); + } + } + + data = ByteBuffer.wrap(tmpData); + } + + private static void swapBGR(byte[] data, int bWidth, int height, int bpp) { + byte r,b; + int k; + for(int i=0; i<height; ++i) { + for(int j=0; j<bWidth; j+=bpp) { + k=i*bWidth+j; + b=data[k+0]; + r=data[k+2]; + data[k+0]=r; + data[k+2]=b; + } + } + } + + /** Returns the width of the image. */ + public int getWidth() { return header.width(); } + + /** Returns the height of the image. */ + public int getHeight() { return header.height(); } + + /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ + public int getGLFormat() { return format; } + + /** Returns the bytes per pixel */ + public int getBytesPerPixel() { return bpp; } + + /** Returns the raw data for this texture in the correct + (bottom-to-top) order for calls to glTexImage2D. */ + public ByteBuffer getData() { return data; } + + /** Reads a Targa image from the specified file. */ + public static TGAImage read(String filename) throws IOException { + return read(new FileInputStream(filename)); + } + + /** Reads a Targa image from the specified InputStream. */ + public static TGAImage read(InputStream in) throws IOException { + LEDataInputStream dIn = new LEDataInputStream(new BufferedInputStream(in)); + + Header header = new Header(dIn); + TGAImage res = new TGAImage(header); + res.decodeImage(dIn); + return res; + } + + /** Writes the image in Targa format to the specified file name. */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** Writes the image in Targa format to the specified file. */ + public void write(File file) throws IOException { + FileOutputStream stream = new FileOutputStream(file); + FileChannel chan = stream.getChannel(); + ByteBuffer buf = ByteBuffer.allocate(header.size()); + buf.order(ByteOrder.LITTLE_ENDIAN); + header.write(buf); + buf.rewind(); + chan.write(buf); + chan.write(data); + data.rewind(); + chan.force(true); + chan.close(); + stream.close(); + } + + /** Creates a TGAImage 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., BGR or + BGRA. */ + public static TGAImage createFromData(int width, + int height, + boolean hasAlpha, + boolean topToBottom, + ByteBuffer data) { + Header header = new Header(); + header.imageType = Header.UTRUECOLOR; + header.width = width; + header.height = height; + header.pixelDepth = (byte) (hasAlpha ? 32 : 24); + header.imageDescriptor = (byte) (topToBottom ? Header.ID_TOPTOBOTTOM : 0); + // Note ID not supported + TGAImage ret = new TGAImage(header); + ret.data = data; + return ret; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java new file mode 100755 index 000000000..88018edbe --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureProvider.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; +import java.net.*; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.util.texture.*; + +/** Plug-in interface to TextureIO to support reading OpenGL textures + from new file formats. For all methods, either internalFormat or + pixelFormat may be 0 in which case they must be inferred as + e.g. RGB or RGBA depending on the file contents. +*/ + +public interface TextureProvider { + + /** + * Produces a TextureData object from a file, or returns null if the + * file format was not supported by this TextureProvider. Does not + * do any OpenGL-related work. The resulting TextureData can be + * converted into an OpenGL texture in a later step. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param file the file from which to read the texture data + * + * @param internalFormat the OpenGL internal format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param pixelFormat the OpenGL pixel format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * + * @param fileSuffix the file suffix to be used as a hint to the + * provider to more quickly decide whether it + * can handle the file, or null if the + * provider should infer the type from the + * file's contents + * + * @throws IOException if an error occurred while reading the file + */ + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException; + + /** + * Produces a TextureData object from a stream, or returns null if + * the file format was not supported by this TextureProvider. Does + * not do any OpenGL-related work. The resulting TextureData can be + * converted into an OpenGL texture in a later step. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param stream the stream from which to read the texture data + * + * @param internalFormat the OpenGL internal format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param pixelFormat the OpenGL pixel format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * + * @param fileSuffix the file suffix to be used as a hint to the + * provider to more quickly decide whether it + * can handle the file, or null if the + * provider should infer the type from the + * file's contents + * + * @throws IOException if an error occurred while reading the stream + */ + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException; + + /** + * Produces a TextureData object from a URL, or returns null if the + * file format was not supported by this TextureProvider. Does not + * do any OpenGL-related work. The resulting TextureData can be + * converted into an OpenGL texture in a later step. + * + * @param glp the OpenGL Profile this texture data should be + * created for. + * @param url the URL from which to read the texture data + * + * @param internalFormat the OpenGL internal format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param pixelFormat the OpenGL pixel format to be used for + * the texture, or 0 if it should be inferred + * from the file's contents + * + * @param mipmap whether mipmaps should be produced for this + * texture either by autogenerating them or + * reading them from the file. Some file formats + * support multiple mipmaps in a single file in + * which case those mipmaps will be used rather + * than generating them. + * + * @param fileSuffix the file suffix to be used as a hint to the + * provider to more quickly decide whether it + * can handle the file, or null if the + * provider should infer the type from the + * file's contents + * + * @throws IOException if an error occurred while reading the URL + */ + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException; +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java new file mode 100755 index 000000000..55527cef5 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/TextureWriter.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi; + +import java.io.*; + +import com.jogamp.opengl.util.texture.*; + +/** Plug-in interface to TextureIO to support writing OpenGL textures + to new file formats. */ + +public interface TextureWriter { + /** Writes the given TextureData to the passed file. Returns true if + this TextureWriter successfully handled the writing of the file, + otherwise false. May throw IOException if either this writer did + not support certain parameters of the TextureData or if an I/O + error occurred. */ + public boolean write(File file, + TextureData data) throws IOException; +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java new file mode 100644 index 000000000..a45821d87 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureProvider.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi.awt; + +import java.awt.Graphics; +import java.awt.image.*; +import java.io.*; +import java.net.*; +import javax.imageio.*; +import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.impl.Debug; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.awt.*; +import com.jogamp.opengl.util.texture.spi.*; + +public class IIOTextureProvider implements TextureProvider { + private static final boolean DEBUG = Debug.debug("TextureIO"); + + public TextureData newTextureData(GLProfile glp, File file, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + BufferedImage img = ImageIO.read(file); + if (img == null) { + return null; + } + if (DEBUG) { + System.out.println("TextureIO.newTextureData(): BufferedImage type for " + file + " = " + + img.getType()); + } + return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); + } + + public TextureData newTextureData(GLProfile glp, InputStream stream, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + BufferedImage img = ImageIO.read(stream); + if (img == null) { + return null; + } + if (DEBUG) { + System.out.println("TextureIO.newTextureData(): BufferedImage type for stream = " + + img.getType()); + } + return new AWTTextureData(glp, internalFormat, pixelFormat, mipmap, img); + } + + public TextureData newTextureData(GLProfile glp, URL url, + int internalFormat, + int pixelFormat, + boolean mipmap, + String fileSuffix) throws IOException { + InputStream stream = url.openStream(); + try { + return newTextureData(glp, stream, internalFormat, pixelFormat, mipmap, fileSuffix); + } finally { + stream.close(); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java new file mode 100644 index 000000000..405211204 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/awt/IIOTextureWriter.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.jogamp.opengl.util.texture.spi.awt; + +import java.awt.Graphics; +import java.awt.image.*; +import java.io.*; +import java.net.*; +import java.nio.*; +import javax.imageio.*; + +import javax.media.opengl.*; +import com.jogamp.opengl.util.*; +import com.jogamp.opengl.util.awt.*; +import com.jogamp.opengl.util.texture.*; +import com.jogamp.opengl.util.texture.spi.*; + +public class IIOTextureWriter implements TextureWriter { + public boolean write(File file, + TextureData data) throws IOException { + int pixelFormat = data.getPixelFormat(); + int pixelType = data.getPixelType(); + if ((pixelFormat == GL.GL_RGB || + pixelFormat == GL.GL_RGBA) && + (pixelType == GL.GL_BYTE || + pixelType == GL.GL_UNSIGNED_BYTE)) { + // Convert TextureData to appropriate BufferedImage + // FIXME: almost certainly not obeying correct pixel order + BufferedImage image = new BufferedImage(data.getWidth(), data.getHeight(), + (pixelFormat == GL.GL_RGB) ? + BufferedImage.TYPE_3BYTE_BGR : + BufferedImage.TYPE_4BYTE_ABGR); + byte[] imageData = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); + ByteBuffer buf = (ByteBuffer) data.getBuffer(); + if (buf == null) { + buf = (ByteBuffer) data.getMipmapData()[0]; + } + buf.rewind(); + buf.get(imageData); + buf.rewind(); + + // Swizzle image components to be correct + if (pixelFormat == GL.GL_RGB) { + for (int i = 0; i < imageData.length; i += 3) { + byte red = imageData[i + 0]; + byte blue = imageData[i + 2]; + imageData[i + 0] = blue; + imageData[i + 2] = red; + } + } else { + for (int i = 0; i < imageData.length; i += 4) { + byte red = imageData[i + 0]; + byte green = imageData[i + 1]; + byte blue = imageData[i + 2]; + byte alpha = imageData[i + 3]; + imageData[i + 0] = alpha; + imageData[i + 1] = blue; + imageData[i + 2] = green; + imageData[i + 3] = red; + } + } + + // Flip image vertically for the user's convenience + ImageUtil.flipImageVertically(image); + + // Happened to notice that writing RGBA images to JPEGS is broken + if (TextureIO.JPG.equals(FileUtil.getFileSuffix(file)) && + image.getType() == BufferedImage.TYPE_4BYTE_ABGR) { + BufferedImage tmpImage = new BufferedImage(image.getWidth(), image.getHeight(), + BufferedImage.TYPE_3BYTE_BGR); + Graphics g = tmpImage.getGraphics(); + g.drawImage(image, 0, 0, null); + g.dispose(); + image = tmpImage; + } + + return ImageIO.write(image, FileUtil.getFileSuffix(file), file); + } + + throw new IOException("ImageIO writer doesn't support this pixel format / type (only GL_RGB/A + bytes)"); + } +} diff --git a/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java b/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java new file mode 100644 index 000000000..08cfeccde --- /dev/null +++ b/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java @@ -0,0 +1,14 @@ + +package com.jogamp.openmax; + +public interface OMXEventListener { + + static final int EVENT_CHANGE_SIZE = 1<<0; + static final int EVENT_CHANGE_FPS = 1<<1; + static final int EVENT_CHANGE_BPS = 1<<2; + static final int EVENT_CHANGE_LENGTH = 1<<3; + + public void changedAttributes(OMXInstance omx, int event_mask); + +} + diff --git a/src/jogl/classes/com/jogamp/openmax/OMXInstance.java b/src/jogl/classes/com/jogamp/openmax/OMXInstance.java new file mode 100644 index 000000000..9f5b850ba --- /dev/null +++ b/src/jogl/classes/com/jogamp/openmax/OMXInstance.java @@ -0,0 +1,509 @@ + +package com.jogamp.openmax; + +import javax.media.opengl.*; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.util.texture.*; + +import com.jogamp.opengl.impl.egl.EGL; +import com.jogamp.opengl.impl.egl.EGLContext; +import com.jogamp.opengl.impl.egl.EGLDrawable; +import com.jogamp.opengl.impl.egl.EGLExt; + +import java.net.URL; +import java.nio.ByteBuffer; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + +public class OMXInstance { + private long moviePtr = 0; + + protected String path = null; + protected URL url = null; + + // *** Texture impl + protected Texture texture = null; // holds the last fetched texture + + protected float playSpeed = 1.0f; + + /** + * The following data is set by the setStream function, + * and may be set by the native OMX implementation, + * in case the stream attributes changes (see attributesUpdated) + */ + protected int width = 0; + protected int height = 0; + protected int fps = 0; // frames per seconds + protected long bps = 0; // bits per seconds + protected long totalFrames = 0; // duration in frames + protected String acodec = null; + protected String vcodec = null; + + /** + * Old stream values, before the last attributesUpdated) + */ + protected int o_width = 0; + protected int o_height = 0; + protected int o_fps = 0; // frames per seconds + protected long o_bps = 0; // bits per seconds + protected long o_totalFrames = 0; // duration in frames + + static class EGLImageTexture { + public EGLImageTexture(com.jogamp.opengl.util.texture.Texture t, long i, long s) { + texture = t; image = i; sync = s; + } + public String toString() { + return "EGLImageTexture[" + texture + ", image " + image + ", sync "+sync+"]"; + } + protected com.jogamp.opengl.util.texture.Texture texture; + protected long image; + protected long sync; + } + private EGLImageTexture[] eglImgTexs=null; + private HashMap eglImgTexsMap = new HashMap(); + protected int textureNum; + + private EGLExt eglExt = null; + private long eglSurface = 0; + private long eglDisplay = 0; + private long eglContext = 0; + private int sWidth=0, sHeight=0; + + private GL initGLData(GL gl) { + if(null==gl) { + throw new RuntimeException("No current GL"); + } + EGLContext eglCtx = (EGLContext) gl.getContext(); + if(null==eglCtx) { + throw new RuntimeException("No current EGL context"); + } + EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); + if(null==eglDrawable) { + throw new RuntimeException("No valid drawable"); + } + eglContext = eglCtx.getContext(); + eglDisplay = eglDrawable.getDisplay(); + eglSurface = eglDrawable.getSurface(); + eglExt = eglCtx.getEGLExt(); + if(null==eglExt) { + throw new RuntimeException("No valid EGLExt"); + } + + int iTmp[] = new int[1]; + EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, iTmp, 0); + sWidth=iTmp[0]; + EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, iTmp, 0); + sHeight=iTmp[0]; + System.out.println("surface size: "+width+"x"+height); + System.out.println(eglDrawable); + System.out.println(eglCtx); + System.out.println("EGL Extensions : "+EGL.eglQueryString(eglDisplay, EGL.EGL_EXTENSIONS)); + System.out.println("EGL CLIENT APIs: "+EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS)); + return gl; + } + + public OMXInstance() { + moviePtr = _createInstance(); + if(0==moviePtr) { + throw new GLException("Couldn't create OMXInstance"); + } + } + native long _createInstance(); + + public synchronized void setStream(int textureNum, URL u) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + this.textureNum=textureNum; + url = u; + if (url == null) { + System.out.println("setURL (null)"); + stop(); + return; + } + path=null; + if (url.getProtocol() == null || "file".equals(url.getProtocol())) { + // CV only accepts absolute paths + try { + File file = new File(url.getPath()); + if (!file.exists()) { + throw new RuntimeException(new FileNotFoundException(file.toString())); + } + path = file.getCanonicalPath(); + System.out.println("setURL: path "+path); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + path = replaceAll(path, "\\", "/").trim(); + if(null==path) { + throw new RuntimeException("Couldn't parse stream URL: "+url); + } + System.out.println("setURL: clean path "+path); + + System.out.println("setURL: p1 "+this); + _setStream(moviePtr, textureNum, path); + System.out.println("setURL: p2 "+this); + } + native void _setStream(long moviePtr, int textureNum, String path); + + public synchronized void setStreamAllEGLImageTexture2D(GL gl) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + if(null==vcodec) { + return; + } + gl = initGLData(gl); + + if(null!=eglImgTexs) { + removeAllEGLImageTexture2D(gl); + } else { + eglImgTexs = new EGLImageTexture[textureNum]; + } + + int[] tmp = new int[1]; + int tex, e; + + errorCheckGL(gl, "i.1"); + gl.glEnable(gl.GL_TEXTURE_2D); + errorCheckGL(gl, "i.2"); + + for(int i=0; i<textureNum; i++) { + String s0 = String.valueOf(i); + gl.glGenTextures(1, tmp, 0); + tex=tmp[0]; + if( (e=gl.glGetError()) != GL.GL_NO_ERROR || 0>tex ) { + throw new RuntimeException("TextureName creation failed: "+e); + } + gl.glBindTexture(gl.GL_TEXTURE_2D, tex); + + // create space for buffer with a texture + gl.glTexImage2D( + gl.GL_TEXTURE_2D, // target + 0, // level + gl.GL_RGBA, // internal format + width, // width + height, // height + 0, // border + gl.GL_RGBA, // format + gl.GL_UNSIGNED_BYTE, // type + null); // pixels -- will be provided later + gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); + gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); + + long image=0, sync=0; + + // create EGLImage from texture + tmp[0] = EGL.EGL_NONE; + image = eglExt.eglCreateImageKHR( + eglDisplay, + eglContext, + eglExt.EGL_GL_TEXTURE_2D_KHR, + tex, + tmp, 0); + if (0==image) { + throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", dpy "+eglDisplay+", ctx "+eglContext+", tex "+tex); + } + + // Create sync object so that we can be sure that gl has finished + // rendering the EGLImage texture before we tell OpenMAX to fill + // it with a new frame. + tmp[0] = EGL.EGL_NONE; + sync = eglExt.eglCreateFenceSyncKHR( + eglDisplay, + eglExt.EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR, tmp, 0); + + _setStreamEGLImageTexture2D(moviePtr, i, tex, image, sync); + + eglImgTexs[i] = new EGLImageTexture( + com.jogamp.opengl.util.texture.TextureIO.newTexture(tex, + javax.media.opengl.GL2.GL_TEXTURE_2D, + width, + height, + width, + height, + true), + image, sync); + eglImgTexsMap.put(new Integer(tex), eglImgTexs[i]); + } + gl.glDisable(gl.GL_TEXTURE_2D); + } + native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync); + + public synchronized void activateStream() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _activateStream(moviePtr); + } + native void _activateStream(long moviePtr); + + public synchronized void detachVideoRenderer() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _detachVideoRenderer(moviePtr); + } + native void _detachVideoRenderer(long moviePtr); // stop before + + public synchronized void attachVideoRenderer() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _attachVideoRenderer(moviePtr); + } + native void _attachVideoRenderer(long moviePtr); // detach before + + public synchronized void setPlaySpeed(float rate) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _setPlaySpeed(moviePtr, rate); + playSpeed = rate; + } + public synchronized float getPlaySpeed() { + return playSpeed; + } + native void _setPlaySpeed(long moviePtr, float rate); + + /** @return time position after issuing the command */ + public synchronized float play() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _play(moviePtr); + } + native float _play(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float pause() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _pause(moviePtr); + } + native float _pause(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float stop() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _stop(moviePtr); + } + native float _stop(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float seek(float pos) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _seek(moviePtr, pos); + } + native float _seek(long moviePtr, float position); + + public synchronized Texture getLastTextureID() { + return texture; + } + public synchronized Texture getNextTextureID() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + texture=null; + EGLImageTexture eglImgTex = (EGLImageTexture) eglImgTexsMap.get(new Integer(_getNextTextureID(moviePtr))); + if(null!=eglImgTex) { + texture = eglImgTex.texture; + } + return texture; + } + native int _getNextTextureID(long moviePtr); + + public synchronized float getCurrentPosition() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _getCurrentPosition(moviePtr); + } + native float _getCurrentPosition(long moviePtr); + + public synchronized void destroy(GL gl) { + removeAllEGLImageTexture2D(gl); + if (moviePtr != 0) { + long ptr = moviePtr; + moviePtr = 0; + _destroyInstance(ptr); + + eglExt=null; + eglSurface=0; + eglDisplay=0; + eglContext=0; + } + } + protected synchronized void finalize() { + if (moviePtr != 0) { + destroy(null); + } + } + native void _destroyInstance(long moviePtr); + + public synchronized boolean isValid() { + return (moviePtr != 0); + } + public synchronized String getPath() { + return path; + } + public synchronized URL getURL() { + return url; + } + public synchronized String getVideoCodec() { + return vcodec; + } + public synchronized String getAudioCodec() { + return acodec; + } + public synchronized long getTotalFrames() { + return totalFrames; + } + public synchronized long getBitrate() { + return bps; + } + public synchronized int getFramerate() { + return fps; + } + public synchronized int getWidth() { + return width; + } + public synchronized int getHeight() { + return height; + } + public synchronized String toString() { + return "OMXInstance [ stream [ video [ "+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp, "+totalFrames+"f ] ] ]"; + } + + /** + * Java callback method issued by the native OMX backend + */ + private void saveAttributes() { + o_width = width; + o_height = height; + o_fps = fps; + o_bps = bps; + o_totalFrames = totalFrames; + } + + private void attributesUpdated() { + int event_mask = 0; + if( o_width != width || o_height != height ) { + event_mask |= OMXEventListener.EVENT_CHANGE_SIZE; + } + if( o_fps != fps ) { + event_mask |= OMXEventListener.EVENT_CHANGE_FPS; + } + if( o_bps != bps ) { + event_mask |= OMXEventListener.EVENT_CHANGE_BPS; + } + if( o_totalFrames != totalFrames ) { + event_mask |= OMXEventListener.EVENT_CHANGE_LENGTH; + } + if(0==event_mask) { + return; + } + + ArrayList listeners = null; + synchronized(this) { + listeners = eventListeners; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + OMXEventListener l = (OMXEventListener) i.next(); + l.changedAttributes(this, event_mask); + } + } + + private String replaceAll(String orig, String search, String repl) { + String dest=null; + // In case replaceAll / java.util.regex.* is not supported (-> CVM) + int i=0,j; + dest = new String(); + while((j=orig.indexOf(search, i))>=0) { + dest=dest.concat(orig.substring(i, j)); + dest=dest.concat(repl); + i=j+1; + } + return dest.concat(orig.substring(i, orig.length())); + } + + private void removeAllEGLImageTexture2D(GL gl) { + if (moviePtr != 0) { + if(null==eglExt) { + throw new RuntimeException("No valid EGLExt"); + } + + texture = null; + for(int i=0; i<textureNum; i++) { + if(null!=eglImgTexs[i]) { + if(0!=eglImgTexs[i].image) { + eglExt.eglDestroyImageKHR( + eglDisplay, + eglImgTexs[i].image); + } + if(0!=eglImgTexs[i].sync) { + eglExt.eglDestroySyncKHR(eglImgTexs[i].sync); + } + if(null!=gl) { + eglImgTexs[i].texture.destroy(gl); + } + eglImgTexs[i]=null; + } + } + eglImgTexsMap.clear(); + } + } + + private void errorCheckGL(GL gl, String s) { + int e; + if( (e=gl.glGetError()) != GL.GL_NO_ERROR ) { + System.out.println("GL Error: ("+s+"): "+e); + } + } + + private void errorCheckEGL(String s) { + int e; + if( (e=EGL.eglGetError()) != EGL.EGL_SUCCESS ) { + System.out.println("EGL Error: ("+s+"): "+e); + } + } + + + // + // OMXEventListener Support + // + + public synchronized void addEventListener(OMXEventListener l) { + if(l == null) { + return; + } + ArrayList newEventListeners = (ArrayList) eventListeners.clone(); + newEventListeners.add(l); + eventListeners = newEventListeners; + } + + public synchronized void removeEventListener(OMXEventListener l) { + if (l == null) { + return; + } + ArrayList newEventListeners = (ArrayList) eventListeners.clone(); + newEventListeners.remove(l); + eventListeners = newEventListeners; + } + + public synchronized OMXEventListener[] getEventListeners() { + return (OMXEventListener[]) eventListeners.toArray(); + } + + private ArrayList eventListeners = new ArrayList(); + +} + |