/** * Copyright 2008 - 2015 The Loon Game Engine Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.5 */ package loon.jni; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import loon.Support; import loon.canvas.LColor; public final class NativeSupport implements Support { @Override public void makeBuffer(byte[] data, int size, int tag) { for (int i = 0; i < size; i++) { data[i] ^= tag; } } @Override public void copy(float[] src, Buffer dst, int numFloats) { copy(src, dst, 0, numFloats); } @Override public void copy(float[] src, Buffer dst, int offset, int numFloats) { putBuffer(dst, src, offset, numFloats); } @Override public IntBuffer newIntBuffer(final int[] src) { if (src == null) { return null; } int size = src.length; IntBuffer buffer = newIntBuffer(size); copy(src, 0, buffer, size); return buffer; } @Override public FloatBuffer newFloatBuffer(float[] src, int offset, int numFloats) { FloatBuffer buffer = newFloatBuffer(numFloats); copy(src, buffer, offset, numFloats); return buffer; } @Override public void copy(byte[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } @Override public void copy(short[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } public void copy(char[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } @Override public void copy(int[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } public void copy(long[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } @Override public void copy(float[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } public void copy(double[] src, int srcOffset, Buffer dst, int numElements) { putBuffer(dst, src, srcOffset, numElements); } private void putBuffer(Buffer dst, Object src, int offset, int numFloats) { if (dst instanceof ByteBuffer) { if (src instanceof byte[]) { ByteBuffer byteBuffer = (ByteBuffer) dst; int oldPosition = byteBuffer.position(); byteBuffer.put((byte[]) src, offset, numFloats); byteBuffer.position(oldPosition); byteBuffer.limit(oldPosition + numFloats); } else { FloatBuffer floatBuffer = asFloatBuffer(dst); floatBuffer.clear(); dst.position(0); floatBuffer.put((float[]) src, offset, numFloats); dst.position(0); dst.limit(numFloats << 2); } } else if (dst instanceof ShortBuffer) { ShortBuffer buffer = (ShortBuffer) dst; int oldPosition = buffer.position(); buffer.put((short[]) src, offset, numFloats); buffer.position(oldPosition); buffer.limit(oldPosition + numFloats); } else if (dst instanceof IntBuffer) { IntBuffer buffer = (IntBuffer) dst; int[] source = (int[]) src; int oldPosition = buffer.position(); buffer.put(source, offset, numFloats); buffer.position(oldPosition); buffer.limit(oldPosition + numFloats); } else if (dst instanceof FloatBuffer) { FloatBuffer floatBuffer = asFloatBuffer(dst); floatBuffer.clear(); dst.position(0); floatBuffer.put((float[]) src, offset, numFloats); dst.position(0); dst.limit(numFloats); } else { throw new RuntimeException("Can't copy to a " + dst.getClass().getName() + " instance"); } dst.position(0); } private final static FloatBuffer asFloatBuffer(final Buffer data) { FloatBuffer buffer = null; if (data instanceof ByteBuffer) buffer = ((ByteBuffer) data).asFloatBuffer(); else if (data instanceof FloatBuffer) buffer = (FloatBuffer) data; if (buffer == null) throw new RuntimeException( "data must be a ByteBuffer or FloatBuffer"); return buffer; } @Override public ByteBuffer replaceBytes(ByteBuffer dst, float[] src) { int size = src.length; dst.clear(); copy(src, 0, dst, size); dst.position(0); return dst; } @Override public FloatBuffer replaceFloats(FloatBuffer dst, float[] src) { int size = src.length; dst.clear(); copy(src, 0, dst, size); dst.position(0); return dst; } @Override public ByteBuffer getByteBuffer(byte[] bytes) { ByteBuffer buffer = newByteBuffer(bytes.length).put(bytes); buffer.position(0); return buffer; } @Override public FloatBuffer getFloatBuffer(float[] floats) { FloatBuffer buffer = newFloatBuffer(floats.length).put(floats); buffer.position(0); return buffer; } @Override public ByteBuffer newByteBuffer(int numBytes) { ByteBuffer buffer = ByteBuffer.allocateDirect(numBytes); buffer.order(ByteOrder.nativeOrder()); return buffer; } @Override public FloatBuffer newFloatBuffer(int numFloats) { ByteBuffer buffer = ByteBuffer.allocateDirect(numFloats * 4); buffer.order(ByteOrder.nativeOrder()); return buffer.asFloatBuffer(); } @Override public ShortBuffer newShortBuffer(int numShorts) { ByteBuffer buffer = ByteBuffer.allocateDirect(numShorts * 2); buffer.order(ByteOrder.nativeOrder()); return buffer.asShortBuffer(); } @Override public IntBuffer newIntBuffer(int numInts) { ByteBuffer buffer = ByteBuffer.allocateDirect(numInts * 4); buffer.order(ByteOrder.nativeOrder()); return buffer.asIntBuffer(); } public void put(final Buffer buffer, final float[] source, final int offset, final int length) { putBuffer(buffer, source, offset, length); } private int allocatedUnsafe = 0; @Override public int getAllocatedBytesUnsafe() { return allocatedUnsafe; } @Override public void disposeUnsafeByteBuffer(ByteBuffer buffer) { freeMemory(buffer); } public ByteBuffer newUnsafeByteBuffer(int numBytes) { return newByteBuffer(numBytes); } @Override public ByteBuffer allocateDirect(final int capacity) { return ByteBuffer.allocateDirect(capacity); } private void freeMemory(Buffer buffer) { buffer.clear(); buffer = null; } @Override public void clear(Buffer buffer) { buffer.clear(); } @Override public final void filterColor(int maxPixel, int pixelStart, int pixelEnd, int[] src, int[] dst, int[] colors, int c1, int c2) { final int length = src.length; if (pixelStart < pixelEnd) { final int start = pixelStart + 1; final int end = pixelEnd + 1; if (end > maxPixel) { return; } for (int i = 0; i < length; i++) { if (dst[i] != 0xffffff) { for (int pixIndex = start; pixIndex < end; pixIndex++) { if (colors[pixIndex] == src[i]) { dst[i] = 0xffffff; } else if (src[i] == c1) { dst[i] = 0xffffff; } } } } } else { final int start = pixelEnd - 1; final int end = pixelStart; if (start < 0) { return; } for (int i = 0; i < length; i++) { if (dst[i] != 0xffffff) { for (int pixIndex = start; pixIndex < end; pixIndex++) { if (colors[pixIndex] == src[i]) { dst[i] = 0xffffff; } else if (src[i] == c2) { dst[i] = 0xffffff; } } } } } } @Override public void filterFractions(int size, float[] fractions, int width, int height, int[] pixels, int numElements) { int x, y; int idx = 0; for (int j = 0; j < size; j++) { idx = j * numElements; if (fractions[idx + 4] != 0xffffff) { if (fractions[idx + 5] <= 0) { fractions[idx + 0] += fractions[idx + 2]; fractions[idx + 1] += fractions[idx + 3]; fractions[idx + 3] += 0.1; } else { fractions[idx + 5]--; } x = (int) fractions[idx + 0]; y = (int) fractions[idx + 1]; if (x > -1 && y > -1 && x < width && y < height) { pixels[x + y * width] = (int) fractions[idx + 4]; } } } } public final int M00 = 0; public final int M01 = 4; public final int M02 = 8; public final int M03 = 12; public final int M10 = 1; public final int M11 = 5; public final int M12 = 9; public final int M13 = 13; public final int M20 = 2; public final int M21 = 6; public final int M22 = 10; public final int M23 = 14; public final int M30 = 3; public final int M31 = 7; public final int M32 = 11; public final int M33 = 15; @Override public void mul(float[] mata, float[] matb) { float[] tmp = new float[16]; tmp[M00] = mata[M00] * matb[M00] + mata[M01] * matb[M10] + mata[M02] * matb[M20] + mata[M03] * matb[M30]; tmp[M01] = mata[M00] * matb[M01] + mata[M01] * matb[M11] + mata[M02] * matb[M21] + mata[M03] * matb[M31]; tmp[M02] = mata[M00] * matb[M02] + mata[M01] * matb[M12] + mata[M02] * matb[M22] + mata[M03] * matb[M32]; tmp[M03] = mata[M00] * matb[M03] + mata[M01] * matb[M13] + mata[M02] * matb[M23] + mata[M03] * matb[M33]; tmp[M10] = mata[M10] * matb[M00] + mata[M11] * matb[M10] + mata[M12] * matb[M20] + mata[M13] * matb[M30]; tmp[M11] = mata[M10] * matb[M01] + mata[M11] * matb[M11] + mata[M12] * matb[M21] + mata[M13] * matb[M31]; tmp[M12] = mata[M10] * matb[M02] + mata[M11] * matb[M12] + mata[M12] * matb[M22] + mata[M13] * matb[M32]; tmp[M13] = mata[M10] * matb[M03] + mata[M11] * matb[M13] + mata[M12] * matb[M23] + mata[M13] * matb[M33]; tmp[M20] = mata[M20] * matb[M00] + mata[M21] * matb[M10] + mata[M22] * matb[M20] + mata[M23] * matb[M30]; tmp[M21] = mata[M20] * matb[M01] + mata[M21] * matb[M11] + mata[M22] * matb[M21] + mata[M23] * matb[M31]; tmp[M22] = mata[M20] * matb[M02] + mata[M21] * matb[M12] + mata[M22] * matb[M22] + mata[M23] * matb[M32]; tmp[M23] = mata[M20] * matb[M03] + mata[M21] * matb[M13] + mata[M22] * matb[M23] + mata[M23] * matb[M33]; tmp[M30] = mata[M30] * matb[M00] + mata[M31] * matb[M10] + mata[M32] * matb[M20] + mata[M33] * matb[M30]; tmp[M31] = mata[M30] * matb[M01] + mata[M31] * matb[M11] + mata[M32] * matb[M21] + mata[M33] * matb[M31]; tmp[M32] = mata[M30] * matb[M02] + mata[M31] * matb[M12] + mata[M32] * matb[M22] + mata[M33] * matb[M32]; tmp[M33] = mata[M30] * matb[M03] + mata[M31] * matb[M13] + mata[M32] * matb[M23] + mata[M33] * matb[M33]; System.arraycopy(tmp, 0, mata, 0, 16); } @Override public void mulVec(float[] mat, float[] vec) { float x = vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02] + mat[M03]; float y = vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12] + mat[M13]; float z = vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22] + mat[M23]; vec[0] = x; vec[1] = y; vec[2] = z; } @Override public void mulVec(float[] mat, float[] vecs, int offset, int numVecs, int stride) { for (int i = 0; i < numVecs; i++) { float[] vecPtr = new float[stride]; System.arraycopy(vecs, offset, vecPtr, 0, stride); mulVec(mat, vecPtr); } } @Override public void prj(float[] mat, float[] vec) { float inv_w = 1.0f / (vec[0] * mat[M30] + vec[1] * mat[M31] + vec[2] * mat[M32] + mat[M33]); float x = (vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02] + mat[M03]) * inv_w; float y = (vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12] + mat[M13]) * inv_w; float z = (vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22] + mat[M23]) * inv_w; vec[0] = x; vec[1] = y; vec[2] = z; } @Override public void prj(float[] mat, float[] vecs, int offset, int numVecs, int stride) { for (int i = 0; i < numVecs; i++) { float[] vecPtr = new float[stride]; System.arraycopy(vecs, offset, vecPtr, 0, stride); prj(mat, vecPtr); } } @Override public void rot(float[] mat, float[] vec) { float x = vec[0] * mat[M00] + vec[1] * mat[M01] + vec[2] * mat[M02]; float y = vec[0] * mat[M10] + vec[1] * mat[M11] + vec[2] * mat[M12]; float z = vec[0] * mat[M20] + vec[1] * mat[M21] + vec[2] * mat[M22]; vec[0] = x; vec[1] = y; vec[2] = z; } @Override public void rot(float[] mat, float[] vecs, int offset, int numVecs, int stride) { for (int i = 0; i < numVecs; i++) { float[] vecPtr = new float[stride]; System.arraycopy(vecs, offset, vecPtr, 0, stride); rot(mat, vecPtr); } } @Override public boolean inv(float[] values) { float[] tmp = new float[16]; float l_det = det(values); if (l_det == 0) return false; tmp[M00] = values[M12] * values[M23] * values[M31] - values[M13] * values[M22] * values[M31] + values[M13] * values[M21] * values[M32] - values[M11] * values[M23] * values[M32] - values[M12] * values[M21] * values[M33] + values[M11] * values[M22] * values[M33]; tmp[M01] = values[M03] * values[M22] * values[M31] - values[M02] * values[M23] * values[M31] - values[M03] * values[M21] * values[M32] + values[M01] * values[M23] * values[M32] + values[M02] * values[M21] * values[M33] - values[M01] * values[M22] * values[M33]; tmp[M02] = values[M02] * values[M13] * values[M31] - values[M03] * values[M12] * values[M31] + values[M03] * values[M11] * values[M32] - values[M01] * values[M13] * values[M32] - values[M02] * values[M11] * values[M33] + values[M01] * values[M12] * values[M33]; tmp[M03] = values[M03] * values[M12] * values[M21] - values[M02] * values[M13] * values[M21] - values[M03] * values[M11] * values[M22] + values[M01] * values[M13] * values[M22] + values[M02] * values[M11] * values[M23] - values[M01] * values[M12] * values[M23]; tmp[M10] = values[M13] * values[M22] * values[M30] - values[M12] * values[M23] * values[M30] - values[M13] * values[M20] * values[M32] + values[M10] * values[M23] * values[M32] + values[M12] * values[M20] * values[M33] - values[M10] * values[M22] * values[M33]; tmp[M11] = values[M02] * values[M23] * values[M30] - values[M03] * values[M22] * values[M30] + values[M03] * values[M20] * values[M32] - values[M00] * values[M23] * values[M32] - values[M02] * values[M20] * values[M33] + values[M00] * values[M22] * values[M33]; tmp[M12] = values[M03] * values[M12] * values[M30] - values[M02] * values[M13] * values[M30] - values[M03] * values[M10] * values[M32] + values[M00] * values[M13] * values[M32] + values[M02] * values[M10] * values[M33] - values[M00] * values[M12] * values[M33]; tmp[M13] = values[M02] * values[M13] * values[M20] - values[M03] * values[M12] * values[M20] + values[M03] * values[M10] * values[M22] - values[M00] * values[M13] * values[M22] - values[M02] * values[M10] * values[M23] + values[M00] * values[M12] * values[M23]; tmp[M20] = values[M11] * values[M23] * values[M30] - values[M13] * values[M21] * values[M30] + values[M13] * values[M20] * values[M31] - values[M10] * values[M23] * values[M31] - values[M11] * values[M20] * values[M33] + values[M10] * values[M21] * values[M33]; tmp[M21] = values[M03] * values[M21] * values[M30] - values[M01] * values[M23] * values[M30] - values[M03] * values[M20] * values[M31] + values[M00] * values[M23] * values[M31] + values[M01] * values[M20] * values[M33] - values[M00] * values[M21] * values[M33]; tmp[M22] = values[M01] * values[M13] * values[M30] - values[M03] * values[M11] * values[M30] + values[M03] * values[M10] * values[M31] - values[M00] * values[M13] * values[M31] - values[M01] * values[M10] * values[M33] + values[M00] * values[M11] * values[M33]; tmp[M23] = values[M03] * values[M11] * values[M20] - values[M01] * values[M13] * values[M20] - values[M03] * values[M10] * values[M21] + values[M00] * values[M13] * values[M21] + values[M01] * values[M10] * values[M23] - values[M00] * values[M11] * values[M23]; tmp[M30] = values[M12] * values[M21] * values[M30] - values[M11] * values[M22] * values[M30] - values[M12] * values[M20] * values[M31] + values[M10] * values[M22] * values[M31] + values[M11] * values[M20] * values[M32] - values[M10] * values[M21] * values[M32]; tmp[M31] = values[M01] * values[M22] * values[M30] - values[M02] * values[M21] * values[M30] + values[M02] * values[M20] * values[M31] - values[M00] * values[M22] * values[M31] - values[M01] * values[M20] * values[M32] + values[M00] * values[M21] * values[M32]; tmp[M32] = values[M02] * values[M11] * values[M30] - values[M01] * values[M12] * values[M30] - values[M02] * values[M10] * values[M31] + values[M00] * values[M12] * values[M31] + values[M01] * values[M10] * values[M32] - values[M00] * values[M11] * values[M32]; tmp[M33] = values[M01] * values[M12] * values[M20] - values[M02] * values[M11] * values[M20] + values[M02] * values[M10] * values[M21] - values[M00] * values[M12] * values[M21] - values[M01] * values[M10] * values[M22] + values[M00] * values[M11] * values[M22]; float inv_det = 1.0f / l_det; values[M00] = tmp[M00] * inv_det; values[M01] = tmp[M01] * inv_det; values[M02] = tmp[M02] * inv_det; values[M03] = tmp[M03] * inv_det; values[M10] = tmp[M10] * inv_det; values[M11] = tmp[M11] * inv_det; values[M12] = tmp[M12] * inv_det; values[M13] = tmp[M13] * inv_det; values[M20] = tmp[M20] * inv_det; values[M21] = tmp[M21] * inv_det; values[M22] = tmp[M22] * inv_det; values[M23] = tmp[M23] * inv_det; values[M30] = tmp[M30] * inv_det; values[M31] = tmp[M31] * inv_det; values[M32] = tmp[M32] * inv_det; values[M33] = tmp[M33] * inv_det; return true; } @Override public float det(float[] values) { return values[M30] * values[M21] * values[M12] * values[M03] - values[M20] * values[M31] * values[M12] * values[M03] - values[M30] * values[M11] * values[M22] * values[M03] + values[M10] * values[M31] * values[M22] * values[M03] + values[M20] * values[M11] * values[M32] * values[M03] - values[M10] * values[M21] * values[M32] * values[M03] - values[M30] * values[M21] * values[M02] * values[M13] + values[M20] * values[M31] * values[M02] * values[M13] + values[M30] * values[M01] * values[M22] * values[M13] - values[M00] * values[M31] * values[M22] * values[M13] - values[M20] * values[M01] * values[M32] * values[M13] + values[M00] * values[M21] * values[M32] * values[M13] + values[M30] * values[M11] * values[M02] * values[M23] - values[M10] * values[M31] * values[M02] * values[M23] - values[M30] * values[M01] * values[M12] * values[M23] + values[M00] * values[M31] * values[M12] * values[M23] + values[M10] * values[M01] * values[M32] * values[M23] - values[M00] * values[M11] * values[M32] * values[M23] - values[M20] * values[M11] * values[M02] * values[M33] + values[M10] * values[M21] * values[M02] * values[M33] + values[M20] * values[M01] * values[M12] * values[M33] - values[M00] * values[M21] * values[M12] * values[M33] - values[M10] * values[M01] * values[M22] * values[M33] + values[M00] * values[M11] * values[M22] * values[M33]; } @Override public int[] toColorKey(int[] buffer, int colorKey) { int size = buffer.length; for (int i = 0; i < size; i++) { int pixel = buffer[i]; if (pixel == colorKey) { buffer[i] = 0x00FFFFFF; } } return buffer; } @Override public int[] toColorKeys(int[] buffer, int[] colors) { int length = colors.length; int size = buffer.length; for (int n = 0; n < length; n++) { for (int i = 0; i < size; i++) { int pixel = buffer[i]; if (pixel == colors[n]) { buffer[i] = 0x00FFFFFF; } } } return buffer; } @Override public int[] toColorKeyLimit(int[] buffer, int start, int end) { int sred = LColor.getRed(start); int sgreen = LColor.getGreen(start); int sblue = LColor.getBlue(start); int ered = LColor.getRed(end); int egreen = LColor.getGreen(end); int eblue = LColor.getBlue(end); int size = buffer.length; for (int i = 0; i < size; i++) { int pixel = buffer[i]; int r = LColor.getRed(pixel); int g = LColor.getGreen(pixel); int b = LColor.getBlue(pixel); if ((r >= sred && g >= sgreen && b >= sblue) && (r <= ered && g <= egreen && b <= eblue)) { buffer[i] = 0x00FFFFFF; } } return buffer; } @Override public int[] toGray(int[] buffer, int w, int h) { int size = w * h; int[] newResult = new int[size]; System.arraycopy(buffer, 0, newResult, 0, size); int alpha = 0xFF << 24; for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { int idx = w * i + j; int color = newResult[idx]; if (color != 0x00FFFFFF) { int red = ((color & 0x00FF0000) >> 16); int green = ((color & 0x0000FF00) >> 8); int blue = color & 0x000000FF; color = (red + green + blue) / 3; color = alpha | (color << 16) | (color << 8) | color; newResult[idx] = color; } } } return newResult; } @Override public boolean isNative() { return false; } @Override public void openNative() { // noop } @Override public void closeNative() { // noop } }