Home | History | Annotate | Download | only in g2d
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.graphics.g2d;
     18 
     19 import java.io.ByteArrayOutputStream;
     20 import java.io.IOException;
     21 import java.io.InputStream;
     22 import java.nio.ByteBuffer;
     23 
     24 import com.badlogic.gdx.graphics.GL20;
     25 import com.badlogic.gdx.utils.Disposable;
     26 import com.badlogic.gdx.utils.GdxRuntimeException;
     27 
     28 /** @author mzechner */
     29 public class Gdx2DPixmap implements Disposable {
     30 	public static final int GDX2D_FORMAT_ALPHA = 1;
     31 	public static final int GDX2D_FORMAT_LUMINANCE_ALPHA = 2;
     32 	public static final int GDX2D_FORMAT_RGB888 = 3;
     33 	public static final int GDX2D_FORMAT_RGBA8888 = 4;
     34 	public static final int GDX2D_FORMAT_RGB565 = 5;
     35 	public static final int GDX2D_FORMAT_RGBA4444 = 6;
     36 
     37 	public static final int GDX2D_SCALE_NEAREST = 0;
     38 	public static final int GDX2D_SCALE_LINEAR = 1;
     39 
     40 	public static final int GDX2D_BLEND_NONE = 0;
     41 	public static final int GDX2D_BLEND_SRC_OVER = 1;
     42 
     43 	public static int toGlFormat (int format) {
     44 		switch (format) {
     45 		case GDX2D_FORMAT_ALPHA:
     46 			return GL20.GL_ALPHA;
     47 		case GDX2D_FORMAT_LUMINANCE_ALPHA:
     48 			return GL20.GL_LUMINANCE_ALPHA;
     49 		case GDX2D_FORMAT_RGB888:
     50 		case GDX2D_FORMAT_RGB565:
     51 			return GL20.GL_RGB;
     52 		case GDX2D_FORMAT_RGBA8888:
     53 		case GDX2D_FORMAT_RGBA4444:
     54 			return GL20.GL_RGBA;
     55 		default:
     56 			throw new GdxRuntimeException("unknown format: " + format);
     57 		}
     58 	}
     59 
     60 	public static int toGlType (int format) {
     61 		switch (format) {
     62 		case GDX2D_FORMAT_ALPHA:
     63 		case GDX2D_FORMAT_LUMINANCE_ALPHA:
     64 		case GDX2D_FORMAT_RGB888:
     65 		case GDX2D_FORMAT_RGBA8888:
     66 			return GL20.GL_UNSIGNED_BYTE;
     67 		case GDX2D_FORMAT_RGB565:
     68 			return GL20.GL_UNSIGNED_SHORT_5_6_5;
     69 		case GDX2D_FORMAT_RGBA4444:
     70 			return GL20.GL_UNSIGNED_SHORT_4_4_4_4;
     71 		default:
     72 			throw new GdxRuntimeException("unknown format: " + format);
     73 		}
     74 	}
     75 
     76 	long basePtr;
     77 	int width;
     78 	int height;
     79 	int format;
     80 	ByteBuffer pixelPtr;
     81 	long[] nativeData = new long[4];
     82 
     83 	static {
     84 		setBlend(GDX2D_BLEND_SRC_OVER);
     85 		setScale(GDX2D_SCALE_LINEAR);
     86 	}
     87 
     88 	public Gdx2DPixmap (byte[] encodedData, int offset, int len, int requestedFormat) throws IOException {
     89 		pixelPtr = load(nativeData, encodedData, offset, len);
     90 		if (pixelPtr == null) throw new IOException("Error loading pixmap: " + getFailureReason());
     91 
     92 		basePtr = nativeData[0];
     93 		width = (int)nativeData[1];
     94 		height = (int)nativeData[2];
     95 		format = (int)nativeData[3];
     96 
     97 		if (requestedFormat != 0 && requestedFormat != format) {
     98 			convert(requestedFormat);
     99 		}
    100 	}
    101 
    102 	public Gdx2DPixmap (InputStream in, int requestedFormat) throws IOException {
    103 		ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
    104 		byte[] buffer = new byte[1024];
    105 		int readBytes = 0;
    106 
    107 		while ((readBytes = in.read(buffer)) != -1) {
    108 			bytes.write(buffer, 0, readBytes);
    109 		}
    110 
    111 		buffer = bytes.toByteArray();
    112 		pixelPtr = load(nativeData, buffer, 0, buffer.length);
    113 		if (pixelPtr == null) throw new IOException("Error loading pixmap: " + getFailureReason());
    114 
    115 		basePtr = nativeData[0];
    116 		width = (int)nativeData[1];
    117 		height = (int)nativeData[2];
    118 		format = (int)nativeData[3];
    119 
    120 		if (requestedFormat != 0 && requestedFormat != format) {
    121 			convert(requestedFormat);
    122 		}
    123 	}
    124 
    125 	/** @throws GdxRuntimeException if allocation failed. */
    126 	public Gdx2DPixmap (int width, int height, int format) throws GdxRuntimeException {
    127 		pixelPtr = newPixmap(nativeData, width, height, format);
    128 		if (pixelPtr == null) throw new GdxRuntimeException("Error loading pixmap.");
    129 
    130 		this.basePtr = nativeData[0];
    131 		this.width = (int)nativeData[1];
    132 		this.height = (int)nativeData[2];
    133 		this.format = (int)nativeData[3];
    134 	}
    135 
    136 	public Gdx2DPixmap (ByteBuffer pixelPtr, long[] nativeData) {
    137 		this.pixelPtr = pixelPtr;
    138 		this.basePtr = nativeData[0];
    139 		this.width = (int)nativeData[1];
    140 		this.height = (int)nativeData[2];
    141 		this.format = (int)nativeData[3];
    142 	}
    143 
    144 	private void convert (int requestedFormat) {
    145 		Gdx2DPixmap pixmap = new Gdx2DPixmap(width, height, requestedFormat);
    146 		pixmap.drawPixmap(this, 0, 0, 0, 0, width, height);
    147 		dispose();
    148 		this.basePtr = pixmap.basePtr;
    149 		this.format = pixmap.format;
    150 		this.height = pixmap.height;
    151 		this.nativeData = pixmap.nativeData;
    152 		this.pixelPtr = pixmap.pixelPtr;
    153 		this.width = pixmap.width;
    154 	}
    155 
    156 	@Override
    157 	public void dispose () {
    158 		free(basePtr);
    159 	}
    160 
    161 	public void clear (int color) {
    162 		clear(basePtr, color);
    163 	}
    164 
    165 	public void setPixel (int x, int y, int color) {
    166 		setPixel(basePtr, x, y, color);
    167 	}
    168 
    169 	public int getPixel (int x, int y) {
    170 		return getPixel(basePtr, x, y);
    171 	}
    172 
    173 	public void drawLine (int x, int y, int x2, int y2, int color) {
    174 		drawLine(basePtr, x, y, x2, y2, color);
    175 	}
    176 
    177 	public void drawRect (int x, int y, int width, int height, int color) {
    178 		drawRect(basePtr, x, y, width, height, color);
    179 	}
    180 
    181 	public void drawCircle (int x, int y, int radius, int color) {
    182 		drawCircle(basePtr, x, y, radius, color);
    183 	}
    184 
    185 	public void fillRect (int x, int y, int width, int height, int color) {
    186 		fillRect(basePtr, x, y, width, height, color);
    187 	}
    188 
    189 	public void fillCircle (int x, int y, int radius, int color) {
    190 		fillCircle(basePtr, x, y, radius, color);
    191 	}
    192 
    193 	public void fillTriangle (int x1, int y1, int x2, int y2, int x3, int y3, int color) {
    194 		fillTriangle(basePtr, x1, y1, x2, y2, x3, y3, color);
    195 	}
    196 
    197 	public void drawPixmap (Gdx2DPixmap src, int srcX, int srcY, int dstX, int dstY, int width, int height) {
    198 		drawPixmap(src.basePtr, basePtr, srcX, srcY, width, height, dstX, dstY, width, height);
    199 	}
    200 
    201 	public void drawPixmap (Gdx2DPixmap src, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth,
    202 		int dstHeight) {
    203 		drawPixmap(src.basePtr, basePtr, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight);
    204 	}
    205 
    206 	public static Gdx2DPixmap newPixmap (InputStream in, int requestedFormat) {
    207 		try {
    208 			return new Gdx2DPixmap(in, requestedFormat);
    209 		} catch (IOException e) {
    210 			return null;
    211 		}
    212 	}
    213 
    214 	public static Gdx2DPixmap newPixmap (int width, int height, int format) {
    215 		try {
    216 			return new Gdx2DPixmap(width, height, format);
    217 		} catch (IllegalArgumentException e) {
    218 			return null;
    219 		}
    220 	}
    221 
    222 	public ByteBuffer getPixels () {
    223 		return pixelPtr;
    224 	}
    225 
    226 	public int getHeight () {
    227 		return height;
    228 	}
    229 
    230 	public int getWidth () {
    231 		return width;
    232 	}
    233 
    234 	public int getFormat () {
    235 		return format;
    236 	}
    237 
    238 	public int getGLInternalFormat () {
    239 		return toGlFormat(format);
    240 	}
    241 
    242 	public int getGLFormat () {
    243 		return getGLInternalFormat();
    244 	}
    245 
    246 	public int getGLType () {
    247 		return toGlType(format);
    248 	}
    249 
    250 	public String getFormatString () {
    251 		switch (format) {
    252 		case GDX2D_FORMAT_ALPHA:
    253 			return "alpha";
    254 		case GDX2D_FORMAT_LUMINANCE_ALPHA:
    255 			return "luminance alpha";
    256 		case GDX2D_FORMAT_RGB888:
    257 			return "rgb888";
    258 		case GDX2D_FORMAT_RGBA8888:
    259 			return "rgba8888";
    260 		case GDX2D_FORMAT_RGB565:
    261 			return "rgb565";
    262 		case GDX2D_FORMAT_RGBA4444:
    263 			return "rgba4444";
    264 		default:
    265 			return "unknown";
    266 		}
    267 	}
    268 
    269 	// @off
    270 	/*JNI
    271 	#include <gdx2d/gdx2d.h>
    272 	#include <stdlib.h>
    273 	 */
    274 
    275 	private static native ByteBuffer load (long[] nativeData, byte[] buffer, int offset, int len); /*MANUAL
    276 		const unsigned char* p_buffer = (const unsigned char*)env->GetPrimitiveArrayCritical(buffer, 0);
    277 		gdx2d_pixmap* pixmap = gdx2d_load(p_buffer + offset, len);
    278 		env->ReleasePrimitiveArrayCritical(buffer, (char*)p_buffer, 0);
    279 
    280 		if(pixmap==0)
    281 			return 0;
    282 
    283 		jobject pixel_buffer = env->NewDirectByteBuffer((void*)pixmap->pixels, pixmap->width * pixmap->height * gdx2d_bytes_per_pixel(pixmap->format));
    284 		jlong* p_native_data = (jlong*)env->GetPrimitiveArrayCritical(nativeData, 0);
    285 		p_native_data[0] = (jlong)pixmap;
    286 		p_native_data[1] = pixmap->width;
    287 		p_native_data[2] = pixmap->height;
    288 		p_native_data[3] = pixmap->format;
    289 		env->ReleasePrimitiveArrayCritical(nativeData, p_native_data, 0);
    290 
    291 		return pixel_buffer;
    292 	 */
    293 
    294 	private static native ByteBuffer newPixmap (long[] nativeData, int width, int height, int format); /*MANUAL
    295 		gdx2d_pixmap* pixmap = gdx2d_new(width, height, format);
    296 		if(pixmap==0)
    297 			return 0;
    298 
    299 		jobject pixel_buffer = env->NewDirectByteBuffer((void*)pixmap->pixels, pixmap->width * pixmap->height * gdx2d_bytes_per_pixel(pixmap->format));
    300 		jlong* p_native_data = (jlong*)env->GetPrimitiveArrayCritical(nativeData, 0);
    301 		p_native_data[0] = (jlong)pixmap;
    302 		p_native_data[1] = pixmap->width;
    303 		p_native_data[2] = pixmap->height;
    304 		p_native_data[3] = pixmap->format;
    305 		env->ReleasePrimitiveArrayCritical(nativeData, p_native_data, 0);
    306 
    307 		return pixel_buffer;
    308 	 */
    309 
    310 	private static native void free (long pixmap); /*
    311 		gdx2d_free((gdx2d_pixmap*)pixmap);
    312 	 */
    313 
    314 	private static native void clear (long pixmap, int color); /*
    315 		gdx2d_clear((gdx2d_pixmap*)pixmap, color);
    316 	 */
    317 
    318 	private static native void setPixel (long pixmap, int x, int y, int color); /*
    319 		gdx2d_set_pixel((gdx2d_pixmap*)pixmap, x, y, color);
    320 	 */
    321 
    322 	private static native int getPixel (long pixmap, int x, int y); /*
    323 		return gdx2d_get_pixel((gdx2d_pixmap*)pixmap, x, y);
    324 	 */
    325 
    326 	private static native void drawLine (long pixmap, int x, int y, int x2, int y2, int color); /*
    327 		gdx2d_draw_line((gdx2d_pixmap*)pixmap, x, y, x2, y2, color);
    328 	 */
    329 
    330 	private static native void drawRect (long pixmap, int x, int y, int width, int height, int color); /*
    331 		gdx2d_draw_rect((gdx2d_pixmap*)pixmap, x, y, width, height, color);
    332 	 */
    333 
    334 	private static native void drawCircle (long pixmap, int x, int y, int radius, int color); /*
    335 		gdx2d_draw_circle((gdx2d_pixmap*)pixmap, x, y, radius, color);
    336 	 */
    337 
    338 	private static native void fillRect (long pixmap, int x, int y, int width, int height, int color); /*
    339 		gdx2d_fill_rect((gdx2d_pixmap*)pixmap, x, y, width, height, color);
    340 	 */
    341 
    342 	private static native void fillCircle (long pixmap, int x, int y, int radius, int color); /*
    343 		gdx2d_fill_circle((gdx2d_pixmap*)pixmap, x, y, radius, color);
    344 	 */
    345 
    346 	private static native void fillTriangle (long pixmap, int x1, int y1, int x2, int y2, int x3, int y3, int color); /*
    347 		gdx2d_fill_triangle((gdx2d_pixmap*)pixmap, x1, y1, x2, y2, x3, y3, color);
    348 	 */
    349 
    350 	private static native void drawPixmap (long src, long dst, int srcX, int srcY, int srcWidth, int srcHeight, int dstX,
    351 		int dstY, int dstWidth, int dstHeight); /*
    352 		gdx2d_draw_pixmap((gdx2d_pixmap*)src, (gdx2d_pixmap*)dst, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight);
    353 		 */
    354 
    355 	public static native void setBlend (int blend); /*
    356 		gdx2d_set_blend(blend);
    357 	 */
    358 
    359 	public static native void setScale (int scale); /*
    360 		gdx2d_set_scale(scale);
    361 	 */
    362 
    363 	public static native String getFailureReason (); /*
    364      return env->NewStringUTF(gdx2d_get_failure_reason());
    365 	 */
    366 }
    367