--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+ <classpathentry combineaccessrules="false" kind="src" path="/dependencies"/>\r
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/gdx"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/angle.jar"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/javazoom-spi.jar"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/jl1.0.1.jar"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/jorbis.jar"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/tritonus-utils.jar"/>\r
+ <classpathentry exported="true" kind="lib" path="/dependencies/gdx-natives.jar"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>gdx-backend-angle</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import com.badlogic.anglejni.ESLoop;\r
+import com.badlogic.anglejni.ESUtil;\r
+import com.badlogic.gdx.Application;\r
+import com.badlogic.gdx.ApplicationListener;\r
+import com.badlogic.gdx.Audio;\r
+import com.badlogic.gdx.Files;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.Graphics;\r
+import com.badlogic.gdx.Input;\r
+import com.badlogic.gdx.Version;\r
+\r
+public class AngleApplication implements Application, ESLoop {\r
+ AngleGraphics graphics;\r
+ AngleAudio audio;\r
+ AngleInput input;\r
+ AngleFiles files;\r
+ ESUtil utils;\r
+ ApplicationListener listener;\r
+ boolean created = false;\r
+ \r
+ public AngleApplication(final ApplicationListener listener,final String title,final int width,final int height,final boolean fullscreen) {\r
+ new Thread(new Runnable() {\r
+ public void run() { \r
+ Version.loadLibrary();\r
+ \r
+ AngleApplication.this.listener = listener;\r
+ utils = new ESUtil(title, width, height, ESUtil.ES_WINDOW_DEPTH | (fullscreen?ESUtil.ES_WINDOW_FULLSCREEN:0));\r
+ graphics = new AngleGraphics(width, height);\r
+ audio = new AngleAudio();\r
+ input = new AngleInput();\r
+ files = new AngleFiles();\r
+ \r
+ Gdx.app = AngleApplication.this;\r
+ Gdx.graphics = graphics;\r
+ Gdx.audio = audio;\r
+ Gdx.input = input;\r
+ Gdx.files = files;\r
+ Gdx.gl = graphics.getGL20();\r
+ Gdx.gl20 = graphics.getGL20(); \r
+ utils.run(AngleApplication.this);\r
+ }\r
+ }).run();\r
+ }\r
+ \r
+ @Override\r
+ public Graphics getGraphics() {\r
+ return graphics;\r
+ }\r
+\r
+ @Override\r
+ public Audio getAudio() {\r
+ return audio;\r
+ }\r
+\r
+ @Override\r
+ public Input getInput() {\r
+ return input;\r
+ }\r
+\r
+ @Override\r
+ public Files getFiles() {\r
+ return files;\r
+ }\r
+\r
+ @Override\r
+ public void log(String tag, String message) {\r
+ System.out.println(tag + ": " + message); \r
+ }\r
+\r
+ @Override\r
+ public ApplicationType getType() {\r
+ return ApplicationType.Desktop;\r
+ }\r
+\r
+ @Override\r
+ public int getVersion() {\r
+ return 0;\r
+ }\r
+\r
+ @Override\r
+ public long getJavaHeap() {\r
+ return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();\r
+ }\r
+\r
+ @Override\r
+ public long getNativeHeap() {\r
+ return getJavaHeap();\r
+ }\r
+\r
+\r
+ @Override\r
+ public void onKey(int action, int key, int keyCode) {\r
+ input.registerKeyEvent(action, key, keyCode);\r
+ }\r
+\r
+\r
+ @Override\r
+ public void onMouse(int action, int x, int y, int button) {\r
+ if(action != ES_MOUSE_WHEEL)\r
+ input.registerMouseEvent(action, x, y, button);\r
+ }\r
+\r
+\r
+ @Override\r
+ public void quit() {\r
+ listener.pause();\r
+ listener.dispose();\r
+ }\r
+\r
+\r
+ @Override\r
+ public void render() {\r
+ if(!created) {\r
+ listener.create();\r
+ listener.resume();\r
+ created = true;\r
+ }\r
+ input.processEvents();\r
+ listener.render(); \r
+ }\r
+\r
+\r
+ @Override\r
+ public void resize(int width, int height) {\r
+ graphics.width = width;\r
+ graphics.height = height;\r
+ if(!created)\r
+ listener.resize(width, height);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+\r
+import javax.sound.sampled.AudioFormat;\r
+import javax.sound.sampled.AudioSystem;\r
+import javax.sound.sampled.SourceDataLine;\r
+\r
+import com.badlogic.gdx.Audio;\r
+import com.badlogic.gdx.audio.AudioDevice;\r
+import com.badlogic.gdx.audio.AudioRecorder;\r
+import com.badlogic.gdx.audio.Music;\r
+import com.badlogic.gdx.audio.Sound;\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+/**\r
+ * An implementation of the {@link Audio} interface for the desktop.\r
+ * \r
+ * @author mzechner\r
+ * \r
+ */\r
+final class AngleAudio implements Audio, Runnable {\r
+ /** the audio line for sound effects **/\r
+ private SourceDataLine line;\r
+\r
+ /** The current buffers to play **/\r
+ private final List<AngleSoundBuffer> buffers = new ArrayList<AngleSoundBuffer>();\r
+\r
+ /** The sound effects thread **/\r
+ private Thread thread;\r
+ \r
+ private volatile boolean run = false;\r
+\r
+ /**\r
+ * Helper class for playing back sound effects concurrently.\r
+ * \r
+ * @author mzechner\r
+ * \r
+ */\r
+ class AngleSoundBuffer {\r
+ private final float[] samples;\r
+ private final AudioFormat format;\r
+ private final float volume;\r
+ private int writtenSamples = 0;\r
+\r
+ public AngleSoundBuffer (AngleSound sound, float volume) throws Exception {\r
+ samples = sound.getAudioData();\r
+ format = sound.getAudioFormat();\r
+ this.volume = volume;\r
+ }\r
+\r
+ /**\r
+ * Writes the next numFrames frames to the line for playback\r
+ * @return whether playback is done or not.\r
+ */\r
+ public boolean writeSamples (int numSamples, float[] buffer) {\r
+ if (format.getChannels() == 1) {\r
+ int remainingSamples = Math.min(samples.length, writtenSamples + numSamples / 2);\r
+ for (int i = writtenSamples, j = 0; i < remainingSamples; i++, j += 2) {\r
+ buffer[j] += samples[i] * volume;\r
+ buffer[j + 1] += samples[i] * volume;\r
+ writtenSamples++;\r
+ }\r
+ } else {\r
+ int remainingSamples = Math.min(samples.length, writtenSamples + numSamples);\r
+ for (int i = writtenSamples, j = 0; i < remainingSamples; i += 2, j += 2) {\r
+ buffer[j] += samples[i] * volume;\r
+ buffer[j + 1] += samples[i + 1] * volume;\r
+ writtenSamples += 2;\r
+ }\r
+ }\r
+\r
+ if (writtenSamples >= samples.length)\r
+ return false;\r
+ else\r
+ return true;\r
+ }\r
+ }\r
+\r
+ AngleAudio () {\r
+ try {\r
+ AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);\r
+ line = AudioSystem.getSourceDataLine(format);\r
+ line.open(format, 4410);\r
+ line.start();\r
+ thread = new Thread(this, "LWJGL Audio");\r
+ thread.setDaemon(true);\r
+ thread.start();\r
+ } catch (Exception e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public AudioDevice newAudioDevice (boolean isMono) {\r
+ return new AngleAudioDevice(isMono);\r
+ }\r
+\r
+ public Music newMusic (FileHandle file) {\r
+ try {\r
+ AngleMusic music = new AngleMusic(((AngleFileHandle)file));\r
+ return music;\r
+ } catch (Throwable e) {\r
+ throw new GdxRuntimeException("Couldn't create Music instance from file '" + file + "'", e);\r
+ }\r
+ }\r
+\r
+ public Sound newSound (FileHandle file) {\r
+ try {\r
+ AngleSound sound = new AngleSound(this, ((AngleFileHandle)file));\r
+ return sound;\r
+ } catch (Exception e) {\r
+ throw new GdxRuntimeException("Couldn't create Sound instance from file '" + file + "'", e);\r
+ }\r
+ }\r
+\r
+ protected void enqueueSound (AngleSound sound, float volume) {\r
+ try {\r
+ synchronized (this) {\r
+ buffers.add(new AngleSoundBuffer(sound, volume));\r
+ }\r
+ } catch (Exception ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+\r
+ public void run () {\r
+\r
+ int NUM_SAMPLES = 44100 * 2;\r
+ float[] buffer = new float[NUM_SAMPLES];\r
+ byte[] bytes = new byte[2 * NUM_SAMPLES];\r
+\r
+ run = true;\r
+ \r
+ while (run) {\r
+ int samplesToWrite = line.available() / 2;\r
+\r
+ if (samplesToWrite > 0) {\r
+ fillBuffer(buffer, bytes, samplesToWrite);\r
+ int writtenBytes = line.write(bytes, 0, samplesToWrite * 2);\r
+ while (writtenBytes != samplesToWrite * 2)\r
+ writtenBytes += line.write(bytes, writtenBytes, samplesToWrite - writtenBytes);\r
+ }\r
+\r
+ try {\r
+ Thread.sleep(5);\r
+ } catch (InterruptedException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+\r
+ private void fillBuffer (float[] buffer, byte[] bytes, int samplesToWrite) {\r
+ for (int i = 0; i < buffer.length; i++)\r
+ buffer[i] = 0.0f;\r
+ for (int i = 0; i < bytes.length; i++)\r
+ bytes[i] = 0;\r
+\r
+ int numBuffers = buffers.size();\r
+ synchronized (this) {\r
+ Iterator<AngleSoundBuffer> bufferIter = buffers.iterator();\r
+ while (bufferIter.hasNext()) {\r
+ AngleSoundBuffer soundBuffer = bufferIter.next();\r
+ if (!soundBuffer.writeSamples(samplesToWrite, buffer)) bufferIter.remove();\r
+ }\r
+ }\r
+ if (numBuffers > 0) {\r
+ for (int i = 0, j = 0; i < samplesToWrite; i++, j += 2) {\r
+ float fValue = buffer[i];\r
+ if (fValue > 1) fValue = 1;\r
+ if (fValue < -1) fValue = -1;\r
+ short value = (short)(fValue * Short.MAX_VALUE);\r
+ bytes[j] = (byte)(value | 0xff);\r
+ bytes[j + 1] = (byte)(value >> 8);\r
+ }\r
+ }\r
+ }\r
+\r
+ public AudioRecorder newAudioRecoder (int samplingRate, boolean isMono) {\r
+ return new AngleAudioRecorder(samplingRate, isMono);\r
+ }\r
+ \r
+ void dispose ( ) {\r
+ run = false;\r
+ try {\r
+ if(thread != null)\r
+ thread.join();\r
+ if(line != null)\r
+ line.close();\r
+ } catch (InterruptedException e) {\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import javax.sound.sampled.AudioFormat;\r
+import javax.sound.sampled.AudioSystem;\r
+import javax.sound.sampled.SourceDataLine;\r
+\r
+import com.badlogic.gdx.audio.AudioDevice;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+/**\r
+ * Implementation of the {@link AudioDevice} interface for the desktop using Java Sound.\r
+ * \r
+ * @author mzechner\r
+ * \r
+ */\r
+final class AngleAudioDevice implements AudioDevice {\r
+ /** the audio line **/\r
+ private SourceDataLine line;\r
+\r
+ /** whether this device is mono **/\r
+ private final boolean isMono;\r
+\r
+ /** byte buffer **/\r
+ private byte[] bytes = new byte[44100 * 2 * 2];\r
+\r
+ public AngleAudioDevice (boolean isMono) {\r
+ this.isMono = isMono;\r
+\r
+ try {\r
+ AudioFormat format = new AudioFormat(44100.0f, 16, isMono ? 1 : 2, true, false);\r
+ line = AudioSystem.getSourceDataLine(format);\r
+ line.open(format, 4410 * 2);\r
+ line.start();\r
+ } catch (Exception e) {\r
+ throw new GdxRuntimeException("Couldn't createa AudioDevice", e);\r
+ }\r
+ }\r
+\r
+ public void dispose () {\r
+ line.drain();\r
+ line.close();\r
+ }\r
+\r
+ public boolean isMono () {\r
+ return isMono;\r
+ }\r
+\r
+ public void writeSamples (short[] samples, int offset, int numSamples) {\r
+ if (bytes.length < samples.length * 2) bytes = new byte[samples.length * 2];\r
+\r
+ for (int i = offset, j = 0; i < offset + numSamples; i++, j += 2) {\r
+ short value = samples[i];\r
+ bytes[j + 1] = (byte)(value & 0xff);\r
+ bytes[j] = (byte)(value >> 8);\r
+ }\r
+\r
+ int writtenBytes = line.write(bytes, 0, numSamples * 2);\r
+ while (writtenBytes != numSamples * 2)\r
+ writtenBytes += line.write(bytes, writtenBytes, numSamples * 2 - writtenBytes);\r
+ }\r
+\r
+ public void writeSamples (float[] samples, int offset, int numSamples) {\r
+ if (bytes.length < samples.length * 2) bytes = new byte[samples.length * 2];\r
+\r
+ for (int i = offset, j = 0; i < offset + numSamples; i++, j += 2) {\r
+ float fValue = samples[i];\r
+ if (fValue > 1) fValue = 1;\r
+ if (fValue < -1) fValue = -1;\r
+ short value = (short)(fValue * Short.MAX_VALUE);\r
+ bytes[j] = (byte)(value | 0xff);\r
+ bytes[j + 1] = (byte)(value >> 8);\r
+ }\r
+\r
+ int writtenBytes = line.write(bytes, 0, numSamples * 2);\r
+ while (writtenBytes != numSamples * 2)\r
+ writtenBytes += line.write(bytes, writtenBytes, numSamples * 2 - writtenBytes);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import javax.sound.sampled.AudioFormat;\r
+import javax.sound.sampled.AudioFormat.Encoding;\r
+import javax.sound.sampled.AudioSystem;\r
+import javax.sound.sampled.TargetDataLine;\r
+\r
+import com.badlogic.gdx.audio.AudioRecorder;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+/**\r
+ * {@link AudioRecorder} implementation for the desktop using the java sound API.\r
+ * \r
+ * @author badlogicgames@gmail.com\r
+ * \r
+ */\r
+final class AngleAudioRecorder implements AudioRecorder {\r
+ /** the line we read the audio from **/\r
+ private TargetDataLine line;\r
+\r
+ /** the buffer to temporarily store the samples **/\r
+ private byte[] buffer = new byte[1024 * 4];\r
+\r
+ public AngleAudioRecorder (int samplingRate, boolean isMono) {\r
+ try {\r
+ AudioFormat format = new AudioFormat(Encoding.PCM_SIGNED, samplingRate, 16, isMono ? 1 : 2, isMono ? 2 : 4,\r
+ samplingRate, false);\r
+ line = AudioSystem.getTargetDataLine(format);\r
+ line.open(format, buffer.length);\r
+ line.start();\r
+ } catch (Exception ex) {\r
+ throw new GdxRuntimeException("Couldn't create AudioRecorder", ex);\r
+ }\r
+ }\r
+\r
+ public void read (short[] samples, int offset, int numSamples) {\r
+ if (buffer.length < numSamples * 2) buffer = new byte[numSamples * 2];\r
+\r
+ int toRead = numSamples * 2;\r
+ int read = 0;\r
+\r
+ while (read != toRead)\r
+ read += line.read(buffer, read, toRead - read);\r
+\r
+ for (int i = 0, j = 0; i < numSamples * 2; i += 2, j++) {\r
+ samples[offset + j] = (short)((buffer[i] << 8) | (buffer[i + 1] & 0xff));\r
+ }\r
+ }\r
+\r
+ public void dispose () {\r
+ line.close();\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.io.File;\r
+\r
+import com.badlogic.gdx.Files.FileType;\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.files.FileHandle;\r
+\r
+/**\r
+ * @author mzechner\r
+ * @author Nathan Sweet <misc@n4te.com>\r
+ */\r
+final class AngleFileHandle extends FileHandle {\r
+ AngleFileHandle (String fileName, FileType type) {\r
+ super(fileName, type);\r
+ }\r
+\r
+ AngleFileHandle (File file, FileType type) {\r
+ super(file, type);\r
+ }\r
+\r
+ public FileHandle child (String name) {\r
+ return new AngleFileHandle(new File(file, name), type);\r
+ }\r
+\r
+ public FileHandle parent () {\r
+ File parent = file.getParentFile();\r
+ if (parent == null) {\r
+ switch (type) {\r
+ case Classpath:\r
+ case Absolute:\r
+ parent = new File("/");\r
+ break;\r
+ case Internal:\r
+ parent = new File("");\r
+ break;\r
+ case External:\r
+ parent = new File(Gdx.files.getExternalStoragePath());\r
+ break;\r
+ }\r
+ }\r
+ return new AngleFileHandle(parent, type);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import com.badlogic.gdx.Files;\r
+import com.badlogic.gdx.files.FileHandle;\r
+\r
+public class AngleFiles implements Files {\r
+ private final String externalPath = System.getProperty("user.home") + "/";\r
+\r
+ @Override public FileHandle getFileHandle (String fileName, FileType type) {\r
+ return new AngleFileHandle(fileName, type);\r
+ }\r
+\r
+ @Override public FileHandle classpath (String path) {\r
+ return new AngleFileHandle(path, FileType.Classpath);\r
+ }\r
+\r
+ @Override public FileHandle internal (String path) {\r
+ return new AngleFileHandle(path, FileType.Internal);\r
+ }\r
+\r
+ @Override public FileHandle external (String path) {\r
+ return new AngleFileHandle(path, FileType.External);\r
+ }\r
+\r
+ @Override public FileHandle absolute (String path) {\r
+ return new AngleFileHandle(path, FileType.Absolute);\r
+ }\r
+\r
+ @Override public String getExternalStoragePath () {\r
+ return externalPath;\r
+ }\r
+\r
+ @Override public boolean isExternalStorageAvailable () {\r
+ return true;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.nio.Buffer;\r
+import java.nio.FloatBuffer;\r
+import java.nio.IntBuffer;\r
+\r
+import com.badlogic.gdx.graphics.GL20;\r
+\r
+public class AngleGLES0 implements GL20\r
+{\r
+ static\r
+ { \r
+ init( );\r
+ } \r
+ \r
+ private static native void init( ); \r
+ \r
+ public native void glActiveTexture ( int texture );\r
+\r
+ public native void glAttachShader ( int program, int shader );\r
+\r
+ public native void glBindAttribLocation ( int program, int index, String name );\r
+\r
+ public native void glBindBuffer ( int target, int buffer );\r
+\r
+ public native void glBindFramebuffer ( int target, int framebuffer );\r
+\r
+ public native void glBindRenderbuffer ( int target, int renderbuffer );\r
+\r
+ public native void glBindTexture ( int target, int texture );\r
+\r
+ public native void glBlendColor ( float red, float green, float blue, float alpha );\r
+\r
+ public native void glBlendEquation ( int mode );\r
+\r
+ public native void glBlendEquationSeparate ( int modeRGB, int modeAlpha );\r
+\r
+ public native void glBlendFunc ( int sfactor, int dfactor );\r
+\r
+ public native void glBlendFuncSeparate ( int srcRGB, int dstRGB, int srcAlpha, int dstAlpha );\r
+\r
+ public native void glBufferData ( int target, int size, Buffer data, int usage );\r
+\r
+ public native void glBufferSubData ( int target, int offset, int size, Buffer data );\r
+\r
+ public native int glCheckFramebufferStatus ( int target );\r
+\r
+ public native void glClear ( int mask );\r
+\r
+ public native void glClearColor ( float red, float green, float blue, float alpha );\r
+\r
+ public native void glClearDepthf ( float depth );\r
+\r
+ public native void glClearStencil ( int s );\r
+\r
+ public native void glColorMask ( boolean red, boolean green, boolean blue, boolean alpha );\r
+\r
+ public native void glCompileShader ( int shader );\r
+\r
+ public native void glCompressedTexImage2D ( int target, int level, int internalformat, int width, int height, int border, int imageSize, Buffer data );\r
+\r
+ public native void glCompressedTexSubImage2D ( int target, int level, int xoffset, int yoffset, int width, int height, int format, int imageSize, Buffer data );\r
+\r
+ public native void glCopyTexImage2D ( int target, int level, int internalformat, int x, int y, int width, int height, int border );\r
+\r
+ public native void glCopyTexSubImage2D ( int target, int level, int xoffset, int yoffset, int x, int y, int width, int height );\r
+\r
+ public native int glCreateProgram ( );\r
+\r
+ public native int glCreateShader ( int type );\r
+\r
+ public native void glCullFace ( int mode );\r
+\r
+ public native void glDeleteBuffers ( int n, IntBuffer buffers );\r
+\r
+ public native void glDeleteFramebuffers ( int n, IntBuffer framebuffers );\r
+\r
+ public native void glDeleteProgram ( int program );\r
+\r
+ public native void glDeleteRenderbuffers ( int n, IntBuffer renderbuffers );\r
+\r
+ public native void glDeleteShader ( int shader );\r
+\r
+ public native void glDeleteTextures ( int n, IntBuffer textures );\r
+\r
+ public native void glDepthFunc ( int func );\r
+\r
+ public native void glDepthMask ( boolean flag );\r
+\r
+ public native void glDepthRangef ( float zNear, float zFar );\r
+\r
+ public native void glDetachShader ( int program, int shader );\r
+\r
+ public native void glDisable ( int cap );\r
+\r
+ public native void glDisableVertexAttribArray ( int index );\r
+\r
+ public native void glDrawArrays ( int mode, int first, int count );\r
+\r
+ public native void glDrawElements ( int mode, int count, int type, Buffer indices );\r
+ \r
+ public native void glDrawElements ( int mode, int count, int type, int indices );\r
+\r
+ public native void glEnable ( int cap );\r
+\r
+ public native void glEnableVertexAttribArray ( int index );\r
+\r
+ public native void glFinish ( );\r
+\r
+ public native void glFlush ( );\r
+\r
+ public native void glFramebufferRenderbuffer ( int target, int attachment, int renderbuffertarget, int renderbuffer );\r
+\r
+ public native void glFramebufferTexture2D ( int target, int attachment, int textarget, int texture, int level );\r
+\r
+ public native void glFrontFace ( int mode );\r
+\r
+ public native void glGenBuffers ( int n, IntBuffer buffers );\r
+\r
+ public native void glGenerateMipmap ( int target );\r
+\r
+ public native void glGenFramebuffers ( int n, IntBuffer framebuffers );\r
+\r
+ public native void glGenRenderbuffers ( int n, IntBuffer renderbuffers );\r
+\r
+ public native void glGenTextures ( int n, IntBuffer textures );\r
+\r
+ public native String glGetActiveAttrib ( int program, int index, IntBuffer size, Buffer type );\r
+\r
+ public native String glGetActiveUniform ( int program, int index, IntBuffer size, Buffer type );\r
+\r
+ public native void glGetAttachedShaders ( int program, int maxcount, Buffer count, IntBuffer shaders );\r
+\r
+ public native int glGetAttribLocation ( int program, String name );\r
+\r
+ public native void glGetBooleanv ( int pname, Buffer params );\r
+\r
+ public native void glGetBufferParameteriv ( int target, int pname, IntBuffer params );\r
+\r
+ public native int glGetError ( );\r
+\r
+ public native void glGetFloatv ( int pname, FloatBuffer params );\r
+\r
+ public native void glGetFramebufferAttachmentParameteriv ( int target, int attachment, int pname, IntBuffer params );\r
+\r
+ public native void glGetIntegerv ( int pname, IntBuffer params );\r
+\r
+ public native void glGetProgramiv ( int program, int pname, IntBuffer params );\r
+\r
+ public native String glGetProgramInfoLog ( int program );\r
+\r
+ public native void glGetRenderbufferParameteriv ( int target, int pname, IntBuffer params );\r
+\r
+ public native void glGetShaderiv ( int shader, int pname, IntBuffer params );\r
+\r
+ public native String glGetShaderInfoLog ( int shader );\r
+\r
+ public native void glGetShaderPrecisionFormat ( int shadertype, int precisiontype, IntBuffer range, IntBuffer precision );\r
+\r
+ public native void glGetShaderSource ( int shader, int bufsize, Buffer length, String source );\r
+\r
+ public native String glGetString ( int name );\r
+\r
+ public native void glGetTexParameterfv ( int target, int pname, FloatBuffer params );\r
+\r
+ public native void glGetTexParameteriv ( int target, int pname, IntBuffer params );\r
+\r
+ public native void glGetUniformfv ( int program, int location, FloatBuffer params );\r
+\r
+ public native void glGetUniformiv ( int program, int location, IntBuffer params );\r
+\r
+ public native int glGetUniformLocation ( int program, String name );\r
+\r
+ public native void glGetVertexAttribfv ( int index, int pname, FloatBuffer params );\r
+\r
+ public native void glGetVertexAttribiv ( int index, int pname, IntBuffer params );\r
+\r
+ public native void glGetVertexAttribPointerv ( int index, int pname, Buffer pointer );\r
+\r
+ public native void glHint ( int target, int mode );\r
+\r
+ public native boolean glIsBuffer ( int buffer );\r
+\r
+ public native boolean glIsEnabled ( int cap );\r
+\r
+ public native boolean glIsFramebuffer ( int framebuffer );\r
+\r
+ public native boolean glIsProgram ( int program );\r
+\r
+ public native boolean glIsRenderbuffer ( int renderbuffer );\r
+\r
+ public native boolean glIsShader ( int shader );\r
+\r
+ public native boolean glIsTexture ( int texture );\r
+\r
+ public native void glLineWidth ( float width );\r
+\r
+ public native void glLinkProgram ( int program );\r
+\r
+ public native void glPixelStorei ( int pname, int param );\r
+\r
+ public native void glPolygonOffset ( float factor, float units );\r
+\r
+ public native void glReadPixels ( int x, int y, int width, int height, int format, int type, Buffer pixels );\r
+\r
+ public native void glReleaseShaderCompiler ( );\r
+\r
+ public native void glRenderbufferStorage ( int target, int internalformat, int width, int height );\r
+\r
+ public native void glSampleCoverage ( float value, boolean invert );\r
+\r
+ public native void glScissor ( int x, int y, int width, int height );\r
+\r
+ public native void glShaderBinary ( int n, IntBuffer shaders, int binaryformat, Buffer binary, int length );\r
+\r
+ public native void glShaderSource ( int shader, String string );\r
+\r
+ public native void glStencilFunc ( int func, int ref, int mask );\r
+\r
+ public native void glStencilFuncSeparate ( int face, int func, int ref, int mask );\r
+\r
+ public native void glStencilMask ( int mask );\r
+\r
+ public native void glStencilMaskSeparate ( int face, int mask );\r
+\r
+ public native void glStencilOp ( int fail, int zfail, int zpass );\r
+\r
+ public native void glStencilOpSeparate ( int face, int fail, int zfail, int zpass );\r
+\r
+ public native void glTexImage2D ( int target, int level, int internalformat, int width, int height, int border, int format, int type, Buffer pixels );\r
+\r
+ public native void glTexParameterf ( int target, int pname, float param );\r
+\r
+ public native void glTexParameterfv ( int target, int pname, FloatBuffer params );\r
+\r
+ public native void glTexParameteri ( int target, int pname, int param );\r
+\r
+ public native void glTexParameteriv ( int target, int pname, IntBuffer params );\r
+\r
+ public native void glTexSubImage2D ( int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, Buffer pixels );\r
+\r
+ public native void glUniform1f ( int location, float x );\r
+\r
+ public native void glUniform1fv ( int location, int count, FloatBuffer v );\r
+\r
+ public native void glUniform1i ( int location, int x );\r
+\r
+ public native void glUniform1iv ( int location, int count, IntBuffer v );\r
+\r
+ public native void glUniform2f ( int location, float x, float y );\r
+\r
+ public native void glUniform2fv ( int location, int count, FloatBuffer v );\r
+\r
+ public native void glUniform2i ( int location, int x, int y );\r
+\r
+ public native void glUniform2iv ( int location, int count, IntBuffer v );\r
+\r
+ public native void glUniform3f ( int location, float x, float y, float z );\r
+\r
+ public native void glUniform3fv ( int location, int count, FloatBuffer v );\r
+\r
+ public native void glUniform3i ( int location, int x, int y, int z );\r
+\r
+ public native void glUniform3iv ( int location, int count, IntBuffer v );\r
+\r
+ public native void glUniform4f ( int location, float x, float y, float z, float w );\r
+\r
+ public native void glUniform4fv ( int location, int count, FloatBuffer v );\r
+\r
+ public native void glUniform4i ( int location, int x, int y, int z, int w );\r
+\r
+ public native void glUniform4iv ( int location, int count, IntBuffer v );\r
+\r
+ public native void glUniformMatrix2fv ( int location, int count, boolean transpose, FloatBuffer value );\r
+\r
+ public native void glUniformMatrix3fv ( int location, int count, boolean transpose, FloatBuffer value );\r
+\r
+ public native void glUniformMatrix4fv ( int location, int count, boolean transpose, FloatBuffer value );\r
+\r
+ public native void glUseProgram ( int program );\r
+\r
+ public native void glValidateProgram ( int program );\r
+\r
+ public native void glVertexAttrib1f ( int indx, float x );\r
+\r
+ public native void glVertexAttrib1fv ( int indx, FloatBuffer values );\r
+\r
+ public native void glVertexAttrib2f ( int indx, float x, float y );\r
+\r
+ public native void glVertexAttrib2fv ( int indx, FloatBuffer values );\r
+\r
+ public native void glVertexAttrib3f ( int indx, float x, float y, float z );\r
+\r
+ public native void glVertexAttrib3fv ( int indx, FloatBuffer values );\r
+\r
+ public native void glVertexAttrib4f ( int indx, float x, float y, float z, float w );\r
+\r
+ public native void glVertexAttrib4fv ( int indx, FloatBuffer values );\r
+\r
+ public native void glVertexAttribPointer ( int indx, int size, int type, boolean normalized, int stride, Buffer ptr );\r
+ \r
+ public native void glVertexAttribPointer ( int indx, int size, int type, boolean normalized, int stride, int ptr );\r
+\r
+ public native void glViewport ( int x, int y, int width, int height );\r
+}
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.awt.Toolkit;\r
+import java.awt.image.BufferedImage;\r
+import java.io.InputStream;\r
+\r
+import javax.imageio.ImageIO;\r
+\r
+import com.badlogic.gdx.Graphics;\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.graphics.GL10;\r
+import com.badlogic.gdx.graphics.GL11;\r
+import com.badlogic.gdx.graphics.GL20;\r
+import com.badlogic.gdx.graphics.GLCommon;\r
+import com.badlogic.gdx.graphics.Pixmap;\r
+import com.badlogic.gdx.graphics.Pixmap.Format;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.Texture.TextureFilter;\r
+import com.badlogic.gdx.graphics.Texture.TextureWrap;\r
+import com.badlogic.gdx.graphics.TextureData;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+import com.badlogic.gdx.utils.MathUtils;\r
+\r
+public class AngleGraphics implements Graphics {\r
+ GL20 gl;\r
+ int width;\r
+ int height;\r
+ long lastTime = System.nanoTime();\r
+ long frameStart = System.nanoTime();\r
+ int fps;\r
+ int frames;\r
+ float deltaTime = 0;\r
+ \r
+ AngleGraphics(int width, int height) {\r
+ gl = new AngleGLES20();\r
+ }\r
+ \r
+ @Override\r
+ public boolean isGL11Available() {\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public boolean isGL20Available() {\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ public GLCommon getGLCommon() {\r
+ return gl;\r
+ }\r
+\r
+ @Override\r
+ public GL10 getGL10() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public GL11 getGL11() {\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public GL20 getGL20() {\r
+ return gl;\r
+ }\r
+\r
+ @Override\r
+ public int getWidth() {\r
+ return width;\r
+ }\r
+\r
+ @Override\r
+ public int getHeight() {\r
+ return height;\r
+ }\r
+\r
+ @Override\r
+ public float getDeltaTime() {\r
+ return deltaTime;\r
+ }\r
+\r
+ @Override\r
+ public int getFramesPerSecond() {\r
+ return fps;\r
+ }\r
+\r
+ @Override\r
+ public Pixmap newPixmap(int width, int height, Format format) {\r
+ return new AnglePixmap(width, height, format);\r
+ }\r
+\r
+ @Override\r
+ public Pixmap newPixmap(InputStream in) {\r
+ try {\r
+ BufferedImage img = (BufferedImage) ImageIO.read(in);\r
+ return new AnglePixmap(img);\r
+ } catch (Exception ex) {\r
+ throw new GdxRuntimeException(\r
+ "Couldn't load Pixmap from InputStream", ex);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Pixmap newPixmap(FileHandle file) {\r
+ return newPixmap(file.read());\r
+ }\r
+\r
+ @Override\r
+ public Pixmap newPixmap(Object nativePixmap) {\r
+ return new AnglePixmap((BufferedImage) nativePixmap);\r
+ }\r
+\r
+ @Override\r
+ public Texture newUnmanagedTexture(int width, int height, Format format,\r
+ TextureFilter minFilter, TextureFilter magFilter,\r
+ TextureWrap uWrap, TextureWrap vWrap) {\r
+ if (!MathUtils.isPowerOfTwo(width) || !MathUtils.isPowerOfTwo(height))\r
+ throw new GdxRuntimeException(\r
+ "Texture dimensions must be a power of two: " + width + "x"\r
+ + height);\r
+\r
+ if (format == Format.Alpha)\r
+ return new AngleTexture(width, height,\r
+ BufferedImage.TYPE_BYTE_GRAY, minFilter, magFilter, uWrap,\r
+ vWrap, false);\r
+ else\r
+ return new AngleTexture(width, height,\r
+ BufferedImage.TYPE_4BYTE_ABGR, minFilter, magFilter, uWrap,\r
+ vWrap, false);\r
+ }\r
+\r
+ @Override\r
+ public Texture newUnmanagedTexture(Pixmap pixmap, TextureFilter minFilter,\r
+ TextureFilter magFilter, TextureWrap uWrap, TextureWrap vWrap) {\r
+ if (!MathUtils.isPowerOfTwo(pixmap.getHeight())\r
+ || !MathUtils.isPowerOfTwo(pixmap.getWidth()))\r
+ throw new GdxRuntimeException(\r
+ "Texture dimensions must be a power of two: " + width + "x"\r
+ + height);\r
+\r
+ return new AngleTexture((BufferedImage) pixmap.getNativePixmap(),\r
+ minFilter, magFilter, uWrap, vWrap, false);\r
+ }\r
+\r
+ @Override\r
+ public Texture newTexture(FileHandle file, TextureFilter minFilter,\r
+ TextureFilter magFilter, TextureWrap uWrap, TextureWrap vWrap) { \r
+ Pixmap pixmap = newPixmap(file);\r
+ if (!MathUtils.isPowerOfTwo(pixmap.getHeight()) || !MathUtils.isPowerOfTwo(pixmap.getWidth()))\r
+ throw new GdxRuntimeException("Texture dimensions must be a power of two: " + file + " (" + pixmap.getWidth() + "x"\r
+ + pixmap.getHeight() + ")"); \r
+\r
+ return new AngleTexture(file, minFilter, magFilter, uWrap, vWrap, false);\r
+ }\r
+\r
+ @Override\r
+ public Texture newTexture(TextureData textureData, TextureFilter minFilter,\r
+ TextureFilter magFilter, TextureWrap uWrap, TextureWrap vWrap) {\r
+ return new AngleTexture(textureData, minFilter, magFilter, uWrap, vWrap);\r
+ }\r
+\r
+ @Override\r
+ public GraphicsType getType() {\r
+ return GraphicsType.Angle;\r
+ }\r
+\r
+ @Override\r
+ public float getPpiX() {\r
+ return Toolkit.getDefaultToolkit().getScreenResolution();\r
+ }\r
+\r
+ @Override\r
+ public float getPpiY() {\r
+ return Toolkit.getDefaultToolkit().getScreenResolution();\r
+ }\r
+\r
+ @Override\r
+ public float getPpcX() {\r
+ return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);\r
+ }\r
+\r
+ @Override\r
+ public float getPpcY() {\r
+ return (Toolkit.getDefaultToolkit().getScreenResolution() / 2.54f);\r
+ }\r
+ \r
+ void updateTime () {\r
+ long time = System.nanoTime();\r
+ deltaTime = (time - lastTime) / 1000000000.0f;\r
+ lastTime = time;\r
+\r
+ if (time - frameStart >= 1000000000) {\r
+ fps = frames;\r
+ frames = 0;\r
+ frameStart = time;\r
+ }\r
+ frames++;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+\r
+import javax.swing.JOptionPane;\r
+import javax.swing.SwingUtilities;\r
+\r
+import com.badlogic.anglejni.ESLoop;\r
+import com.badlogic.gdx.Input;\r
+import com.badlogic.gdx.InputProcessor;\r
+import com.badlogic.gdx.utils.Pool;\r
+import com.badlogic.gdx.utils.Pool.PoolObjectFactory;\r
+\r
+public class AngleInput implements Input {\r
+\r
+ class KeyEvent {\r
+ static final int KEY_DOWN = 0;\r
+ static final int KEY_UP = 1;\r
+ static final int KEY_TYPED = 2;\r
+\r
+ int type;\r
+ int keyCode;\r
+ char keyChar;\r
+ }\r
+\r
+ class TouchEvent {\r
+ static final int TOUCH_DOWN = 0;\r
+ static final int TOUCH_UP = 1;\r
+ static final int TOUCH_DRAGGED = 2;\r
+\r
+ int type;\r
+ int x;\r
+ int y;\r
+ int pointer;\r
+ }\r
+\r
+ Pool<KeyEvent> freeKeyEvents = new Pool<KeyEvent>(\r
+ new PoolObjectFactory<KeyEvent>() {\r
+\r
+ @Override\r
+ public KeyEvent createObject() {\r
+ return new KeyEvent();\r
+ }\r
+ }, 1000);\r
+\r
+ Pool<TouchEvent> freeTouchEvents = new Pool<TouchEvent>(\r
+ new PoolObjectFactory<TouchEvent>() {\r
+\r
+ @Override\r
+ public TouchEvent createObject() {\r
+ return new TouchEvent();\r
+ }\r
+ }, 1000);\r
+\r
+ List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();\r
+ List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();\r
+ boolean mousePressed = false;\r
+ int mouseX = 0;\r
+ int mouseY = 0;\r
+ HashSet<Integer> pressedKeys = new HashSet<Integer>();\r
+\r
+ private InputProcessor processor;\r
+ \r
+ public float getAccelerometerX () {\r
+ return 0;\r
+ }\r
+\r
+ public float getAccelerometerY () {\r
+ return 0;\r
+ }\r
+\r
+ public float getAccelerometerZ () {\r
+ return 0;\r
+ }\r
+\r
+ public void getTextInput (final TextInputListener listener, final String title, final String text) {\r
+ SwingUtilities.invokeLater(new Runnable() {\r
+ public void run () {\r
+ String output = JOptionPane.showInputDialog(null, title, text);\r
+ listener.input(output);\r
+ }\r
+ });\r
+ }\r
+\r
+ public int getX () {\r
+ // FIXME\r
+ return 0;\r
+ }\r
+\r
+ public int getY () {\r
+ // FIXME\r
+ return 0;\r
+ }\r
+\r
+ public boolean isAccelerometerAvailable () {\r
+ return false;\r
+ }\r
+\r
+ public boolean isKeyPressed (int key) {\r
+ // FIXME\r
+ return false;\r
+ }\r
+\r
+ public boolean isTouched () {\r
+ // FIXME \r
+ return false;\r
+ }\r
+\r
+ public int getX (int pointer) {\r
+ if (pointer > 0)\r
+ return 0;\r
+ else\r
+ return getX();\r
+ }\r
+\r
+ public int getY (int pointer) {\r
+ if (pointer > 0)\r
+ return 0;\r
+ else\r
+ return getY();\r
+ }\r
+\r
+ public boolean isTouched (int pointer) {\r
+ if (pointer > 0)\r
+ return false;\r
+ else\r
+ return isTouched();\r
+ }\r
+\r
+ public boolean supportsMultitouch () {\r
+ return false;\r
+ }\r
+\r
+ @Override public void setOnscreenKeyboardVisible (boolean visible) {\r
+ \r
+ }\r
+\r
+ @Override public boolean supportsOnscreenKeyboard () {\r
+ return false;\r
+ }\r
+ \r
+ @Override public void setCatchBackKey (boolean catchBack) {\r
+ \r
+ }\r
+\r
+ void processEvents() {\r
+ synchronized(this) {\r
+ if(processor!=null) { \r
+ InputProcessor processor = this.processor;\r
+ int len = keyEvents.size();\r
+ for(int i=0; i < len; i++) {\r
+ KeyEvent e = keyEvents.get(i);\r
+ switch(e.type) {\r
+ case KeyEvent.KEY_DOWN:\r
+ processor.keyDown(e.keyCode);\r
+ break;\r
+ case KeyEvent.KEY_UP:\r
+ processor.keyUp(e.keyCode);\r
+ break;\r
+ case KeyEvent.KEY_TYPED:\r
+ processor.keyTyped(e.keyChar);\r
+ }\r
+ freeKeyEvents.free(e);\r
+ } \r
+ \r
+ len = touchEvents.size();\r
+ for(int i=0; i < len; i++) {\r
+ TouchEvent e = touchEvents.get(i);\r
+ switch(e.type) {\r
+ case TouchEvent.TOUCH_DOWN:\r
+ processor.touchDown(e.x, e.y, e.pointer);\r
+ break;\r
+ case TouchEvent.TOUCH_UP:\r
+ processor.touchUp(e.x, e.y, e.pointer);\r
+ break;\r
+ case TouchEvent.TOUCH_DRAGGED:\r
+ processor.touchDragged(e.x, e.y, e.pointer);\r
+ }\r
+ freeTouchEvents.free(e);\r
+ }\r
+ } else {\r
+ int len = touchEvents.size();\r
+ for(int i=0; i < len; i++) {\r
+ freeTouchEvents.free(touchEvents.get(i));\r
+ }\r
+ \r
+ len = keyEvents.size();\r
+ for(int i=0; i < len; i++) {\r
+ freeKeyEvents.free(keyEvents.get(i));\r
+ }\r
+ }\r
+ \r
+ keyEvents.clear();\r
+ touchEvents.clear();\r
+ }\r
+ } \r
+ \r
+ \r
+ boolean isButtonPressed () { \r
+ return mousePressed;\r
+ }\r
+\r
+ @Override\r
+ public void setInputProcessor(InputProcessor processor) {\r
+ this.processor = processor;\r
+ }\r
+\r
+ void registerKeyEvent(int action, int key, int uniCode) {\r
+ synchronized(this) {\r
+ KeyEvent event = freeKeyEvents.newObject();\r
+ event.keyChar = (char)uniCode;\r
+ event.keyCode = translateKey(key); \r
+ \r
+ switch(action) {\r
+ case ESLoop.ES_KEY_DOWN:\r
+ event.type = KeyEvent.KEY_DOWN;\r
+ break;\r
+ case ESLoop.ES_KEY_UP:\r
+ event.type = KeyEvent.KEY_UP;\r
+ break;\r
+ case ESLoop.ES_KEY_TYPED:\r
+ event.type = KeyEvent.KEY_TYPED;\r
+ break;\r
+ }\r
+ \r
+ keyEvents.add(event);\r
+ } \r
+ }\r
+\r
+ void registerMouseEvent(int action, int x, int y, int button) {\r
+ if(button != 1)\r
+ return;\r
+ \r
+ synchronized(this) {\r
+ TouchEvent event = freeTouchEvents.newObject();\r
+ event.x = x;\r
+ event.y = y;\r
+ event.pointer = 0;\r
+ \r
+ switch(action) {\r
+ case ESLoop.ES_MOUSE_DOWN:\r
+ event.type = TouchEvent.TOUCH_DOWN;\r
+ break;\r
+ case ESLoop.ES_MOUSE_UP:\r
+ event.type = TouchEvent.TOUCH_UP;\r
+ break;\r
+ case ESLoop.ES_MOUSE_MOVE: \r
+ event.type = TouchEvent.TOUCH_DRAGGED;\r
+ break;\r
+ }\r
+ } \r
+ }\r
+ \r
+ int translateKey(int keyCode) {\r
+ // FIXME\r
+ return keyCode;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.IOException;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+\r
+import javax.sound.sampled.AudioFormat;\r
+import javax.sound.sampled.AudioInputStream;\r
+import javax.sound.sampled.AudioSystem;\r
+import javax.sound.sampled.FloatControl;\r
+import javax.sound.sampled.LineUnavailableException;\r
+import javax.sound.sampled.SourceDataLine;\r
+import javax.sound.sampled.UnsupportedAudioFileException;\r
+\r
+import com.badlogic.gdx.audio.Music;\r
+import com.badlogic.gdx.files.FileHandle;\r
+\r
+final class AngleMusic implements Music, Runnable {\r
+ private final int Playing = 0;\r
+ private final int Stopped = 1;\r
+ private final int Paused = 2;\r
+\r
+ private AtomicInteger state = new AtomicInteger(Stopped);\r
+ private final Thread thread;\r
+ private final FileHandle handle;\r
+ private AudioInputStream ain;\r
+ private final SourceDataLine line;\r
+ private final byte[] buffer;\r
+ private AtomicBoolean looping = new AtomicBoolean(false);\r
+ private boolean disposed = false;\r
+\r
+ public AngleMusic (FileHandle handle) throws UnsupportedAudioFileException, IOException, LineUnavailableException {\r
+ this.handle = handle;\r
+\r
+ openAudioInputStream();\r
+ AudioFormat audioFormat = ain.getFormat();\r
+ line = AudioSystem.getSourceDataLine(audioFormat);\r
+ line.open(audioFormat); // FIXME reduce latency, gotta reimplement the playback thread.\r
+ line.start();\r
+ buffer = new byte[10000 * ain.getFormat().getFrameSize()];\r
+ ain.close();\r
+ ain = null;\r
+\r
+ thread = new Thread(this);\r
+ thread.setDaemon(true);\r
+ thread.start();\r
+ }\r
+\r
+ private void openAudioInputStream () throws UnsupportedAudioFileException, IOException {\r
+ ain = AudioSystem.getAudioInputStream(new BufferedInputStream(handle.read()));\r
+ AudioFormat baseFormat = ain.getFormat();\r
+ AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,\r
+ baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);\r
+\r
+ ain = AudioSystem.getAudioInputStream(decodedFormat, ain);\r
+ }\r
+\r
+ @Override public void dispose () {\r
+ disposed = true;\r
+ try {\r
+ thread.join();\r
+ line.close();\r
+ ain.close();\r
+ } catch (Exception e) {\r
+ // nothing we can do here\r
+ }\r
+ }\r
+\r
+ @Override public boolean isLooping () {\r
+ return looping.get();\r
+ }\r
+\r
+ @Override public boolean isPlaying () {\r
+ return state.get() == Playing;\r
+ }\r
+\r
+ @Override public void pause () {\r
+ state.compareAndSet(Playing, Paused);\r
+ }\r
+\r
+ @Override public void play () {\r
+ state.set(Playing);\r
+ }\r
+\r
+ @Override public void stop () {\r
+ state.set(Stopped);\r
+ }\r
+\r
+ @Override public void setLooping (boolean isLooping) {\r
+ looping.set(isLooping);\r
+ }\r
+\r
+ @Override public void setVolume (float volume) {\r
+ try {\r
+ volume = Math.min(1, volume);\r
+ volume = Math.max(0, volume);\r
+ FloatControl control = (FloatControl)line.getControl(FloatControl.Type.MASTER_GAIN);\r
+ control.setValue(-80 + volume * 80);\r
+ } catch (IllegalArgumentException ex) {\r
+ ex.printStackTrace();\r
+ }\r
+ }\r
+\r
+ @Override public void run () {\r
+ int readBytes = 0;\r
+ long readSamples = 0;\r
+\r
+ while (!disposed) {\r
+ int curState = state.get();\r
+ if (curState == Playing) {\r
+ try {\r
+ if (ain == null) openAudioInputStream();\r
+ readBytes = ain.read(buffer);\r
+\r
+ if (readBytes != -1) {\r
+ int writtenBytes = line.write(buffer, 0, readBytes);\r
+ while (writtenBytes != readBytes)\r
+ writtenBytes += line.write(buffer, writtenBytes, readBytes - writtenBytes);\r
+ readSamples += readBytes / ain.getFormat().getFrameSize();\r
+ } else {\r
+ System.out.println("samples: " + readSamples);\r
+ ain.close();\r
+ if (!isLooping()) state.set(Stopped);\r
+ else openAudioInputStream();\r
+ }\r
+ } catch (Exception ex) {\r
+ try {\r
+ ain.close();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ line.close();\r
+ ex.printStackTrace();\r
+ state.set(Stopped);\r
+ return;\r
+ }\r
+ }\r
+ else if (curState == Stopped && ain != null)\r
+ {\r
+ try {\r
+ ain.close();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ ain = null;\r
+ line.flush();\r
+ }\r
+\r
+ try {\r
+ Thread.sleep(10);\r
+ } catch (InterruptedException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.awt.AlphaComposite;\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Composite;\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.image.BufferedImage;\r
+\r
+import com.badlogic.gdx.graphics.Pixmap;\r
+\r
+/**\r
+ * An implementation of Pixmap based on the java graphics framework.\r
+ * \r
+ * @author badlogicgames@gmail.com\r
+ * \r
+ */\r
+final class AnglePixmap implements Pixmap {\r
+ BufferedImage pixmap;\r
+ Composite composite;\r
+ Color color = new Color(0);\r
+ int strokeWidth = 1;\r
+\r
+ AnglePixmap (int width, int height, Pixmap.Format format) {\r
+ int internalformat = getInternalFormat(format);\r
+ pixmap = new BufferedImage(width, height, internalformat);\r
+ Graphics2D g = pixmap.createGraphics();\r
+ g.setComposite(AlphaComposite.Clear);\r
+ g.setColor(new Color(0, 0, 0, 0));\r
+ g.fillRect(0, 0, pixmap.getWidth(), pixmap.getHeight());\r
+ g.dispose();\r
+ composite = AlphaComposite.SrcOver;\r
+ }\r
+\r
+ AnglePixmap (BufferedImage image) {\r
+ if (image == null) throw new IllegalArgumentException("image cannot be null.");\r
+ pixmap = convert(image);\r
+ }\r
+\r
+ private BufferedImage convert (BufferedImage image) {\r
+ BufferedImage out = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);\r
+ Graphics2D g = out.createGraphics();\r
+ g.setComposite(AlphaComposite.Clear);\r
+ g.fillRect(0, 0, image.getWidth(), image.getHeight());\r
+ g.setComposite(AlphaComposite.SrcOver);\r
+ g.drawImage(image, 0, 0, null);\r
+ g.dispose();\r
+ return out;\r
+ }\r
+\r
+ private int getInternalFormat (Pixmap.Format format) {\r
+ return BufferedImage.TYPE_4BYTE_ABGR;\r
+ }\r
+\r
+ public void drawCircle (int x, int y, int radius) {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.setStroke(new BasicStroke(strokeWidth));\r
+ g.drawRect(x, y, radius * 2, radius * 2);\r
+ g.dispose();\r
+\r
+ }\r
+\r
+ public void drawLine (int x, int y, int x2, int y2) {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.setStroke(new BasicStroke(strokeWidth));\r
+ g.drawLine(x, y, x2, y2);\r
+ g.dispose();\r
+\r
+ }\r
+\r
+ public void drawRectangle (int x, int y, int width, int height) {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.setStroke(new BasicStroke(strokeWidth));\r
+ g.drawRect(x, y, width, height);\r
+ g.dispose();\r
+ }\r
+\r
+ public void fill () {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.fillRect(0, 0, pixmap.getWidth(), pixmap.getHeight());\r
+ g.dispose();\r
+ }\r
+\r
+ public void fillCircle (int x, int y, int radius) {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.fillOval(x, y, radius * 2, radius * 2);\r
+ g.dispose();\r
+ }\r
+\r
+ public void fillRectangle (int x, int y, int width, int height) {\r
+ Graphics2D g = (Graphics2D)pixmap.getGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
+ g.setComposite(composite);\r
+ g.setColor(color);\r
+ g.fillRect(x, y, width, height);\r
+ g.dispose();\r
+ }\r
+\r
+ public Object getNativePixmap () {\r
+ return pixmap;\r
+ }\r
+\r
+ public void setColor (float r, float g, float b, float a) {\r
+ color = new Color(r, g, b, a);\r
+ }\r
+\r
+ public void setStrokeWidth (int width) {\r
+ strokeWidth = width;\r
+ }\r
+\r
+ public int getPixel (int x, int y) {\r
+ if (x < 0 || x >= pixmap.getWidth()) return 0;\r
+ if (y < 0 || y >= pixmap.getHeight()) return 0;\r
+ return pixmap.getRGB(x, y);\r
+ }\r
+\r
+ public int getHeight () {\r
+ return pixmap.getHeight();\r
+ }\r
+\r
+ public int getWidth () {\r
+ return pixmap.getWidth();\r
+ }\r
+\r
+ public void drawPixmap (Pixmap pixmap, int x, int y, int srcx, int srcy, int width, int height) {\r
+ BufferedImage image = (BufferedImage)pixmap.getNativePixmap();\r
+\r
+ Graphics2D g = (Graphics2D)this.pixmap.getGraphics();\r
+ g.setComposite(composite);\r
+ g.drawImage(image, x, y, x + width, y + height, srcx, srcy, srcx + width, srcy + height, null);\r
+ g.dispose();\r
+\r
+ }\r
+\r
+ public void dispose () {\r
+\r
+ }\r
+\r
+ public void getPixelRow (int[] pixels, int y) {\r
+ for (int x = 0; x < pixmap.getWidth(); x++) {\r
+ pixels[x] = pixmap.getRGB(x, y);\r
+ }\r
+\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.nio.ByteBuffer;\r
+import java.nio.ByteOrder;\r
+import java.nio.ShortBuffer;\r
+\r
+import javax.sound.sampled.AudioFormat;\r
+import javax.sound.sampled.AudioInputStream;\r
+import javax.sound.sampled.AudioSystem;\r
+import javax.sound.sampled.Clip;\r
+import javax.sound.sampled.UnsupportedAudioFileException;\r
+\r
+import com.badlogic.gdx.audio.Sound;\r
+\r
+/**\r
+ * Implements the {@link Sound} interface for the desktop using {@link Clip}s internally.\r
+ * @author mzechner\r
+ * \r
+ */\r
+final class AngleSound implements Sound {\r
+ /** the audio format **/\r
+ private final AudioFormat format;\r
+\r
+ /** the audio data **/\r
+ private final byte[] originalSamples;\r
+\r
+ /** the float audio data **/\r
+ private float[] samples;\r
+\r
+ /** the audio instance **/\r
+ private final AngleAudio audio;\r
+\r
+ public AngleSound (AngleAudio audio, AngleFileHandle file) throws UnsupportedAudioFileException, IOException {\r
+ this.audio = audio;\r
+ InputStream fin = new BufferedInputStream(file.read());\r
+ AudioInputStream ain = AudioSystem.getAudioInputStream(fin);\r
+ AudioFormat baseFormat = ain.getFormat();\r
+ AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,\r
+ baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);\r
+\r
+ ain = AudioSystem.getAudioInputStream(decodedFormat, ain);\r
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();\r
+ byte[] buffer = new byte[1024 * 10];\r
+ int readBytes = ain.read(buffer);\r
+ while (readBytes != -1) {\r
+ bytes.write(buffer, 0, readBytes);\r
+ readBytes = ain.read(buffer);\r
+ }\r
+ ain.close();\r
+ System.out.println(decodedFormat);\r
+ format = decodedFormat;\r
+ originalSamples = bytes.toByteArray();\r
+\r
+ ByteBuffer tmpBuffer = ByteBuffer.wrap(originalSamples);\r
+ tmpBuffer.order(ByteOrder.LITTLE_ENDIAN);\r
+ ShortBuffer shorts = tmpBuffer.asShortBuffer();\r
+ samples = new float[originalSamples.length / 2];\r
+ for (int i = 0; i < samples.length; i++) {\r
+ float value = shorts.get(i) / (float)Short.MAX_VALUE;\r
+ if (value < -1) value = -1;\r
+ if (value > 1) value = 1;\r
+ samples[i] = value;\r
+ }\r
+\r
+ samples = resample(samples, decodedFormat.getSampleRate(), decodedFormat.getChannels() == 1);\r
+ }\r
+\r
+ private float[] resample (float[] samples, float sampleRate, boolean isMono) {\r
+ if (sampleRate == 44100) return samples;\r
+\r
+ float idxInc = sampleRate / 44100;\r
+ int numSamples = (int)((samples.length / (float)sampleRate) * 44100);\r
+ if (!isMono && numSamples % 2 != 0) numSamples--;\r
+\r
+ float[] newSamples = new float[numSamples];\r
+\r
+ if (isMono) {\r
+ float idx = 0;\r
+ for (int i = 0; i < newSamples.length; i++) {\r
+ int intIdx = (int)idx;\r
+ if (intIdx >= samples.length - 1) break;\r
+\r
+ float value = samples[intIdx] + samples[intIdx + 1];\r
+ value /= 2;\r
+ if (value > 1) value = 1;\r
+ if (value < -1) value = -1;\r
+ newSamples[i] = value;\r
+ idx += idxInc;\r
+ }\r
+ } else {\r
+ float idx = 0;\r
+ for (int i = 0; i < newSamples.length; i += 2) {\r
+ int intIdxL = (int)idx * 2;\r
+ int intIdxR = (int)idx * 2 + 1;\r
+ if (intIdxL >= samples.length - 2) break;\r
+\r
+ float value = samples[intIdxL] + samples[intIdxL + 2];\r
+ value /= 2;\r
+ if (value > 1) value = 1;\r
+ if (value < -1) value = -1;\r
+ newSamples[i] = value;\r
+\r
+ value = samples[intIdxR] + samples[intIdxR + 2];\r
+ value /= 2;\r
+ if (value > 1) value = 1;\r
+ if (value < -1) value = -1;\r
+ newSamples[i + 1] = value;\r
+\r
+ idx += idxInc;\r
+ }\r
+ }\r
+\r
+ return newSamples;\r
+ }\r
+\r
+ public void dispose () {\r
+\r
+ }\r
+\r
+ public void play () {\r
+ audio.enqueueSound(this, 1);\r
+ }\r
+\r
+ public void play (float volume) {\r
+ audio.enqueueSound(this, volume);\r
+ }\r
+\r
+ /**\r
+ * @return the {@link AudioFormat} of the audio data\r
+ */\r
+ public AudioFormat getAudioFormat () {\r
+ return format;\r
+ }\r
+\r
+ /**\r
+ * @return the audio samples in form of a byte array\r
+ */\r
+ public float[] getAudioData () {\r
+ return samples;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com)\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the\r
+ * License. You may obtain a copy of the License at\r
+ * \r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"\r
+ * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language\r
+ * governing permissions and limitations under the License.\r
+ */\r
+\r
+package com.badlogic.gdx.backends.angle;\r
+\r
+import java.awt.Graphics2D;\r
+import java.awt.RenderingHints;\r
+import java.awt.image.BufferedImage;\r
+import java.awt.image.ColorModel;\r
+import java.awt.image.DataBufferInt;\r
+import java.awt.image.Raster;\r
+import java.io.IOException;\r
+import java.nio.ByteBuffer;\r
+import java.nio.ByteOrder;\r
+import java.nio.IntBuffer;\r
+\r
+import com.badlogic.gdx.Gdx;\r
+import com.badlogic.gdx.backends.angle.PNGDecoder.Format;\r
+import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.graphics.GL10;\r
+import com.badlogic.gdx.graphics.GL20;\r
+import com.badlogic.gdx.graphics.Pixmap;\r
+import com.badlogic.gdx.graphics.Texture;\r
+import com.badlogic.gdx.graphics.TextureData;\r
+import com.badlogic.gdx.utils.BufferUtils;\r
+import com.badlogic.gdx.utils.GdxRuntimeException;\r
+\r
+/**\r
+ * @author badlogicgames@gmail.com\r
+ * @author Nathan Sweet <misc@n4te.com>\r
+ */\r
+final class AngleTexture implements Texture {\r
+ /** height in pixels of texture **/\r
+ private int texHeight;\r
+ /** width in pixels of texture **/\r
+ private int texWidth;\r
+ /** whether this textures i managed or not **/\r
+ private final boolean isManaged;\r
+ private int textureID;\r
+ private final boolean isMipMapped;\r
+\r
+ /** global number of textures **/\r
+ public static int textures = 0;\r
+\r
+ static private ByteBuffer buffer;\r
+ static private IntBuffer intBuffer;\r
+ static private final PNGDecoder pngDecoder = new PNGDecoder();\r
+\r
+ AngleTexture (FileHandle file, TextureFilter minFilter, TextureFilter maxFilter, TextureWrap uWrap, TextureWrap vWrap,\r
+ boolean managed) {\r
+ this.isManaged = managed;\r
+ this.isMipMapped = TextureFilter.isMipMap(minFilter);\r
+\r
+ if (!isMipMapped && file.path().endsWith(".png")) {\r
+ // Fast path.\r
+ loadPNG(file);\r
+ } else {\r
+ BufferedImage image = (BufferedImage)Gdx.graphics.newPixmap(file).getNativePixmap();\r
+ loadMipMap(image);\r
+ }\r
+ bind();\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, getTextureFilter(minFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, getTextureFilter(maxFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, getTextureWrap(uWrap));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, getTextureWrap(vWrap));\r
+ textures++;\r
+ }\r
+\r
+ AngleTexture (BufferedImage image, TextureFilter minFilter, TextureFilter maxFilter, TextureWrap uWrap, TextureWrap vWrap,\r
+ boolean managed) {\r
+ this.isManaged = managed;\r
+ this.isMipMapped = TextureFilter.isMipMap(minFilter);\r
+\r
+ BufferedImage img = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);\r
+ loadMipMap(img);\r
+ this.draw(Gdx.graphics.newPixmap(image), 0, 0);\r
+ bind();\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, getTextureFilter(minFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, getTextureFilter(maxFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, getTextureWrap(uWrap));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, getTextureWrap(vWrap));\r
+ textures++;\r
+ }\r
+\r
+ AngleTexture (int width, int height, int format, TextureFilter minFilter, TextureFilter maxFilter, TextureWrap uWrap,\r
+ TextureWrap vWrap, boolean managed) {\r
+ this.isManaged = managed;\r
+ this.isMipMapped = TextureFilter.isMipMap(minFilter);\r
+\r
+ BufferedImage image = new BufferedImage(width, height, format);\r
+ loadMipMap(image);\r
+ bind();\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, getTextureFilter(minFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, getTextureFilter(maxFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, getTextureWrap(uWrap));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, getTextureWrap(vWrap));\r
+ textures++;\r
+ }\r
+\r
+ public AngleTexture (TextureData textureData, TextureFilter minFilter, TextureFilter magFilter, TextureWrap uWrap,\r
+ TextureWrap vWrap) {\r
+ isManaged = false;\r
+ this.isMipMapped = TextureFilter.isMipMap(minFilter);\r
+\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ IntBuffer buffer = BufferUtils.newIntBuffer(1);\r
+ gl.glGenTextures(1, buffer);\r
+ textureID = buffer.get(0);\r
+ bind(); \r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, getTextureFilter(minFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, getTextureFilter(magFilter));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, getTextureWrap(uWrap));\r
+ gl.glTexParameteri(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, getTextureWrap(vWrap));\r
+\r
+ textureData.load();\r
+ texWidth = textureData.getWidth();\r
+ texHeight = textureData.getHeight();\r
+\r
+ textures++;\r
+ }\r
+\r
+ private void loadPNG (FileHandle file) {\r
+ try {\r
+ pngDecoder.decodeHeader(file.read());\r
+ texWidth = pngDecoder.getWidth();\r
+ texHeight = pngDecoder.getHeight();\r
+ int stride = texWidth * 4;\r
+ ensureBufferSize(stride * texHeight);\r
+\r
+ Format pngFormat = pngDecoder.decideTextureFormat(PNGDecoder.Format.RGBA);\r
+ int glFormat, glInternalFormat;\r
+ switch (pngFormat) {\r
+ case ALPHA:\r
+ glFormat = GL10.GL_ALPHA;\r
+ glInternalFormat = GL10.GL_ALPHA;\r
+ break;\r
+ case LUMINANCE:\r
+ glFormat = GL10.GL_LUMINANCE;\r
+ glInternalFormat = GL10.GL_LUMINANCE;\r
+ break;\r
+ case LUMINANCE_ALPHA:\r
+ glFormat = GL10.GL_LUMINANCE_ALPHA;\r
+ glInternalFormat = GL10.GL_LUMINANCE_ALPHA;\r
+ break;\r
+ case RGB:\r
+ glFormat = GL10.GL_RGB;\r
+ glInternalFormat = GL10.GL_RGB;\r
+ break;\r
+ case RGBA:\r
+ glFormat = GL10.GL_RGBA;\r
+ glInternalFormat = GL10.GL_RGBA;\r
+ break;\r
+// case BGRA:\r
+// glFormat = GL10.GL_BGRA;\r
+// glInternalFormat = GL10.GL_BGRA;\r
+// break;\r
+ default:\r
+ throw new UnsupportedOperationException("PNG format not handled: " + pngFormat);\r
+ }\r
+ pngDecoder.decode(buffer, stride, pngFormat);\r
+ buffer.flip();\r
+\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ IntBuffer buffer = BufferUtils.newIntBuffer(1);\r
+ gl.glGenTextures(1, buffer);\r
+ textureID = buffer.get(0); \r
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);\r
+ gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, glInternalFormat, texWidth, texHeight, 0, glFormat, GL10.GL_UNSIGNED_BYTE, buffer);\r
+ } catch (IOException ex) {\r
+ throw new GdxRuntimeException("Error loading image file: " + file, ex);\r
+ }\r
+ }\r
+\r
+ private ByteBuffer toByteBuffer (BufferedImage image) {\r
+ int width = image.getWidth();\r
+ int height = image.getHeight();\r
+ ensureBufferSize(width * height * 4);\r
+\r
+ Raster raster = image.getRaster();\r
+ if (image.getType() == BufferedImage.TYPE_INT_ARGB)\r
+ intBuffer.put(((DataBufferInt)raster.getDataBuffer()).getData(), 0, width * height);\r
+ else {\r
+ // Same as image.getRGB() without allocating a large int[].\r
+ ColorModel colorModel = image.getColorModel();\r
+ Object data = raster.getDataElements(0, 0, null);\r
+ for (int y = 0; y < height; y++)\r
+ for (int x = 0; x < width; x++)\r
+ intBuffer.put(colorModel.getRGB(raster.getDataElements(x, y, data)));\r
+ }\r
+\r
+ buffer.limit(intBuffer.position() * 4);\r
+ return buffer;\r
+ }\r
+\r
+ private void ensureBufferSize (int size) {\r
+ if (buffer == null || buffer.capacity() < size) {\r
+ buffer = BufferUtils.newByteBuffer(size);\r
+ ByteBuffer temp = buffer.slice();\r
+ temp.order(ByteOrder.LITTLE_ENDIAN);\r
+ intBuffer = temp.asIntBuffer();\r
+ } else {\r
+ buffer.clear();\r
+ intBuffer.clear();\r
+ }\r
+ }\r
+\r
+ private BufferedImage scaleDown (BufferedImage image) {\r
+ BufferedImage scaled = new BufferedImage(image.getWidth() / 2, image.getHeight() / 2, BufferedImage.TYPE_4BYTE_ABGR_PRE);\r
+ Graphics2D g = scaled.createGraphics();\r
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);\r
+ g.drawImage(image, 0, 0, scaled.getWidth(), scaled.getHeight(), null);\r
+ g.dispose();\r
+ return scaled;\r
+ }\r
+\r
+ private void loadMipMap (BufferedImage image) {\r
+ int level = 0;\r
+ int height = image.getHeight();\r
+ int width = image.getWidth();\r
+ texWidth = width;\r
+ texHeight = height;\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ IntBuffer buffer = BufferUtils.newIntBuffer(1);\r
+ gl.glGenTextures(1, buffer);\r
+ textureID = buffer.get(0); \r
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);\r
+\r
+ while (height >= 1 || width >= 1 && level < 4) {\r
+ ByteBuffer imageBuffer = toByteBuffer(image);\r
+ gl.glTexImage2D(GL10.GL_TEXTURE_2D, level, GL10.GL_RGBA, width, height, 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, imageBuffer);\r
+ if (height == 1 || width == 1 || isMipMapped == false) break;\r
+\r
+ level++;\r
+ if (height > 1) height /= 2;\r
+ if (width > 1) width /= 2;\r
+\r
+ image = scaleDown(image);\r
+ }\r
+ }\r
+\r
+ private int getTextureFilter (TextureFilter filter) {\r
+ if (filter == TextureFilter.Linear)\r
+ return GL10.GL_LINEAR;\r
+ else if (filter == TextureFilter.Nearest)\r
+ return GL10.GL_NEAREST;\r
+ else if (filter == TextureFilter.MipMap)\r
+ return GL10.GL_LINEAR_MIPMAP_LINEAR;\r
+ else if (filter == TextureFilter.MipMapNearestNearest)\r
+ return GL10.GL_NEAREST_MIPMAP_NEAREST;\r
+ else if (filter == TextureFilter.MipMapNearestLinear)\r
+ return GL10.GL_NEAREST_MIPMAP_LINEAR;\r
+ else if (filter == TextureFilter.MipMapLinearNearest)\r
+ return GL10.GL_LINEAR_MIPMAP_NEAREST;\r
+ else if (filter == TextureFilter.MipMapLinearLinear)\r
+ return GL10.GL_LINEAR_MIPMAP_LINEAR;\r
+ else\r
+ return GL10.GL_LINEAR_MIPMAP_LINEAR;\r
+ }\r
+\r
+ private int getTextureWrap (TextureWrap wrap) {\r
+ if (wrap == TextureWrap.ClampToEdge)\r
+ return GL10.GL_CLAMP_TO_EDGE;\r
+ else\r
+ return GL10.GL_REPEAT;\r
+ }\r
+\r
+ public boolean isManaged () {\r
+ return isManaged;\r
+ }\r
+\r
+ public void bind () {\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);\r
+ }\r
+\r
+ public void dispose () {\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ IntBuffer buffer = BufferUtils.newIntBuffer(1);\r
+ buffer.put(textureID);\r
+ buffer.flip();\r
+ gl.glDeleteTextures(1, buffer);\r
+ textures--;\r
+ }\r
+\r
+ public int getHeight () {\r
+ return texHeight;\r
+ }\r
+\r
+ public int getWidth () {\r
+ return texWidth;\r
+ }\r
+\r
+ public void draw (Pixmap pixmap, int x, int y) {\r
+ if (isManaged) throw new GdxRuntimeException("Can't draw to a managed texture");\r
+ BufferedImage image = (BufferedImage)pixmap.getNativePixmap();\r
+\r
+ int level = 0;\r
+ int height = image.getHeight();\r
+ int width = image.getWidth();\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ bind();\r
+ while (height >= 1 || width >= 1 && level < 4) {\r
+ ByteBuffer imageBuffer = toByteBuffer(image);\r
+ gl.glTexSubImage2D(GL10.GL_TEXTURE_2D, level, x, y, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, imageBuffer);\r
+ if (height == 1 || width == 1 || isMipMapped == false) break;\r
+\r
+ level++;\r
+ if (height > 1) height /= 2;\r
+ if (width > 1) width /= 2;\r
+\r
+ image = scaleDown(image);\r
+ }\r
+\r
+ }\r
+\r
+ public int getTextureObjectHandle () {\r
+ return textureID;\r
+ }\r
+\r
+ public void setWrap (TextureWrap x, TextureWrap y) {\r
+ bind();\r
+ GL20 gl = Gdx.graphics.getGL20();\r
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, x == TextureWrap.Repeat ? GL10.GL_REPEAT : GL10.GL_CLAMP_TO_EDGE);\r
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, y == TextureWrap.Repeat ? GL10.GL_REPEAT : GL10.GL_CLAMP_TO_EDGE);\r
+ }\r
+}\r
--- /dev/null
+/*
+ * Copyright (c) 2008-2010, Matthias Mann
+ *
+ * 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 Matthias Mann 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.
+ */
+
+package com.badlogic.gdx.backends.angle;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.zip.CRC32;
+import java.util.zip.DataFormatException;
+import java.util.zip.Inflater;
+
+/**
+ * Decodes A PNG directly a ByteBuffer.
+ *
+ * @author Matthias Mann
+ * @author Nathan Sweet <misc@n4te.com> (minor edits to avoid allocation)
+ */
+final class PNGDecoder {
+ public enum Format {
+ ALPHA(1, true), LUMINANCE(1, false), LUMINANCE_ALPHA(2, true), RGB(3, false), RGBA(4, true), BGRA(4, true), ABGR(4, true);
+
+ final int numComponents;
+ final boolean hasAlpha;
+
+ private Format (int numComponents, boolean hasAlpha) {
+ this.numComponents = numComponents;
+ this.hasAlpha = hasAlpha;
+ }
+
+ public int getNumComponents () {
+ return numComponents;
+ }
+
+ public boolean isHasAlpha () {
+ return hasAlpha;
+ }
+ }
+
+ private static final byte[] SIGNATURE = {(byte)137, 80, 78, 71, 13, 10, 26, 10};
+
+ private static final int IHDR = 0x49484452;
+ private static final int PLTE = 0x504C5445;
+ private static final int tRNS = 0x74524E53;
+ private static final int IDAT = 0x49444154;
+ private static final int IEND = 0x49454E44;
+
+ private static final byte COLOR_GREYSCALE = 0;
+ private static final byte COLOR_TRUECOLOR = 2;
+ private static final byte COLOR_INDEXED = 3;
+ private static final byte COLOR_GREYALPHA = 4;
+ private static final byte COLOR_TRUEALPHA = 6;
+
+ private InputStream input;
+ private final CRC32 crc;
+ private final byte[] buffer;
+
+ private int chunkLength;
+ private int chunkType;
+ private int chunkRemaining;
+
+ private int width;
+ private int height;
+ private int bitdepth;
+ private int colorType;
+ private int bytesPerPixel;
+ private byte[] palette;
+ private byte[] paletteA;
+ private byte[] transPixel;
+
+ public PNGDecoder () {
+ this.crc = new CRC32();
+ this.buffer = new byte[4096];
+ }
+
+ public void decodeHeader (InputStream input) throws IOException {
+ this.input = input;
+
+ readFully(buffer, 0, SIGNATURE.length);
+ if (!checkSignatur(buffer)) {
+ throw new IOException("Not a valid PNG file");
+ }
+
+ openChunk(IHDR);
+ readIHDR();
+ closeChunk();
+
+ searchIDAT:
+ for (;;) {
+ openChunk();
+ switch (chunkType) {
+ case IDAT:
+ break searchIDAT;
+ case PLTE:
+ readPLTE();
+ break;
+ case tRNS:
+ readtRNS();
+ break;
+ }
+ closeChunk();
+ }
+
+ if (colorType == COLOR_INDEXED && palette == null) {
+ throw new IOException("Missing PLTE chunk");
+ }
+ }
+
+ public int getHeight () {
+ return height;
+ }
+
+ public int getWidth () {
+ return width;
+ }
+
+ public boolean hasAlpha () {
+ return colorType == COLOR_TRUEALPHA || paletteA != null || transPixel != null;
+ }
+
+ public boolean isRGB () {
+ return colorType == COLOR_TRUEALPHA || colorType == COLOR_TRUECOLOR || colorType == COLOR_INDEXED;
+ }
+
+ /**
+ * Computes the implemented format conversion for the desired format.
+ *
+ * @param fmt the desired format
+ * @return format which best matches the desired format
+ * @throws UnsupportedOperationException if this PNG file can't be decoded
+ */
+ public Format decideTextureFormat (Format fmt) {
+ switch (colorType) {
+ case COLOR_TRUECOLOR:
+ switch (fmt) {
+ case ABGR:
+ case RGBA:
+ case BGRA:
+ case RGB:
+ return fmt;
+ default:
+ return Format.RGB;
+ }
+ case COLOR_TRUEALPHA:
+ switch (fmt) {
+ case ABGR:
+ case RGBA:
+ case BGRA:
+ case RGB:
+ return fmt;
+ default:
+ return Format.RGBA;
+ }
+ case COLOR_GREYSCALE:
+ switch (fmt) {
+ case LUMINANCE:
+ case ALPHA:
+ return fmt;
+ default:
+ return Format.LUMINANCE;
+ }
+ case COLOR_GREYALPHA:
+ return Format.LUMINANCE_ALPHA;
+ case COLOR_INDEXED:
+ switch (fmt) {
+ case ABGR:
+ case RGBA:
+ case BGRA:
+ return fmt;
+ default:
+ return Format.RGBA;
+ }
+ default:
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+ }
+
+ public void decode (ByteBuffer buffer, int stride, Format fmt) throws IOException {
+ final int offset = buffer.position();
+ final int lineSize = ((width * bitdepth + 7) / 8) * bytesPerPixel;
+ byte[] curLine = new byte[lineSize + 1];
+ byte[] prevLine = new byte[lineSize + 1];
+ byte[] palLine = (bitdepth < 8) ? new byte[width + 1] : null;
+
+ final Inflater inflater = new Inflater();
+ try {
+ for (int y = 0; y < height; y++) {
+ readChunkUnzip(inflater, curLine, 0, curLine.length);
+ unfilter(curLine, prevLine);
+
+ buffer.position(offset + y * stride);
+
+ switch (colorType) {
+ case COLOR_TRUECOLOR:
+ switch (fmt) {
+ case ABGR:
+ copyRGBtoABGR(buffer, curLine);
+ break;
+ case RGBA:
+ copyRGBtoRGBA(buffer, curLine);
+ break;
+ case BGRA:
+ copyRGBtoBGRA(buffer, curLine);
+ break;
+ case RGB:
+ copy(buffer, curLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported format for this image");
+ }
+ break;
+ case COLOR_TRUEALPHA:
+ switch (fmt) {
+ case ABGR:
+ copyRGBAtoABGR(buffer, curLine);
+ break;
+ case RGBA:
+ copy(buffer, curLine);
+ break;
+ case BGRA:
+ copyRGBAtoBGRA(buffer, curLine);
+ break;
+ case RGB:
+ copyRGBAtoRGB(buffer, curLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported format for this image");
+ }
+ break;
+ case COLOR_GREYSCALE:
+ switch (fmt) {
+ case LUMINANCE:
+ case ALPHA:
+ copy(buffer, curLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported format for this image");
+ }
+ break;
+ case COLOR_GREYALPHA:
+ switch (fmt) {
+ case LUMINANCE_ALPHA:
+ copy(buffer, curLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported format for this image");
+ }
+ break;
+ case COLOR_INDEXED:
+ switch (bitdepth) {
+ case 8:
+ palLine = curLine;
+ break;
+ case 4:
+ expand4(curLine, palLine);
+ break;
+ case 2:
+ expand2(curLine, palLine);
+ break;
+ case 1:
+ expand1(curLine, palLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported bitdepth for this image");
+ }
+ switch (fmt) {
+ case ABGR:
+ copyPALtoABGR(buffer, palLine);
+ break;
+ case RGBA:
+ copyPALtoRGBA(buffer, palLine);
+ break;
+ case BGRA:
+ copyPALtoBGRA(buffer, palLine);
+ break;
+ default:
+ throw new UnsupportedOperationException("Unsupported format for this image");
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ byte[] tmp = curLine;
+ curLine = prevLine;
+ prevLine = tmp;
+ }
+ } finally {
+ inflater.end();
+ }
+ }
+
+ private void copy (ByteBuffer buffer, byte[] curLine) {
+ buffer.put(curLine, 1, curLine.length - 1);
+ }
+
+ private void copyRGBtoABGR (ByteBuffer buffer, byte[] curLine) {
+ if (transPixel != null) {
+ byte tr = transPixel[1];
+ byte tg = transPixel[3];
+ byte tb = transPixel[5];
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ byte r = curLine[i];
+ byte g = curLine[i + 1];
+ byte b = curLine[i + 2];
+ byte a = (byte)0xFF;
+ if (r == tr && g == tg && b == tb) {
+ a = 0;
+ }
+ buffer.put(a).put(b).put(g).put(r);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ buffer.put((byte)0xFF).put(curLine[i + 2]).put(curLine[i + 1]).put(curLine[i]);
+ }
+ }
+ }
+
+ private void copyRGBtoRGBA (ByteBuffer buffer, byte[] curLine) {
+ if (transPixel != null) {
+ byte tr = transPixel[1];
+ byte tg = transPixel[3];
+ byte tb = transPixel[5];
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ byte r = curLine[i];
+ byte g = curLine[i + 1];
+ byte b = curLine[i + 2];
+ byte a = (byte)0xFF;
+ if (r == tr && g == tg && b == tb) {
+ a = 0;
+ }
+ buffer.put(r).put(g).put(b).put(a);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ buffer.put(curLine[i]).put(curLine[i + 1]).put(curLine[i + 2]).put((byte)0xFF);
+ }
+ }
+ }
+
+ private void copyRGBtoBGRA (ByteBuffer buffer, byte[] curLine) {
+ if (transPixel != null) {
+ byte tr = transPixel[1];
+ byte tg = transPixel[3];
+ byte tb = transPixel[5];
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ byte r = curLine[i];
+ byte g = curLine[i + 1];
+ byte b = curLine[i + 2];
+ byte a = (byte)0xFF;
+ if (r == tr && g == tg && b == tb) {
+ a = 0;
+ }
+ buffer.put(b).put(g).put(r).put(a);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 3) {
+ buffer.put(curLine[i + 2]).put(curLine[i + 1]).put(curLine[i]).put((byte)0xFF);
+ }
+ }
+ }
+
+ private void copyRGBAtoABGR (ByteBuffer buffer, byte[] curLine) {
+ for (int i = 1, n = curLine.length; i < n; i += 4) {
+ buffer.put(curLine[i + 3]).put(curLine[i + 2]).put(curLine[i + 1]).put(curLine[i]);
+ }
+ }
+
+ private void copyRGBAtoBGRA (ByteBuffer buffer, byte[] curLine) {
+ for (int i = 1, n = curLine.length; i < n; i += 4) {
+ buffer.put(curLine[i + 2]).put(curLine[i + 1]).put(curLine[i + 0]).put(curLine[i + 3]);
+ }
+ }
+
+ private void copyRGBAtoRGB (ByteBuffer buffer, byte[] curLine) {
+ for (int i = 1, n = curLine.length; i < n; i += 4) {
+ buffer.put(curLine[i]).put(curLine[i + 1]).put(curLine[i + 2]);
+ }
+ }
+
+ private void copyPALtoABGR (ByteBuffer buffer, byte[] curLine) {
+ if (paletteA != null) {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = paletteA[idx];
+ buffer.put(a).put(b).put(g).put(r);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = (byte)0xFF;
+ buffer.put(a).put(b).put(g).put(r);
+ }
+ }
+ }
+
+ private void copyPALtoRGBA (ByteBuffer buffer, byte[] curLine) {
+ if (paletteA != null) {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = paletteA[idx];
+ buffer.put(r).put(g).put(b).put(a);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = (byte)0xFF;
+ buffer.put(r).put(g).put(b).put(a);
+ }
+ }
+ }
+
+ private void copyPALtoBGRA (ByteBuffer buffer, byte[] curLine) {
+ if (paletteA != null) {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = paletteA[idx];
+ buffer.put(b).put(g).put(r).put(a);
+ }
+ } else {
+ for (int i = 1, n = curLine.length; i < n; i += 1) {
+ int idx = curLine[i] & 255;
+ byte r = palette[idx * 3 + 0];
+ byte g = palette[idx * 3 + 1];
+ byte b = palette[idx * 3 + 2];
+ byte a = (byte)0xFF;
+ buffer.put(b).put(g).put(r).put(a);
+ }
+ }
+ }
+
+ private void expand4 (byte[] src, byte[] dst) {
+ for (int i = 1, n = dst.length; i < n; i += 2) {
+ int val = src[1 + (i >> 1)] & 255;
+ switch (n - i) {
+ default:
+ dst[i + 1] = (byte)(val & 15);
+ case 1:
+ dst[i] = (byte)(val >> 4);
+ }
+ }
+ }
+
+ private void expand2 (byte[] src, byte[] dst) {
+ for (int i = 1, n = dst.length; i < n; i += 4) {
+ int val = src[1 + (i >> 2)] & 255;
+ switch (n - i) {
+ default:
+ dst[i + 3] = (byte)((val) & 3);
+ case 3:
+ dst[i + 2] = (byte)((val >> 2) & 3);
+ case 2:
+ dst[i + 1] = (byte)((val >> 4) & 3);
+ case 1:
+ dst[i] = (byte)((val >> 6));
+ }
+ }
+ }
+
+ private void expand1 (byte[] src, byte[] dst) {
+ for (int i = 1, n = dst.length; i < n; i += 8) {
+ int val = src[1 + (i >> 3)] & 255;
+ switch (n - i) {
+ default:
+ dst[i + 7] = (byte)((val) & 1);
+ case 7:
+ dst[i + 6] = (byte)((val >> 1) & 1);
+ case 6:
+ dst[i + 5] = (byte)((val >> 2) & 1);
+ case 5:
+ dst[i + 4] = (byte)((val >> 3) & 1);
+ case 4:
+ dst[i + 3] = (byte)((val >> 4) & 1);
+ case 3:
+ dst[i + 2] = (byte)((val >> 5) & 1);
+ case 2:
+ dst[i + 1] = (byte)((val >> 6) & 1);
+ case 1:
+ dst[i] = (byte)((val >> 7));
+ }
+ }
+ }
+
+ private void unfilter (byte[] curLine, byte[] prevLine) throws IOException {
+ switch (curLine[0]) {
+ case 0: // none
+ break;
+ case 1:
+ unfilterSub(curLine);
+ break;
+ case 2:
+ unfilterUp(curLine, prevLine);
+ break;
+ case 3:
+ unfilterAverage(curLine, prevLine);
+ break;
+ case 4:
+ unfilterPaeth(curLine, prevLine);
+ break;
+ default:
+ throw new IOException("invalide filter type in scanline: " + curLine[0]);
+ }
+ }
+
+ private void unfilterSub (byte[] curLine) {
+ final int bpp = this.bytesPerPixel;
+ for (int i = bpp + 1, n = curLine.length; i < n; ++i) {
+ curLine[i] += curLine[i - bpp];
+ }
+ }
+
+ private void unfilterUp (byte[] curLine, byte[] prevLine) {
+ for (int i = 1, n = curLine.length; i < n; ++i) {
+ curLine[i] += prevLine[i];
+ }
+ }
+
+ private void unfilterAverage (byte[] curLine, byte[] prevLine) {
+ final int bpp = this.bytesPerPixel;
+
+ int i;
+ for (i = 1; i <= bpp; ++i) {
+ curLine[i] += (byte)((prevLine[i] & 0xFF) >>> 1);
+ }
+ for (int n = curLine.length; i < n; ++i) {
+ curLine[i] += (byte)(((prevLine[i] & 0xFF) + (curLine[i - bpp] & 0xFF)) >>> 1);
+ }
+ }
+
+ private void unfilterPaeth (byte[] curLine, byte[] prevLine) {
+ final int bpp = this.bytesPerPixel;
+
+ int i;
+ for (i = 1; i <= bpp; ++i) {
+ curLine[i] += prevLine[i];
+ }
+ for (int n = curLine.length; i < n; ++i) {
+ int a = curLine[i - bpp] & 255;
+ int b = prevLine[i] & 255;
+ int c = prevLine[i - bpp] & 255;
+ int p = a + b - c;
+ int pa = p - a;
+ if (pa < 0) pa = -pa;
+ int pb = p - b;
+ if (pb < 0) pb = -pb;
+ int pc = p - c;
+ if (pc < 0) pc = -pc;
+ if (pa <= pb && pa <= pc)
+ c = a;
+ else if (pb <= pc) c = b;
+ curLine[i] += (byte)c;
+ }
+ }
+
+ private void readIHDR () throws IOException {
+ checkChunkLength(13);
+ readChunk(buffer, 0, 13);
+ width = readInt(buffer, 0);
+ height = readInt(buffer, 4);
+ bitdepth = buffer[8] & 255;
+ colorType = buffer[9] & 255;
+
+ switch (colorType) {
+ case COLOR_GREYSCALE:
+ if (bitdepth != 8) {
+ throw new IOException("Unsupported bit depth: " + bitdepth);
+ }
+ bytesPerPixel = 1;
+ break;
+ case COLOR_GREYALPHA:
+ if (bitdepth != 8) {
+ throw new IOException("Unsupported bit depth: " + bitdepth);
+ }
+ bytesPerPixel = 2;
+ break;
+ case COLOR_TRUECOLOR:
+ if (bitdepth != 8) {
+ throw new IOException("Unsupported bit depth: " + bitdepth);
+ }
+ bytesPerPixel = 3;
+ break;
+ case COLOR_TRUEALPHA:
+ if (bitdepth != 8) {
+ throw new IOException("Unsupported bit depth: " + bitdepth);
+ }
+ bytesPerPixel = 4;
+ break;
+ case COLOR_INDEXED:
+ switch (bitdepth) {
+ case 8:
+ case 4:
+ case 2:
+ case 1:
+ bytesPerPixel = 1;
+ break;
+ default:
+ throw new IOException("Unsupported bit depth: " + bitdepth);
+ }
+ break;
+ default:
+ throw new IOException("unsupported color format: " + colorType);
+ }
+
+ if (buffer[10] != 0) {
+ throw new IOException("unsupported compression method");
+ }
+ if (buffer[11] != 0) {
+ throw new IOException("unsupported filtering method");
+ }
+ if (buffer[12] != 0) {
+ throw new IOException("unsupported interlace method");
+ }
+ }
+
+ private void readPLTE () throws IOException {
+ int paletteEntries = chunkLength / 3;
+ if (paletteEntries < 1 || paletteEntries > 256 || (chunkLength % 3) != 0) {
+ throw new IOException("PLTE chunk has wrong length");
+ }
+ palette = new byte[paletteEntries * 3];
+ readChunk(palette, 0, palette.length);
+ }
+
+ private void readtRNS () throws IOException {
+ switch (colorType) {
+ case COLOR_GREYSCALE:
+ checkChunkLength(2);
+ transPixel = new byte[2];
+ readChunk(transPixel, 0, 2);
+ break;
+ case COLOR_TRUECOLOR:
+ checkChunkLength(6);
+ transPixel = new byte[6];
+ readChunk(transPixel, 0, 6);
+ break;
+ case COLOR_INDEXED:
+ if (palette == null) {
+ throw new IOException("tRNS chunk without PLTE chunk");
+ }
+ paletteA = new byte[palette.length / 3];
+ Arrays.fill(paletteA, (byte)0xFF);
+ readChunk(paletteA, 0, paletteA.length);
+ break;
+ default:
+ // just ignore it
+ }
+ }
+
+ private void closeChunk () throws IOException {
+ if (chunkRemaining > 0) {
+ // just skip the rest and the CRC
+ skip(chunkRemaining + 4);
+ } else {
+ readFully(buffer, 0, 4);
+ int expectedCrc = readInt(buffer, 0);
+ int computedCrc = (int)crc.getValue();
+ if (computedCrc != expectedCrc) {
+ throw new IOException("Invalid CRC");
+ }
+ }
+ chunkRemaining = 0;
+ chunkLength = 0;
+ chunkType = 0;
+ }
+
+ private void openChunk () throws IOException {
+ readFully(buffer, 0, 8);
+ chunkLength = readInt(buffer, 0);
+ chunkType = readInt(buffer, 4);
+ chunkRemaining = chunkLength;
+ crc.reset();
+ crc.update(buffer, 4, 4); // only chunkType
+ }
+
+ private void openChunk (int expected) throws IOException {
+ openChunk();
+ if (chunkType != expected) {
+ throw new IOException("Expected chunk: " + Integer.toHexString(expected));
+ }
+ }
+
+ private void checkChunkLength (int expected) throws IOException {
+ if (chunkLength != expected) {
+ throw new IOException("Chunk has wrong size");
+ }
+ }
+
+ private int readChunk (byte[] buffer, int offset, int length) throws IOException {
+ if (length > chunkRemaining) {
+ length = chunkRemaining;
+ }
+ readFully(buffer, offset, length);
+ crc.update(buffer, offset, length);
+ chunkRemaining -= length;
+ return length;
+ }
+
+ private void refillInflater (Inflater inflater) throws IOException {
+ while (chunkRemaining == 0) {
+ closeChunk();
+ openChunk(IDAT);
+ }
+ int read = readChunk(buffer, 0, buffer.length);
+ inflater.setInput(buffer, 0, read);
+ }
+
+ private void readChunkUnzip (Inflater inflater, byte[] buffer, int offset, int length) throws IOException {
+ assert (buffer != this.buffer);
+ try {
+ do {
+ int read = inflater.inflate(buffer, offset, length);
+ if (read <= 0) {
+ if (inflater.finished()) {
+ throw new EOFException();
+ }
+ if (inflater.needsInput()) {
+ refillInflater(inflater);
+ } else {
+ throw new IOException("Can't inflate " + length + " bytes");
+ }
+ } else {
+ offset += read;
+ length -= read;
+ }
+ } while (length > 0);
+ } catch (DataFormatException ex) {
+ throw (IOException)(new IOException("inflate error").initCause(ex));
+ }
+ }
+
+ private void readFully (byte[] buffer, int offset, int length) throws IOException {
+ do {
+ int read = input.read(buffer, offset, length);
+ if (read < 0) {
+ throw new EOFException();
+ }
+ offset += read;
+ length -= read;
+ } while (length > 0);
+ }
+
+ private int readInt (byte[] buffer, int offset) {
+ return ((buffer[offset]) << 24) | ((buffer[offset + 1] & 255) << 16) | ((buffer[offset + 2] & 255) << 8)
+ | ((buffer[offset + 3] & 255));
+ }
+
+ private void skip (long amount) throws IOException {
+ while (amount > 0) {
+ long skipped = input.skip(amount);
+ if (skipped < 0) {
+ throw new EOFException();
+ }
+ amount -= skipped;
+ }
+ }
+
+ private static boolean checkSignatur (byte[] buffer) {
+ for (int i = 0; i < SIGNATURE.length; i++) {
+ if (buffer[i] != SIGNATURE[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+}