|
@@ -1,17 +1,15 @@
|
|
|
package hxd;
|
|
|
|
|
|
-private typedef InnerData =
|
|
|
-#if (flash||openfl)
|
|
|
- flash.display.BitmapData
|
|
|
+typedef BitmapInnerData =
|
|
|
+#if (flash || openfl || nme)
|
|
|
+ flash.display.BitmapData;
|
|
|
#elseif js
|
|
|
- js.html.CanvasRenderingContext2D
|
|
|
-#elseif nme
|
|
|
- nme.display.BitmapData
|
|
|
+ js.html.CanvasRenderingContext2D;
|
|
|
#else
|
|
|
- Int
|
|
|
-#end;
|
|
|
+ Int;
|
|
|
+#end
|
|
|
|
|
|
-abstract BitmapData(InnerData) {
|
|
|
+class BitmapData {
|
|
|
|
|
|
#if (flash || nme || openfl)
|
|
|
static var tmpRect = new flash.geom.Rectangle();
|
|
@@ -19,28 +17,46 @@ abstract BitmapData(InnerData) {
|
|
|
static var tmpMatrix = new flash.geom.Matrix();
|
|
|
#end
|
|
|
|
|
|
+#if (flash||openfl||nme)
|
|
|
+ var bmp : flash.display.BitmapData;
|
|
|
+#elseif js
|
|
|
+ var ctx : js.html.CanvasRenderingContext2D;
|
|
|
+ var lockImage : js.html.ImageData;
|
|
|
+ var pixel : js.html.ImageData;
|
|
|
+#end
|
|
|
+
|
|
|
public var width(get, never) : Int;
|
|
|
public var height(get, never) : Int;
|
|
|
|
|
|
- public inline function new(width:Int, height:Int) {
|
|
|
- #if (flash||openfl||nme)
|
|
|
- this = new flash.display.BitmapData(width, height, true, 0);
|
|
|
- #else
|
|
|
- var canvas = js.Browser.document.createCanvasElement();
|
|
|
- canvas.width = width;
|
|
|
- canvas.height = height;
|
|
|
- this = canvas.getContext2d();
|
|
|
- #end
|
|
|
+ public function new(width:Int, height:Int) {
|
|
|
+ if( width == -101 && height == -102 ) {
|
|
|
+ // no alloc
|
|
|
+ } else {
|
|
|
+ #if (flash||openfl||nme)
|
|
|
+ bmp = new flash.display.BitmapData(width, height, true, 0);
|
|
|
+ #elseif js
|
|
|
+ var canvas = js.Browser.document.createCanvasElement();
|
|
|
+ canvas.width = width;
|
|
|
+ canvas.height = height;
|
|
|
+ ctx = canvas.getContext2d();
|
|
|
+ #else
|
|
|
+ notImplemented();
|
|
|
+ #end
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- public inline function clear( color : Int ) {
|
|
|
- #if (flash||openfl)
|
|
|
- this.fillRect(this.rect, color);
|
|
|
+ public function clear( color : Int ) {
|
|
|
+ #if (flash||openfl||nme)
|
|
|
+ bmp.fillRect(bmp.rect, color);
|
|
|
#else
|
|
|
fill(0, 0, width, height, color);
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
+ static inline function notImplemented() {
|
|
|
+ throw "Not implemented";
|
|
|
+ }
|
|
|
+
|
|
|
public function fill( x : Int, y : Int, width : Int, height : Int, color : Int ) {
|
|
|
#if (flash || openfl || nme)
|
|
|
var r = tmpRect;
|
|
@@ -48,15 +64,17 @@ abstract BitmapData(InnerData) {
|
|
|
r.y = y;
|
|
|
r.width = width;
|
|
|
r.height = height;
|
|
|
- this.fillRect(r, color);
|
|
|
+ bmp.fillRect(r, color);
|
|
|
+ #elseif js
|
|
|
+ ctx.fillStyle = 'rgba(${(color>>16)&0xFF}, ${(color>>8)&0xFF}, ${color&0xFF}, ${(color>>>24)/255})';
|
|
|
+ ctx.fillRect(x, y, width, height);
|
|
|
#else
|
|
|
- this.fillStyle = 'rgba(${(color>>16)&0xFF}, ${(color>>8)&0xFF}, ${color&0xFF}, ${(color>>>24)/255})';
|
|
|
- this.fillRect(x, y, width, height);
|
|
|
+ notImplemented();
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
public function draw( x : Int, y : Int, src : BitmapData, srcX : Int, srcY : Int, width : Int, height : Int, ?blendMode : h2d.BlendMode ) {
|
|
|
- #if flash
|
|
|
+ #if (flash || openfl || nme)
|
|
|
if( blendMode == null ) blendMode = Alpha;
|
|
|
var r = tmpRect;
|
|
|
r.x = srcX;
|
|
@@ -68,51 +86,51 @@ abstract BitmapData(InnerData) {
|
|
|
var p = tmpPoint;
|
|
|
p.x = x;
|
|
|
p.y = y;
|
|
|
- this.copyPixels(src.toNative(), r, p);
|
|
|
+ bmp.copyPixels(src.bmp, r, p);
|
|
|
case Alpha:
|
|
|
var p = tmpPoint;
|
|
|
p.x = x;
|
|
|
p.y = y;
|
|
|
- this.copyPixels(src.toNative(), r, p, src.toNative(), null, true);
|
|
|
+ bmp.copyPixels(src.bmp, r, p, src.bmp, null, true);
|
|
|
case Add:
|
|
|
var m = tmpMatrix;
|
|
|
m.tx = x - srcX;
|
|
|
m.ty = y - srcY;
|
|
|
r.x = x;
|
|
|
r.y = y;
|
|
|
- this.draw(src.toNative(), m, null, flash.display.BlendMode.ADD, r, false);
|
|
|
+ bmp.draw(src.bmp, m, null, flash.display.BlendMode.ADD, r, false);
|
|
|
case Erase:
|
|
|
var m = tmpMatrix;
|
|
|
m.tx = x - srcX;
|
|
|
m.ty = y - srcY;
|
|
|
r.x = x;
|
|
|
r.y = y;
|
|
|
- this.draw(src.toNative(), m, null, flash.display.BlendMode.ERASE, r, false);
|
|
|
+ bmp.draw(src.bmp, m, null, flash.display.BlendMode.ERASE, r, false);
|
|
|
case Multiply:
|
|
|
var m = tmpMatrix;
|
|
|
m.tx = x - srcX;
|
|
|
m.ty = y - srcY;
|
|
|
r.x = x;
|
|
|
r.y = y;
|
|
|
- this.draw(src.toNative(), m, null, flash.display.BlendMode.MULTIPLY, r, false);
|
|
|
+ bmp.draw(src.bmp, m, null, flash.display.BlendMode.MULTIPLY, r, false);
|
|
|
case Screen:
|
|
|
var m = tmpMatrix;
|
|
|
m.tx = x - srcX;
|
|
|
m.ty = y - srcY;
|
|
|
r.x = x;
|
|
|
r.y = y;
|
|
|
- this.draw(src.toNative(), m, null, flash.display.BlendMode.SCREEN, r, false);
|
|
|
+ bmp.draw(src.bmp, m, null, flash.display.BlendMode.SCREEN, r, false);
|
|
|
case SoftAdd:
|
|
|
throw "BlendMode not supported";
|
|
|
}
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
public function drawScaled( x : Int, y : Int, width : Int, height : Int, src : BitmapData, srcX : Int, srcY : Int, srcWidth : Int, srcHeight : Int, ?blendMode : h2d.BlendMode, smooth = true ) {
|
|
|
- #if flash
|
|
|
if( blendMode == null ) blendMode = Alpha;
|
|
|
+ #if (flash || openfl || nme)
|
|
|
|
|
|
var b = switch( blendMode ) {
|
|
|
case None:
|
|
@@ -144,12 +162,12 @@ abstract BitmapData(InnerData) {
|
|
|
r.width = width;
|
|
|
r.height = height;
|
|
|
|
|
|
- this.draw(src.toNative(), m, null, b, r, smooth);
|
|
|
+ bmp.draw(src.bmp, m, null, b, r, smooth);
|
|
|
m.a = 1;
|
|
|
m.d = 1;
|
|
|
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
#end
|
|
|
}
|
|
|
|
|
@@ -173,13 +191,13 @@ abstract BitmapData(InnerData) {
|
|
|
for( x in x0...x1 + 1 )
|
|
|
setPixel(x, y0, color);
|
|
|
} else {
|
|
|
- throw "TODO";
|
|
|
+ throw "TODO : brensenham line";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public inline function dispose() {
|
|
|
- #if (flash||openfl)
|
|
|
- this.dispose();
|
|
|
+ #if (flash||openfl||nme)
|
|
|
+ bmp.dispose();
|
|
|
#end
|
|
|
}
|
|
|
|
|
@@ -188,12 +206,12 @@ abstract BitmapData(InnerData) {
|
|
|
}
|
|
|
|
|
|
public function sub( x, y, w, h ) : BitmapData {
|
|
|
- #if flash
|
|
|
+ #if (flash || openfl || nme)
|
|
|
var b = new flash.display.BitmapData(w, h);
|
|
|
- b.copyPixels(this, new flash.geom.Rectangle(x, y, w, h), new flash.geom.Point(0, 0));
|
|
|
+ b.copyPixels(bmp, new flash.geom.Rectangle(x, y, w, h), new flash.geom.Point(0, 0));
|
|
|
return fromNative(b);
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
return null;
|
|
|
#end
|
|
|
}
|
|
@@ -201,35 +219,47 @@ abstract BitmapData(InnerData) {
|
|
|
/**
|
|
|
Inform that we will perform several pixel operations on the BitmapData.
|
|
|
**/
|
|
|
- public inline function lock() {
|
|
|
+ public function lock() {
|
|
|
#if flash
|
|
|
- this.lock();
|
|
|
+ bmp.lock();
|
|
|
#elseif js
|
|
|
- canvasLock(this, true);
|
|
|
+ if( lockImage == null )
|
|
|
+ lockImage = ctx.getImageData(0, 0, width, height);
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
Inform that we have finished performing pixel operations on the BitmapData.
|
|
|
**/
|
|
|
- public inline function unlock() {
|
|
|
+ public function unlock() {
|
|
|
#if flash
|
|
|
- this.unlock();
|
|
|
+ bmp.unlock();
|
|
|
#elseif js
|
|
|
- canvasLock(this, false);
|
|
|
+ if( lockImage != null ) {
|
|
|
+ ctx.putImageData(lockImage, 0, 0);
|
|
|
+ lockImage = null;
|
|
|
+ }
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
Access the pixel color value at the given position. Note : this function can be very slow if done many times and the BitmapData has not been locked.
|
|
|
**/
|
|
|
- public inline function getPixel( x : Int, y : Int ) : Int {
|
|
|
- #if ( flash || openfl )
|
|
|
- return this.getPixel32(x, y);
|
|
|
+ public #if (flash || openfl || nme) inline #end function getPixel( x : Int, y : Int ) : Int {
|
|
|
+ #if ( flash || openfl || nme )
|
|
|
+ return bmp.getPixel32(x, y);
|
|
|
#elseif js
|
|
|
- return canvasGetPixel(this, x, y);
|
|
|
+ var i = lockImage;
|
|
|
+ var a;
|
|
|
+ if( i != null )
|
|
|
+ a = (x + y * i.width) << 2;
|
|
|
+ else {
|
|
|
+ a = 0;
|
|
|
+ i = ctx.getImageData(x, y, 1, 1);
|
|
|
+ }
|
|
|
+ return (i.data[a] << 16) | (i.data[a|1] << 8) | i.data[a|2] | (i.data[a|3] << 24);
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
return 0;
|
|
|
#end
|
|
|
}
|
|
@@ -237,64 +267,65 @@ abstract BitmapData(InnerData) {
|
|
|
/**
|
|
|
Modify the pixel color value at the given position. Note : this function can be very slow if done many times and the BitmapData has not been locked.
|
|
|
**/
|
|
|
- public inline function setPixel( x : Int, y : Int, c : Int ) {
|
|
|
- #if (flash||openfl)
|
|
|
- this.setPixel32(x, y, c);
|
|
|
+ public #if (flash || openfl || nme) inline #end function setPixel( x : Int, y : Int, c : Int ) {
|
|
|
+ #if ( flash || openfl || nme)
|
|
|
+ bmp.setPixel32(x, y, c);
|
|
|
#elseif js
|
|
|
- canvasSetPixel(this, x, y, c);
|
|
|
+ var i : js.html.ImageData = lockImage;
|
|
|
+ if( i != null ) {
|
|
|
+ var a = (x + y * i.width) << 2;
|
|
|
+ i.data[a] = (c >> 16) & 0xFF;
|
|
|
+ i.data[a|1] = (c >> 8) & 0xFF;
|
|
|
+ i.data[a|2] = c & 0xFF;
|
|
|
+ i.data[a|3] = (c >>> 24) & 0xFF;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var i = pixel;
|
|
|
+ if( i == null ) {
|
|
|
+ i = ctx.createImageData(1, 1);
|
|
|
+ pixel = i;
|
|
|
+ }
|
|
|
+ i.data[0] = (c >> 16) & 0xFF;
|
|
|
+ i.data[1] = (c >> 8) & 0xFF;
|
|
|
+ i.data[2] = c & 0xFF;
|
|
|
+ i.data[3] = (c >>> 24) & 0xFF;
|
|
|
+ ctx.putImageData(i, x, y);
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
inline function get_width() : Int {
|
|
|
- #if js
|
|
|
- return this.canvas.width;
|
|
|
+ #if (flash || nme || openfl)
|
|
|
+ return bmp.width;
|
|
|
+ #elseif js
|
|
|
+ return ctx.canvas.width;
|
|
|
#else
|
|
|
- return this.width;
|
|
|
+ notImplemented();
|
|
|
+ return 0;
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
inline function get_height() {
|
|
|
- #if js
|
|
|
- return this.canvas.height;
|
|
|
+ #if (flash || nme || openfl)
|
|
|
+ return bmp.height;
|
|
|
+ #elseif js
|
|
|
+ return ctx.canvas.height;
|
|
|
#else
|
|
|
- return this.height;
|
|
|
+ notImplemented();
|
|
|
+ return 0;
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
- public inline function getPixels() : Pixels {
|
|
|
- return nativeGetPixels(this);
|
|
|
- }
|
|
|
-
|
|
|
- public inline function setPixels( pixels : Pixels ) {
|
|
|
- nativeSetPixels(this, pixels);
|
|
|
- }
|
|
|
-
|
|
|
- public inline function toNative() : InnerData {
|
|
|
- return this;
|
|
|
- }
|
|
|
-
|
|
|
- public static inline function fromNative( bmp : InnerData ) : BitmapData {
|
|
|
- return cast bmp;
|
|
|
- }
|
|
|
-
|
|
|
- public function toPNG() {
|
|
|
- var pixels = getPixels();
|
|
|
- var png = pixels.toPNG();
|
|
|
- pixels.dispose();
|
|
|
- return png;
|
|
|
- }
|
|
|
-
|
|
|
- static function nativeGetPixels( b : InnerData ) {
|
|
|
- #if flash
|
|
|
- var p = new Pixels(b.width, b.height, haxe.io.Bytes.ofData(b.getPixels(b.rect)), ARGB);
|
|
|
+ public function getPixels() : Pixels {
|
|
|
+ #if (flash || nme || openfl)
|
|
|
+ var p = new Pixels(width, height, haxe.io.Bytes.ofData(bmp.getPixels(bmp.rect)), ARGB);
|
|
|
p.flags.set(AlphaPremultiplied);
|
|
|
return p;
|
|
|
#elseif js
|
|
|
- var w = b.canvas.width;
|
|
|
- var h = b.canvas.height;
|
|
|
- var data = b.getImageData(0, 0, w, h).data;
|
|
|
+ var w = width;
|
|
|
+ var h = height;
|
|
|
+ var data = ctx.getImageData(0, 0, w, h).data;
|
|
|
#if (haxe_ver < 3.2)
|
|
|
var pixels = [];
|
|
|
for( i in 0...w * h * 4 )
|
|
@@ -303,20 +334,14 @@ abstract BitmapData(InnerData) {
|
|
|
// starting from Haxe 3.2, bytes are based on native array
|
|
|
var pixels = data;
|
|
|
#end
|
|
|
- return new Pixels(b.canvas.width, b.canvas.height, haxe.io.Bytes.ofData(pixels), RGBA);
|
|
|
- #elseif openfl
|
|
|
- var bRect = b.rect;
|
|
|
- var bPixels : haxe.io.Bytes = hxd.ByteConversions.byteArrayToBytes(b.getPixels(b.rect));
|
|
|
- var p = new Pixels(b.width, b.height, bPixels, ARGB);
|
|
|
- p.flags.set(AlphaPremultiplied);
|
|
|
- return p;
|
|
|
+ return new Pixels(w, h, haxe.io.Bytes.ofData(pixels), RGBA);
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
return null;
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
- static function nativeSetPixels( b : InnerData, pixels : Pixels ) {
|
|
|
+ public function setPixels( pixels : Pixels ) {
|
|
|
#if flash
|
|
|
var bytes = pixels.bytes.getData();
|
|
|
bytes.position = 0;
|
|
@@ -329,65 +354,48 @@ abstract BitmapData(InnerData) {
|
|
|
pixels.convert(BGRA);
|
|
|
bytes.endian = flash.utils.Endian.LITTLE_ENDIAN;
|
|
|
}
|
|
|
- b.setPixels(b.rect, bytes);
|
|
|
+ bmp.setPixels(bmp.rect, bytes);
|
|
|
#elseif js
|
|
|
- var img = b.createImageData(pixels.width, pixels.height);
|
|
|
+ var img = ctx.createImageData(pixels.width, pixels.height);
|
|
|
pixels.convert(RGBA);
|
|
|
for( i in 0...pixels.width*pixels.height*4 ) img.data[i] = pixels.bytes.get(i);
|
|
|
- b.putImageData(img, 0, 0);
|
|
|
- #elseif cpp
|
|
|
- b.setPixels(b.rect, flash.utils.ByteArray.fromBytes(pixels.bytes));
|
|
|
+ ctx.putImageData(img, 0, 0);
|
|
|
+ #elseif (nme || openfl)
|
|
|
+ pixels.convert(BGRA);
|
|
|
+ bmp.setPixels(bmp.rect, flash.utils.ByteArray.fromBytes(pixels.bytes));
|
|
|
#else
|
|
|
- throw "TODO";
|
|
|
+ notImplemented();
|
|
|
#end
|
|
|
}
|
|
|
|
|
|
- #if js
|
|
|
-
|
|
|
- static function canvasLock( b : InnerData, lock : Bool ) untyped {
|
|
|
- if( lock ) {
|
|
|
- if( b.lockImage == null )
|
|
|
- b.lockImage = b.getImageData(0, 0, b.canvas.width, b.canvas.height);
|
|
|
- } else {
|
|
|
- if( b.lockImage != null ) {
|
|
|
- b.putImageData(b.lockImage, 0, 0);
|
|
|
- b.lockImage = null;
|
|
|
- }
|
|
|
- }
|
|
|
+ public inline function toNative() : BitmapInnerData {
|
|
|
+ #if (flash || nme || openfl)
|
|
|
+ return bmp;
|
|
|
+ #elseif js
|
|
|
+ return ctx;
|
|
|
+ #else
|
|
|
+ notImplemented();
|
|
|
+ return 0;
|
|
|
+ #end
|
|
|
}
|
|
|
|
|
|
- static function canvasGetPixel( b : InnerData, x : Int, y : Int ) {
|
|
|
- var i : js.html.ImageData = untyped b.lockImage;
|
|
|
- var a;
|
|
|
- if( i != null )
|
|
|
- a = (x + y * i.width) << 2;
|
|
|
- else {
|
|
|
- a = 0;
|
|
|
- i = b.getImageData(x, y, 1, 1);
|
|
|
- }
|
|
|
- return (i.data[a] << 16) | (i.data[a|1] << 8) | i.data[a|2] | (i.data[a|3] << 24);
|
|
|
+ public static function fromNative( data : BitmapInnerData ) : BitmapData {
|
|
|
+ var b = new BitmapData( -101, -102 );
|
|
|
+ #if (flash || nme || openfl)
|
|
|
+ b.bmp = data;
|
|
|
+ #elseif js
|
|
|
+ b.ctx = data;
|
|
|
+ #else
|
|
|
+ notImplemented();
|
|
|
+ #end
|
|
|
+ return b;
|
|
|
}
|
|
|
|
|
|
- static function canvasSetPixel( b : InnerData, x : Int, y : Int, c : Int ) {
|
|
|
- var i : js.html.ImageData = untyped b.lockImage;
|
|
|
- if( i != null ) {
|
|
|
- var a = (x + y * i.width) << 2;
|
|
|
- i.data[a] = (c >> 16) & 0xFF;
|
|
|
- i.data[a|1] = (c >> 8) & 0xFF;
|
|
|
- i.data[a|2] = c & 0xFF;
|
|
|
- i.data[a|3] = (c >>> 24) & 0xFF;
|
|
|
- return;
|
|
|
- }
|
|
|
- var i = untyped b.pixel;
|
|
|
- if( i == null ) {
|
|
|
- i = b.createImageData(1, 1);
|
|
|
- untyped b.pixel = i;
|
|
|
- }
|
|
|
- i.data[0] = (c >> 16) & 0xFF;
|
|
|
- i.data[1] = (c >> 8) & 0xFF;
|
|
|
- i.data[2] = c & 0xFF;
|
|
|
- i.data[3] = (c >>> 24) & 0xFF;
|
|
|
- b.putImageData(i, x, y);
|
|
|
+ public function toPNG() {
|
|
|
+ var pixels = getPixels();
|
|
|
+ var png = pixels.toPNG();
|
|
|
+ pixels.dispose();
|
|
|
+ return png;
|
|
|
}
|
|
|
- #end
|
|
|
+
|
|
|
}
|