diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ad8334ff..f4a3dd544 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,72 @@
+2.5.2 (07/23/2015)
+------------------
+
+* Added support for automatic software fallback on native platforms
+* Improved the behavior of image getPixel/setPixel
+* Fixed native fillRect/floodFill when using certain color values
+* Improved color conversion support for Flash
+* Fixed issue preventing Neko from reading 32-bit integers correctly
+
+
+2.5.1 (07/21/2015)
+------------------
+
+* Made Image properly support all PixelFormat/premultiplied types
+* Updated PixelFormat names to be more descriptive
+* Added prefix support for generated library class names
+* Fixed an issue with Assets.loadImage on HTML5
+* Fixed support for OpenAL playback using a starting offset
+
+
+2.5.0 (07/17/2015)
+------------------
+
+* Added guards against duplicate gamepad connect events
+* Added guards against gamepad events after a disconnect
+* Added dead zone and repeat value filtering for gamepad axis
+* Added CairoImageSurface, properly separate from CairoSurface
+* Improved HTML5 to use the project FPS setting
+* Improved asset libraries to have an "unload" method
+* Fixed repeated calls to Assets.load* with the same ID
+* Fixed "lime build" to not progress without sources
+* Fixed a regression in ByteArray.fromFile on Android
+* Fixed a bug in arrayBufferView.set
+* Quieted libpng "known incorrect profile" messages
+* Added a patch to allow Wii Remote detection (legacy)
+
+
+2.4.9 (07/13/2015)
+------------------
+
+* Added lime.system.ThreadPool
+* Added lime.utils.Log
+* Added image.scroll
+* Added event.has
+* Improved performance of Flash target logging
+* Improved "lime upgrade" when Git is not in the PATH
+* Improved image.clone when using canvas
+* Updated for compatibility with newer lime-samples
+* Updated to use a default icon when none is available
+* Updated Assets to use a ThreadPool for asynchronous loads
+* Updated to pass -verbose during "run" when in verbose mode
+* Fixed an issue when tracing null typed arrays
+* Fixed image.copyChannel when clipping is necessary
+* Fixed use of cURL basic types as Int
+* Improved support for asynchronous SSL requests (legacy)
+
+
+2.4.8 (07/09/2015)
+------------------
+
+* Improved lime.system.BackgroundWorker onComplete
+* Improved native bytes to guard against premature GC
+* Fixed ENABLE_BITCODE when targeting older iOS versions
+* Fixed possible double mouse events on iOS
+* Fixed embedded font support on iOS
+* Fixed "lime rebuild ios" with some versions of HXCPP
+* Fixed mouse middle/right/wheel events on desktop (legacy)
+
+
2.4.7 (07/06/2015)
------------------
@@ -9,7 +78,7 @@
* Added lime.system.BackgroundWorker for easy threads
* Made Assets loadImage/loadBytes asynchronous on native
-* Removed the ByteArray __init__ and matching CFFI functions
+* Removed the ByteArray \__init__ and matching CFFI functions
* Improved the help documentation when using "lime create"
* Fixed a crash that could occur when using Bytes
* Fixed audioSource.play on native when there is no data
diff --git a/haxelib.json b/haxelib.json
index 4034cf160..d29e9c2fb 100644
--- a/haxelib.json
+++ b/haxelib.json
@@ -4,7 +4,7 @@
"license": "MIT",
"tags": [],
"description": "A flexible lightweight layer for Haxe cross-platform developers",
- "version": "2.4.7",
- "releasenote": "Fixed regression in HTML5 typed array support",
+ "version": "2.5.2",
+ "releasenote": "Software fallback support, image fixes",
"contributors": [ "singmajesty" ]
}
diff --git a/include.xml b/include.xml
index 610d21dc3..b01a1cddb 100644
--- a/include.xml
+++ b/include.xml
@@ -74,7 +74,7 @@
-
+
diff --git a/legacy/project/src/sdl2/SDL2Stage.cpp b/legacy/project/src/sdl2/SDL2Stage.cpp
index 5071ce712..46047009c 100644
--- a/legacy/project/src/sdl2/SDL2Stage.cpp
+++ b/legacy/project/src/sdl2/SDL2Stage.cpp
@@ -535,7 +535,7 @@ public:
}
#endif
- #if defined(WEBOS) || defined(BLACKBERRY) || defined(HX_LINUX) || defined(HX_WINDOWS)
+ #if defined(WEBOS) || defined(BLACKBERRY)
if (inEvent.type == etMouseMove || inEvent.type == etMouseDown || inEvent.type == etMouseUp)
{
if (mSingleTouchID == NO_TOUCH || inEvent.value == mSingleTouchID || !mMultiTouch)
@@ -1210,8 +1210,8 @@ void ProcessEvent(SDL_Event &inEvent)
//int inValue=0, int inID=0, int inFlags=0, float inScaleX=1,float inScaleY=1, int inDeltaX=0,int inDeltaY=0
Event mouse(etMouseMove, inEvent.motion.x, inEvent.motion.y, 0, 0, 0, 1.0f, 1.0f, deltaX, deltaY);
- mouse.value = inEvent.motion.which;
#if defined(WEBOS) || defined(BLACKBERRY)
+ mouse.value = inEvent.motion.which;
mouse.flags |= efLeftDown;
#else
AddModStates(mouse.flags);
@@ -1222,8 +1222,8 @@ void ProcessEvent(SDL_Event &inEvent)
case SDL_MOUSEBUTTONDOWN:
{
Event mouse(etMouseDown, inEvent.button.x, inEvent.button.y, inEvent.button.button - 1);
- mouse.value = inEvent.motion.which;
#if defined(WEBOS) || defined(BLACKBERRY)
+ mouse.value = inEvent.motion.which;
mouse.flags |= efLeftDown;
#else
AddModStates(mouse.flags);
@@ -1234,8 +1234,9 @@ void ProcessEvent(SDL_Event &inEvent)
case SDL_MOUSEBUTTONUP:
{
Event mouse(etMouseUp, inEvent.button.x, inEvent.button.y, inEvent.button.button - 1);
+ #if defined(WEBOS) || defined(BLACKBERRY)
mouse.value = inEvent.motion.which;
- #if !defined(WEBOS) && defined(BLACKBERRY)
+ #else
AddModStates(mouse.flags);
#endif
sgSDLFrame->ProcessEvent(mouse);
@@ -1408,6 +1409,18 @@ void ProcessEvent(SDL_Event &inEvent)
{
joystick.x = 3;
}
+ else if (strcmp (gamepadstring, "Mayflash WIIMote PC Adapter") == 0) //MayFlash WIIMote PC Adapter
+ {
+ joystick.x = 4;
+ }
+ else if (strcmp (gamepadstring, "Nintendo RVL-CNT-01-TR") == 0) //Nintendo WIIMote MotionPlus, used directly
+ {
+ joystick.x = 5;
+ }
+ else if (strcmp (gamepadstring, "Nintendo RVL-CNT-01") == 0) //Nintendo WIIMote w/o MotionPlus attachment, used directly
+ {
+ joystick.x = 6;
+ }
else //default (XBox 360, basically)
{
joystick.x = 0;
diff --git a/lime/Assets.hx b/lime/Assets.hx
index 6d7f62013..6dff318fb 100644
--- a/lime/Assets.hx
+++ b/lime/Assets.hx
@@ -935,6 +935,7 @@ class Assets {
if (library != null) {
cache.clear (name + ":");
+ library.unload ();
library.eventCallback = null;
}
@@ -1140,6 +1141,13 @@ class AssetLibrary {
}
+ public function unload ():Void {
+
+
+
+ }
+
+
}
diff --git a/lime/_backend/html5/HTML5Application.hx b/lime/_backend/html5/HTML5Application.hx
index 2a7ef0547..fe2ac6eff 100644
--- a/lime/_backend/html5/HTML5Application.hx
+++ b/lime/_backend/html5/HTML5Application.hx
@@ -96,6 +96,7 @@ class HTML5Application {
if (config != null) {
+ setFrameRate (config.fps);
var window = new Window (config);
var renderer = new Renderer (window);
parent.addWindow (window);
diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx
index fc8645d0e..1b62c0877 100644
--- a/lime/_backend/native/NativeApplication.hx
+++ b/lime/_backend/native/NativeApplication.hx
@@ -14,6 +14,7 @@ import lime.ui.Gamepad;
import lime.ui.Window;
@:access(haxe.Timer)
+@:access(lime._backend.native.NativeRenderer)
@:access(lime.app.Application)
@:access(lime.graphics.Renderer)
@:access(lime.ui.Gamepad)
@@ -132,28 +133,35 @@ class NativeApplication {
case AXIS_MOVE:
- parent.window.onGamepadAxisMove.dispatch (Gamepad.devices.get (gamepadEventInfo.id), gamepadEventInfo.axis, gamepadEventInfo.value);
+ var gamepad = Gamepad.devices.get (gamepadEventInfo.id);
+ if (gamepad != null) parent.window.onGamepadAxisMove.dispatch (gamepad, gamepadEventInfo.axis, gamepadEventInfo.value);
case BUTTON_DOWN:
- parent.window.onGamepadButtonDown.dispatch (Gamepad.devices.get (gamepadEventInfo.id), gamepadEventInfo.button);
+ var gamepad = Gamepad.devices.get (gamepadEventInfo.id);
+ if (gamepad != null) parent.window.onGamepadButtonDown.dispatch (gamepad, gamepadEventInfo.button);
case BUTTON_UP:
- parent.window.onGamepadButtonUp.dispatch (Gamepad.devices.get (gamepadEventInfo.id), gamepadEventInfo.button);
+ var gamepad = Gamepad.devices.get (gamepadEventInfo.id);
+ if (gamepad != null) parent.window.onGamepadButtonUp.dispatch (gamepad, gamepadEventInfo.button);
case CONNECT:
- var gamepad = new Gamepad (gamepadEventInfo.id);
- Gamepad.devices.set (gamepadEventInfo.id, gamepad);
- parent.window.onGamepadConnect.dispatch (gamepad);
+ if (!Gamepad.devices.exists (gamepadEventInfo.id)) {
+
+ var gamepad = new Gamepad (gamepadEventInfo.id);
+ Gamepad.devices.set (gamepadEventInfo.id, gamepad);
+ parent.window.onGamepadConnect.dispatch (gamepad);
+
+ }
case DISCONNECT:
var gamepad = Gamepad.devices.get (gamepadEventInfo.id);
if (gamepad != null) gamepad.connected = false;
Gamepad.devices.remove (gamepadEventInfo.id);
- parent.window.onGamepadDisconnect.dispatch (gamepad);
+ if (gamepad != null) parent.window.onGamepadDisconnect.dispatch (gamepad);
}
@@ -229,22 +237,26 @@ class NativeApplication {
case RENDER_CONTEXT_LOST:
- parent.renderer.context = null;
- parent.renderer.onRenderContextLost.dispatch ();
+ if (parent.renderer.backend.useHardware) {
+
+ parent.renderer.context = null;
+ parent.renderer.onRenderContextLost.dispatch ();
+
+ }
case RENDER_CONTEXT_RESTORED:
- #if lime_console
- parent.renderer.context = CONSOLE (new ConsoleRenderContext ());
- #else
- if (parent.config.hardware) {
+ if (parent.renderer.backend.useHardware) {
+ #if lime_console
+ parent.renderer.context = CONSOLE (new ConsoleRenderContext ());
+ #else
parent.renderer.context = OPENGL (new GLRenderContext ());
+ #end
+
+ parent.renderer.onRenderContextRestored.dispatch (parent.renderer.context);
}
- #end
-
- parent.renderer.onRenderContextRestored.dispatch (parent.renderer.context);
}
@@ -753,4 +765,4 @@ private class WindowEventInfo {
var WINDOW_RESIZE = 9;
var WINDOW_RESTORE = 10;
-}
\ No newline at end of file
+}
diff --git a/lime/_backend/native/NativeRenderer.hx b/lime/_backend/native/NativeRenderer.hx
index ace13fdf1..91b9234a3 100644
--- a/lime/_backend/native/NativeRenderer.hx
+++ b/lime/_backend/native/NativeRenderer.hx
@@ -3,6 +3,7 @@ package lime._backend.native;
import lime.graphics.cairo.Cairo;
import lime.graphics.cairo.CairoFormat;
+import lime.graphics.cairo.CairoImageSurface;
import lime.graphics.cairo.CairoSurface;
import lime.graphics.CairoRenderContext;
import lime.graphics.ConsoleRenderContext;
@@ -39,23 +40,33 @@ class NativeRenderer {
handle = lime_renderer_create (parent.window.backend.handle);
- useHardware = parent.window.config.hardware;
-
#if lime_console
+
+ useHardware = true;
parent.context = CONSOLE (new ConsoleRenderContext ());
+
#else
- if (useHardware) {
+
+ var type = lime_renderer_get_type (handle);
+
+ switch (type) {
- parent.context = OPENGL (new GLRenderContext ());
+ case "opengl":
+
+ useHardware = true;
+ parent.context = OPENGL (new GLRenderContext ());
- } else {
-
- #if lime_cairo
- render ();
- parent.context = CAIRO (cairo);
- #end
+ default:
+
+ useHardware = false;
+
+ #if lime_cairo
+ render ();
+ parent.context = CAIRO (cairo);
+ #end
}
+
#end
}
@@ -97,14 +108,17 @@ class NativeRenderer {
if (cacheLock == null || cacheLock.pixels != lock.pixels || cacheLock.width != lock.width || cacheLock.height != lock.height) {
- if ( primarySurface != null )
+ if (primarySurface != null) {
+
primarySurface.destroy ();
+
+ }
- primarySurface = CairoSurface.createForData (lock.pixels, CairoFormat.ARGB32, lock.width, lock.height, lock.pitch);
+ primarySurface = CairoImageSurface.create (lock.pixels, CairoFormat.ARGB32, lock.width, lock.height, lock.pitch);
if (cairo != null) {
- cairo.recreate( primarySurface );
+ cairo.recreate (primarySurface);
} else {
@@ -112,7 +126,6 @@ class NativeRenderer {
}
-
}
cacheLock = lock;
@@ -134,6 +147,7 @@ class NativeRenderer {
private static var lime_renderer_create = System.load ("lime", "lime_renderer_create", 1);
private static var lime_renderer_flip = System.load ("lime", "lime_renderer_flip", 1);
+ private static var lime_renderer_get_type = System.load ("lime", "lime_renderer_get_type", 1);
private static var lime_renderer_lock = System.load ("lime", "lime_renderer_lock", 1);
private static var lime_renderer_unlock = System.load ("lime", "lime_renderer_unlock", 1);
diff --git a/lime/app/Event.hx b/lime/app/Event.hx
index 646d9d996..0b0ef6e6b 100644
--- a/lime/app/Event.hx
+++ b/lime/app/Event.hx
@@ -74,6 +74,14 @@ class Event {
}
+ public function has (listener:T):Bool {
+
+ var index = listeners.indexOf (listener);
+ return (index > -1);
+
+ }
+
+
public function remove (listener:T):Void {
var index = listeners.indexOf (listener);
diff --git a/lime/audio/AudioSource.hx b/lime/audio/AudioSource.hx
index 682423932..ebe8cea3d 100644
--- a/lime/audio/AudioSource.hx
+++ b/lime/audio/AudioSource.hx
@@ -428,8 +428,8 @@ class AudioSource {
if (buffer != null) {
AL.sourceRewind (id);
- AL.sourcef (id, AL.SEC_OFFSET, (value + offset) / 1000);
if (playing) AL.sourcePlay (id);
+ AL.sourcef (id, AL.SEC_OFFSET, (value + offset) / 1000);
}
diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx
index da14b33eb..b036a7593 100644
--- a/lime/graphics/Image.hx
+++ b/lime/graphics/Image.hx
@@ -12,6 +12,9 @@ import lime.graphics.format.JPEG;
import lime.graphics.format.PNG;
import lime.graphics.utils.ImageCanvasUtil;
import lime.graphics.utils.ImageDataUtil;
+import lime.math.color.ARGB;
+import lime.math.color.BGRA;
+import lime.math.color.RGBA;
import lime.math.ColorMatrix;
import lime.math.Rectangle;
import lime.math.Vector2;
@@ -161,8 +164,26 @@ class Image {
public function clone ():Image {
- var image = new Image (buffer.clone (), offsetX, offsetY, width, height, null, type);
- return image;
+ if (buffer != null) {
+
+ if (type == CANVAS && buffer.__srcImage == null) {
+
+ ImageCanvasUtil.convertToCanvas (this);
+ ImageCanvasUtil.sync (this);
+ buffer.data = null;
+ buffer.__srcImageData = null;
+
+ }
+
+ var image = new Image (buffer.clone (), offsetX, offsetY, width, height, null, type);
+ image.dirty = dirty;
+ return image;
+
+ } else {
+
+ return new Image (null, offsetX, offsetY, width, height, null, type);
+
+ }
}
@@ -374,8 +395,16 @@ class Image {
case FLASH:
rect.offset (offsetX, offsetY);
- if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8);
- buffer.__srcBitmapData.fillRect (rect.__toFlashRectangle (), color);
+
+ var argb:ARGB = switch (format) {
+
+ case ARGB32: color;
+ case BGRA32: (color:BGRA);
+ default: (color:RGBA);
+
+ }
+
+ buffer.__srcBitmapData.fillRect (rect.__toFlashRectangle (), argb);
default:
@@ -404,8 +433,15 @@ class Image {
case FLASH:
- if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8);
- buffer.__srcBitmapData.floodFill (x + offsetX, y + offsetY, color);
+ var argb:ARGB = switch (format) {
+
+ case ARGB32: color;
+ case BGRA32: (color:BGRA);
+ default: (color:RGBA);
+
+ }
+
+ buffer.__srcBitmapData.floodFill (x + offsetX, y + offsetY, argb);
default:
@@ -522,15 +558,13 @@ class Image {
case FLASH:
- var color = buffer.__srcBitmapData.getPixel (x + offsetX, y + offsetY);
+ var color:ARGB = buffer.__srcBitmapData.getPixel (x + offsetX, y + offsetY);
- if (format == null || format == RGBA) {
+ switch (format) {
- return ((color & 0xFF) << 24) | (color >> 8);
-
- } else {
-
- return color;
+ case ARGB32: return color;
+ case BGRA32: var bgra:BGRA = color; return bgra;
+ default: var rgba:RGBA = color; return rgba;
}
@@ -563,15 +597,13 @@ class Image {
case FLASH:
- var color = buffer.__srcBitmapData.getPixel32 (x + offsetX, y + offsetY);
+ var color:ARGB = buffer.__srcBitmapData.getPixel32 (x + offsetX, y + offsetY);
- if (format == null || format == RGBA) {
+ switch (format) {
- return ((color & 0xFF) << 24) | (color >> 8);
-
- } else {
-
- return color;
+ case ARGB32: return color;
+ case BGRA32: var bgra:BGRA = color; return bgra;
+ default: var rgba:RGBA = color; return rgba;
}
@@ -607,20 +639,38 @@ class Image {
rect.offset (offsetX, offsetY);
var byteArray = buffer.__srcBitmapData.getPixels (rect.__toFlashRectangle ());
- if (format == null || format == RGBA) {
+ switch (format) {
- var color;
- var length = Std.int (byteArray.length / 4);
-
- for (i in 0...length) {
+ case ARGB32: // do nothing
+ case BGRA32:
- color = byteArray.readUnsignedInt ();
- byteArray.position -= 4;
- byteArray.writeUnsignedInt (((color & 0xFF) << 24) | (color >> 8));
+ var color:BGRA;
+ var length = Std.int (byteArray.length / 4);
- }
+ for (i in 0...length) {
+
+ color = (byteArray.readUnsignedInt ():ARGB);
+ byteArray.position -= 4;
+ byteArray.writeUnsignedInt (color);
+
+ }
+
+ byteArray.position = 0;
- byteArray.position = 0;
+ default:
+
+ var color:RGBA;
+ var length = Std.int (byteArray.length / 4);
+
+ for (i in 0...length) {
+
+ color = (byteArray.readUnsignedInt ():ARGB);
+ byteArray.position -= 4;
+ byteArray.writeUnsignedInt (color);
+
+ }
+
+ byteArray.position = 0;
}
@@ -706,6 +756,37 @@ class Image {
}
+ public function scroll (x:Int, y:Int):Void {
+
+ if (buffer == null) return;
+
+ switch (type) {
+
+ case CANVAS:
+
+ ImageCanvasUtil.scroll (this, x, y);
+
+ case DATA:
+
+ //#if (js && html5)
+ //ImageCanvasUtil.convertToData (this);
+ //#end
+
+ //ImageDataUtil.scroll (this, x, y);
+
+ copyPixels (this, rect, new Vector2 (x, y));
+
+ case FLASH:
+
+ buffer.__srcBitmapData.scroll (x + offsetX, y + offsetX);
+
+ default:
+
+ }
+
+ }
+
+
public function setPixel (x:Int, y:Int, color:Int, format:PixelFormat = null):Void {
if (buffer == null || x < 0 || y < 0 || x >= width || y >= height) return;
@@ -726,8 +807,15 @@ class Image {
case FLASH:
- if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8);
- buffer.__srcBitmapData.setPixel (x + offsetX, y + offsetX, color);
+ var argb:ARGB = switch (format) {
+
+ case ARGB32: color;
+ case BGRA32: (color:BGRA);
+ default: (color:RGBA);
+
+ }
+
+ buffer.__srcBitmapData.setPixel (x + offsetX, y + offsetX, argb);
default:
@@ -756,8 +844,15 @@ class Image {
case FLASH:
- if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8);
- buffer.__srcBitmapData.setPixel32 (x + offsetX, y + offsetY, color);
+ var argb:ARGB = switch (format) {
+
+ case ARGB32: color;
+ case BGRA32: (color:BGRA);
+ default: (color:RGBA);
+
+ }
+
+ buffer.__srcBitmapData.setPixel32 (x + offsetX, y + offsetY, argb);
default:
@@ -788,27 +883,54 @@ class Image {
case FLASH:
rect.offset (offsetX, offsetY);
- if (format == null || format == RGBA) {
+
+ switch (format) {
- var srcData = byteArray;
- byteArray = new ByteArray ();
- #if flash
- byteArray.length = srcData.length;
- #end
-
- var color;
- var length = Std.int (byteArray.length / 4);
-
- for (i in 0...length) {
+ case ARGB32: // do nothing
+ case BGRA32:
- color = srcData.readUnsignedInt ();
- byteArray.writeUnsignedInt (((color & 0xFF) << 24) | (color >> 8));
+ var srcData = byteArray;
+ byteArray = new ByteArray ();
+ #if flash
+ byteArray.length = srcData.length;
+ #end
- }
+ var color:BGRA;
+ var length = Std.int (byteArray.length / 4);
+
+ for (i in 0...length) {
+
+ color = srcData.readUnsignedInt ();
+ byteArray.writeUnsignedInt (cast (color, ARGB));
+
+ }
+
+ srcData.position = 0;
+ byteArray.position = 0;
+
+ default:
+
+ var srcData = byteArray;
+ byteArray = new ByteArray ();
+ #if flash
+ byteArray.length = srcData.length;
+ #end
+
+ var color:RGBA;
+ var length = Std.int (byteArray.length / 4);
+
+ for (i in 0...length) {
+
+ color = srcData.readUnsignedInt ();
+ byteArray.writeUnsignedInt (cast (color, ARGB));
+
+ }
+
+ srcData.position = 0;
+ byteArray.position = 0;
- srcData.position = 0;
- byteArray.position = 0;
}
+
buffer.__srcBitmapData.setPixels (rect.__toFlashRectangle (), byteArray);
default:
diff --git a/lime/graphics/ImageBuffer.hx b/lime/graphics/ImageBuffer.hx
index ca1bb1368..c046e972c 100644
--- a/lime/graphics/ImageBuffer.hx
+++ b/lime/graphics/ImageBuffer.hx
@@ -47,7 +47,7 @@ class ImageBuffer {
this.width = width;
this.height = height;
this.bitsPerPixel = bitsPerPixel;
- this.format = (format == null ? RGBA : format);
+ this.format = (format == null ? RGBA32 : format);
transparent = true;
}
@@ -108,6 +108,8 @@ class ImageBuffer {
}
#end
+ buffer.bitsPerPixel = bitsPerPixel;
+ buffer.format = format;
buffer.premultiplied = premultiplied;
buffer.transparent = transparent;
return buffer;
diff --git a/lime/graphics/PixelFormat.hx b/lime/graphics/PixelFormat.hx
index 7b8106948..bcd901493 100644
--- a/lime/graphics/PixelFormat.hx
+++ b/lime/graphics/PixelFormat.hx
@@ -3,8 +3,8 @@ package lime.graphics;
@:enum abstract PixelFormat(Int) from Int to Int {
- public var RGBA = 0;
- public var ARGB = 1;
- public var BGRA = 2;
+ public var RGBA32 = 0;
+ public var ARGB32 = 1;
+ public var BGRA32 = 2;
}
\ No newline at end of file
diff --git a/lime/graphics/cairo/CairoImageSurface.hx b/lime/graphics/cairo/CairoImageSurface.hx
new file mode 100644
index 000000000..0f83305df
--- /dev/null
+++ b/lime/graphics/cairo/CairoImageSurface.hx
@@ -0,0 +1,131 @@
+package lime.graphics.cairo;
+
+
+import lime.system.System;
+
+
+@:forward abstract CairoImageSurface(CairoSurface) from CairoSurface to CairoSurface {
+
+
+ public var data (get, never):Dynamic;
+ public var format (get, never):CairoFormat;
+ public var height (get, never):Int;
+ public var stride (get, never):Int;
+ public var width (get, never):Int;
+
+
+ public function new (format:CairoFormat, width:Int, height:Int):CairoSurface {
+
+ #if lime_cairo
+ this = lime_cairo_image_surface_create (format, width, height);
+ #else
+ this = cast 0;
+ #end
+
+ }
+
+
+ public static function create (data:Dynamic, format:CairoFormat, width:Int, height:Int, stride:Int):CairoSurface {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_create_for_data (data, format, width, height, stride);
+ #else
+ return cast 0;
+ #end
+
+ }
+
+
+ public static function fromImage (image:Image):CairoSurface {
+
+ #if lime_cairo
+ return create (lime_bytes_get_data_pointer (#if nodejs image.data #else image.data.buffer #end), CairoFormat.ARGB32, image.width, image.height, image.buffer.stride);
+ #else
+ return null;
+ #end
+
+ }
+
+
+
+
+ // Get & Set Methods
+
+
+
+
+ @:noCompletion private function get_data ():Dynamic {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_get_data (this);
+ #else
+ return null;
+ #end
+
+ }
+
+
+ @:noCompletion private function get_format ():CairoFormat {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_get_format (this);
+ #else
+ return 0;
+ #end
+
+ }
+
+
+ @:noCompletion private function get_height ():Int {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_get_height (this);
+ #else
+ return 0;
+ #end
+
+ }
+
+
+ @:noCompletion private function get_stride ():Int {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_get_stride (this);
+ #else
+ return 0;
+ #end
+
+ }
+
+
+ @:noCompletion private function get_width ():Int {
+
+ #if lime_cairo
+ return lime_cairo_image_surface_get_width (this);
+ #else
+ return 0;
+ #end
+
+ }
+
+
+
+
+ // Native Methods
+
+
+
+
+ #if lime_cairo
+ private static var lime_bytes_get_data_pointer = System.load ("lime", "lime_bytes_get_data_pointer", 1);
+ private static var lime_cairo_image_surface_create = System.load ("lime", "lime_cairo_image_surface_create", 3);
+ private static var lime_cairo_image_surface_create_for_data = System.load ("lime", "lime_cairo_image_surface_create_for_data", 5);
+ private static var lime_cairo_image_surface_get_data = System.load ("lime", "lime_cairo_image_surface_get_data", 1);
+ private static var lime_cairo_image_surface_get_format = System.load ("lime", "lime_cairo_image_surface_get_format", 1);
+ private static var lime_cairo_image_surface_get_height = System.load ("lime", "lime_cairo_image_surface_get_height", 1);
+ private static var lime_cairo_image_surface_get_stride = System.load ("lime", "lime_cairo_image_surface_get_stride", 1);
+ private static var lime_cairo_image_surface_get_width = System.load ("lime", "lime_cairo_image_surface_get_width", 1);
+ #end
+
+
+}
\ No newline at end of file
diff --git a/lime/graphics/cairo/CairoSurface.hx b/lime/graphics/cairo/CairoSurface.hx
index 725ef20d1..5ef637b19 100644
--- a/lime/graphics/cairo/CairoSurface.hx
+++ b/lime/graphics/cairo/CairoSurface.hx
@@ -11,32 +11,6 @@ import lime.utils.ByteArray;
abstract CairoSurface(Dynamic) {
- public var height (get, never):Int;
- public var width (get, never):Int;
-
-
- public function new (format:CairoFormat, width:Int, height:Int):CairoSurface {
-
- #if lime_cairo
- this = lime_cairo_image_surface_create (format, width, height);
- #else
- this = 0;
- #end
-
- }
-
-
- public static function createForData (data:Dynamic, format:CairoFormat, width:Int, height:Int, stride:Int):CairoSurface {
-
- #if lime_cairo
- return lime_cairo_image_surface_create_for_data (data, format, width, height, stride);
- #else
- return cast 0;
- #end
-
- }
-
-
public function destroy ():Void {
#if lime_cairo
@@ -55,46 +29,6 @@ abstract CairoSurface(Dynamic) {
}
- public static function fromImage (image:Image):CairoSurface {
-
- #if lime_cairo
- return createForData (lime_bytes_get_data_pointer (#if nodejs image.data #else image.data.buffer #end), CairoFormat.ARGB32, image.width, image.height, image.buffer.stride);
- #else
- return null;
- #end
-
- }
-
-
-
-
- // Get & Set Methods
-
-
-
-
- @:noCompletion private function get_height ():Int {
-
- #if lime_cairo
- return lime_cairo_image_surface_get_height (this);
- #else
- return 0;
- #end
-
- }
-
-
- @:noCompletion private function get_width ():Int {
-
- #if lime_cairo
- return lime_cairo_image_surface_get_width (this);
- #else
- return 0;
- #end
-
- }
-
-
// Native Methods
@@ -103,11 +37,6 @@ abstract CairoSurface(Dynamic) {
#if lime_cairo
- private static var lime_bytes_get_data_pointer = System.load ("lime", "lime_bytes_get_data_pointer", 1);
- private static var lime_cairo_image_surface_create = System.load ("lime", "lime_cairo_image_surface_create", 3);
- private static var lime_cairo_image_surface_create_for_data = System.load ("lime", "lime_cairo_image_surface_create_for_data", 5);
- private static var lime_cairo_image_surface_get_height = System.load ("lime", "lime_cairo_image_surface_get_height", 1);
- private static var lime_cairo_image_surface_get_width = System.load ("lime", "lime_cairo_image_surface_get_width", 1);
private static var lime_cairo_surface_destroy = System.load ("lime", "lime_cairo_surface_destroy", 1);
private static var lime_cairo_surface_flush = System.load ("lime", "lime_cairo_surface_flush", 1);
#end
diff --git a/lime/graphics/format/BMP.hx b/lime/graphics/format/BMP.hx
index e3cf0d6d2..ffad8c901 100644
--- a/lime/graphics/format/BMP.hx
+++ b/lime/graphics/format/BMP.hx
@@ -94,7 +94,7 @@ class BMP {
}
- var pixels = image.getPixels (new Rectangle (0, 0, image.width, image.height), ARGB);
+ var pixels = image.getPixels (new Rectangle (0, 0, image.width, image.height), ARGB32);
var a, r, g, b;
switch (type) {
diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx
index 7720ff945..73e1f46df 100644
--- a/lime/graphics/utils/ImageCanvasUtil.hx
+++ b/lime/graphics/utils/ImageCanvasUtil.hx
@@ -46,6 +46,11 @@ class ImageCanvasUtil {
buffer.__srcImage = null;
+ } else if (buffer.data != null && buffer.__srcCanvas == null) {
+
+ createCanvas (image, buffer.width, buffer.height);
+ createImageData (image);
+
}
}
@@ -83,6 +88,12 @@ class ImageCanvasUtil {
public static function copyPixels (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image = null, alphaPoint:Vector2 = null, mergeAlpha:Bool = false):Void {
+ if (destPoint.x >= image.width || destPoint.y >= image.height) {
+
+ return;
+
+ }
+
if (alphaImage != null && alphaImage.transparent) {
if (alphaPoint == null) alphaPoint = new Vector2 ();
@@ -156,9 +167,19 @@ class ImageCanvasUtil {
var buffer = image.buffer;
- if (buffer.data == null) {
+ if (buffer.__srcImageData == null) {
+
+ if (buffer.data == null) {
+
+ buffer.__srcImageData = buffer.__srcContext.getImageData (0, 0, buffer.width, buffer.height);
+
+ } else {
+
+ buffer.__srcImageData = buffer.__srcContext.createImageData (buffer.width, buffer.height);
+ buffer.__srcImageData.data.set (cast buffer.data);
+
+ }
- buffer.__srcImageData = buffer.__srcContext.getImageData (0, 0, buffer.width, buffer.height);
buffer.data = new UInt8Array (cast buffer.__srcImageData.data.buffer);
}
@@ -186,7 +207,7 @@ class ImageCanvasUtil {
var r, g, b, a;
- if (format == ARGB) {
+ if (format == ARGB32) {
r = (color >> 16) & 0xFF;
g = (color >> 8) & 0xFF;
@@ -282,6 +303,19 @@ class ImageCanvasUtil {
}
+ public static function scroll (image:Image, x:Int, y:Int):Void {
+
+ if ((x % image.width == 0) && (y % image.height == 0)) return;
+
+ convertToCanvas (image);
+ sync (image);
+
+ image.buffer.__srcContext.clearRect (x, y, image.width, image.height);
+ image.buffer.__srcContext.drawImage (image.buffer.__srcCanvas, x, y);
+
+ }
+
+
public static function setPixel (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
convertToCanvas (image);
@@ -315,7 +349,7 @@ class ImageCanvasUtil {
public static function sync (image:Image):Void {
#if (js && html5)
- if (image.dirty && image.type != DATA) {
+ if (image.dirty && image.buffer.__srcImageData != null && image.type != DATA) {
image.buffer.__srcContext.putImageData (image.buffer.__srcImageData, 0, 0);
image.buffer.data = null;
@@ -327,4 +361,4 @@ class ImageCanvasUtil {
}
-}
\ No newline at end of file
+}
diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx
index 1d0d9892b..30951cf7a 100644
--- a/lime/graphics/utils/ImageDataUtil.hx
+++ b/lime/graphics/utils/ImageDataUtil.hx
@@ -2,10 +2,14 @@ package lime.graphics.utils;
import haxe.ds.Vector;
+import haxe.Int32;
import haxe.io.Bytes;
import lime.graphics.Image;
import lime.graphics.ImageBuffer;
import lime.graphics.PixelFormat;
+import lime.math.color.ARGB;
+import lime.math.color.BGRA;
+import lime.math.color.RGBA;
import lime.math.ColorMatrix;
import lime.math.Rectangle;
import lime.math.Vector2;
@@ -13,41 +17,12 @@ import lime.system.System;
import lime.utils.ByteArray;
import lime.utils.UInt8Array;
+@:access(lime.math.color.RGBA)
+
class ImageDataUtil {
- private static var __alpha16:Vector;
- private static var __clamp:Vector;
-
-
- private static function __init__ ():Void {
-
- __alpha16 = new Vector (256);
-
- for (i in 0...256) {
-
- __alpha16[i] = Std.int (i * (1 << 16) / 255);
-
- }
-
- __clamp = new Vector (0xFF + 0xFF);
-
- for (i in 0...0xFF) {
-
- __clamp[i] = i;
-
- }
-
- for (i in 0xFF...(0xFF + 0xFF + 1)) {
-
- __clamp[i] = 0xFF;
-
- }
-
- }
-
-
public static function colorTransform (image:Image, rect:Rectangle, colorMatrix:ColorMatrix):Void {
var data = image.buffer.data;
@@ -58,34 +33,29 @@ class ImageDataUtil {
#end
{
- var stride = image.buffer.width * 4;
- var offset:Int;
+ var format = image.buffer.format;
+ var premultiplied = image.buffer.premultiplied;
- var rowStart = Std.int (rect.top + image.offsetY);
- var rowEnd = Std.int (rect.bottom + image.offsetY);
- var columnStart = Std.int (rect.left + image.offsetX);
- var columnEnd = Std.int (rect.right + image.offsetX);
+ var dataView = new ImageDataView (image, rect);
- var r, g, b, a, ex = 0;
+ var alphaTable = colorMatrix.getAlphaTable ();
+ var redTable = colorMatrix.getRedTable ();
+ var greenTable = colorMatrix.getGreenTable ();
+ var blueTable = colorMatrix.getBlueTable ();
- for (row in rowStart...rowEnd) {
+ var row, offset, pixel:RGBA;
+
+ for (y in 0...dataView.height) {
- for (column in columnStart...columnEnd) {
+ row = dataView.row (y);
+
+ for (x in 0...dataView.width) {
- offset = (row * stride) + (column * 4);
+ offset = row + (x * 4);
- a = Std.int ((data[offset + 3] * colorMatrix.alphaMultiplier) + colorMatrix.alphaOffset);
- ex = a > 0xFF ? a - 0xFF : 0;
- b = Std.int ((data[offset + 2] * colorMatrix.blueMultiplier) + colorMatrix.blueOffset + ex);
- ex = b > 0xFF ? b - 0xFF : 0;
- g = Std.int ((data[offset + 1] * colorMatrix.greenMultiplier) + colorMatrix.greenOffset + ex);
- ex = g > 0xFF ? g - 0xFF : 0;
- r = Std.int ((data[offset] * colorMatrix.redMultiplier) + colorMatrix.redOffset + ex);
-
- data[offset] = r > 0xFF ? 0xFF : r;
- data[offset + 1] = g > 0xFF ? 0xFF : g;
- data[offset + 2] = b > 0xFF ? 0xFF : b;
- data[offset + 3] = a > 0xFF ? 0xFF : a;
+ pixel.readUInt8 (data, offset, format, premultiplied);
+ pixel.set (redTable[pixel.r], greenTable[pixel.g], blueTable[pixel.b], alphaTable[pixel.a]);
+ pixel.writeUInt8 (data, offset, format, premultiplied);
}
@@ -128,36 +98,48 @@ class ImageDataUtil {
#end
{
- var srcStride = Std.int (sourceImage.buffer.width * 4);
- var srcPosition = Std.int (((sourceRect.x + sourceImage.offsetX) * 4) + (srcStride * (sourceRect.y + sourceImage.offsetY)) + srcIdx);
- var srcRowOffset = srcStride - Std.int (4 * (sourceRect.width + sourceImage.offsetX));
- var srcRowEnd = Std.int (4 * (sourceRect.x + sourceImage.offsetX + sourceRect.width));
- var srcData = sourceImage.buffer.data;
+ var srcView = new ImageDataView (sourceImage, sourceRect);
+ var destView = new ImageDataView (image, new Rectangle (destPoint.x, destPoint.y, srcView.width, srcView.height));
- var destStride = Std.int (image.buffer.width * 4);
- var destPosition = Std.int (((destPoint.x + image.offsetX) * 4) + (destStride * (destPoint.y + image.offsetY)) + destIdx);
- var destRowOffset = destStride - Std.int (4 * (sourceRect.width + image.offsetX));
- var destRowEnd = Std.int (4 * (destPoint.x + image.offsetX + sourceRect.width));
- var destData = image.buffer.data;
+ var srcFormat = sourceImage.buffer.format;
+ var destFormat = image.buffer.format;
+ var srcPremultiplied = sourceImage.buffer.premultiplied;
+ var destPremultiplied = image.buffer.premultiplied;
- var length = Std.int (sourceRect.width * sourceRect.height);
+ var srcPosition, destPosition, srcPixel:RGBA, destPixel:RGBA, value = 0;
- for (i in 0...length) {
+ for (y in 0...destView.height) {
- destData[destPosition] = srcData[srcPosition];
+ srcPosition = srcView.row (y);
+ destPosition = destView.row (y);
- srcPosition += 4;
- destPosition += 4;
-
- if ((srcPosition % srcStride) > srcRowEnd) {
+ for (x in 0...destView.width) {
- srcPosition += srcRowOffset;
+ srcPixel.readUInt8 (srcData, srcPosition, srcFormat, srcPremultiplied);
+ destPixel.readUInt8 (destData, destPosition, destFormat, destPremultiplied);
- }
-
- if ((destPosition % destStride) > destRowEnd) {
+ switch (srcIdx) {
+
+ case 0: value = srcPixel.r;
+ case 1: value = srcPixel.g;
+ case 2: value = srcPixel.b;
+ case 3: value = srcPixel.a;
+
+ }
- destPosition += destRowOffset;
+ switch (destIdx) {
+
+ case 0: destPixel.r = value;
+ case 1: destPixel.g = value;
+ case 2: destPixel.b = value;
+ case 3: destPixel.a = value;
+
+ }
+
+ destPixel.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
+
+ srcPosition += 4;
+ destPosition += 4;
}
@@ -172,56 +154,40 @@ class ImageDataUtil {
public static function copyPixels (image:Image, sourceImage:Image, sourceRect:Rectangle, destPoint:Vector2, alphaImage:Image = null, alphaPoint:Vector2 = null, mergeAlpha:Bool = false):Void {
- if (alphaImage != null && alphaImage.transparent) {
-
- if (alphaPoint == null) alphaPoint = new Vector2 ();
-
- // TODO: use faster method
-
- var tempData = image.clone ();
- tempData.copyChannel (alphaImage, new Rectangle (alphaPoint.x, alphaPoint.y, sourceRect.width, sourceRect.height), new Vector2 (sourceRect.x, sourceRect.y), ImageChannel.ALPHA, ImageChannel.ALPHA);
- sourceImage = tempData;
-
- }
-
#if ((cpp || neko) && !disable_cffi)
- if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, mergeAlpha); else
+ if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); else
#end
{
- var rowOffset = Std.int (destPoint.y + image.offsetY - sourceRect.y - sourceImage.offsetY);
- var columnOffset = Std.int (destPoint.x + image.offsetX - sourceRect.x - sourceImage.offsetY);
-
var sourceData = sourceImage.buffer.data;
- var sourceStride = sourceImage.buffer.width * 4;
- var sourceOffset:Int = 0;
+ var destData = image.buffer.data;
- var data = image.buffer.data;
- var stride = image.buffer.width * 4;
- var offset:Int = 0;
+ if (sourceData == null || destData == null) return;
+
+ var sourceView = new ImageDataView (sourceImage, sourceRect);
+ var destView = new ImageDataView (image, new Rectangle (destPoint.x, destPoint.y, sourceView.width, sourceView.height));
+
+ var sourceFormat = sourceImage.buffer.format;
+ var destFormat = image.buffer.format;
+ var sourcePremultiplied = sourceImage.buffer.premultiplied;
+ var destPremultiplied = image.buffer.premultiplied;
+
+ var sourcePosition, destPosition, sourcePixel:RGBA;
if (!mergeAlpha || !sourceImage.transparent) {
- //#if (!js && !flash)
- //if (sourceRect.width == image.width && sourceRect.height == image.height && image.width == sourceImage.width && image.height == sourceImage.height && sourceRect.x == 0 && sourceRect.y == 0 && destPoint.x == 0 && destPoint.y == 0) {
- //
- //image.buffer.data.buffer.blit (0, sourceImage.buffer.data.buffer, 0, Std.int (sourceRect.width * sourceRect.height) * 4);
- //return;
- //
- //}
- //#end
-
- for (row in Std.int (sourceRect.top + sourceImage.offsetY)...Std.int (sourceRect.bottom + sourceImage.offsetY)) {
+ for (y in 0...destView.height) {
- for (column in Std.int (sourceRect.left + sourceImage.offsetX)...Std.int (sourceRect.right + sourceImage.offsetX)) {
+ sourcePosition = sourceView.row (y);
+ destPosition = destView.row (y);
+
+ for (x in 0...destView.width) {
- sourceOffset = (row * sourceStride) + (column * 4);
- offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
+ sourcePixel.readUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
+ sourcePixel.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
- data[offset] = sourceData[sourceOffset];
- data[offset + 1] = sourceData[sourceOffset + 1];
- data[offset + 2] = sourceData[sourceOffset + 2];
- data[offset + 3] = sourceData[sourceOffset + 3];
+ sourcePosition += 4;
+ destPosition += 4;
}
@@ -229,28 +195,93 @@ class ImageDataUtil {
} else {
- var sourceAlpha:Float;
- var destAlpha:Float;
- var outA:Float;
- var oneMinusSourceAlpha:Float;
+ var sourceAlpha, destAlpha, oneMinusSourceAlpha, blendAlpha;
+ var destPixel:RGBA;
- for (row in Std.int (sourceRect.top + sourceImage.offsetY)...Std.int (sourceRect.bottom + sourceImage.offsetY)) {
+ if (alphaImage == null) {
- for (column in Std.int (sourceRect.left + sourceImage.offsetX)...Std.int (sourceRect.right + sourceImage.offsetX)) {
+ for (y in 0...destView.height) {
- sourceOffset = (row * sourceStride) + (column * 4);
- offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
+ sourcePosition = sourceView.row (y);
+ destPosition = destView.row (y);
- sourceAlpha = sourceData[sourceOffset + 3] / 255.0;
- destAlpha = data[offset + 3] / 255.0;
- oneMinusSourceAlpha = (1 - sourceAlpha);
+ for (x in 0...destView.width) {
+
+ sourcePixel.readUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
+ destPixel.readUInt8 (destData, destPosition, destFormat, destPremultiplied);
+
+ sourceAlpha = sourcePixel.a / 255.0;
+ destAlpha = destPixel.a / 255.0;
+ oneMinusSourceAlpha = 1 - sourceAlpha;
+ blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha);
+
+ if (blendAlpha == 0) {
+
+ destPixel = 0;
+
+ } else {
+
+ destPixel.r = RGBA.__clamp[Math.round ((sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.g = RGBA.__clamp[Math.round ((sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.b = RGBA.__clamp[Math.round ((sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.a = RGBA.__clamp[Math.round (blendAlpha * 255.0)];
+
+ }
+
+ destPixel.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
+
+ sourcePosition += 4;
+ destPosition += 4;
+
+ }
- outA = sourceAlpha + destAlpha * oneMinusSourceAlpha;
- data[offset + 0] = __clamp[Math.round ((sourceData[sourceOffset + 0] * sourceAlpha + data[offset + 0] * destAlpha * oneMinusSourceAlpha) / outA)];
- data[offset + 1] = __clamp[Math.round ((sourceData[sourceOffset + 1] * sourceAlpha + data[offset + 1] * destAlpha * oneMinusSourceAlpha) / outA)];
- data[offset + 2] = __clamp[Math.round ((sourceData[sourceOffset + 2] * sourceAlpha + data[offset + 2] * destAlpha * oneMinusSourceAlpha) / outA)];
- data[offset + 3] = __clamp[Math.round (outA * 255.0)];
+ }
+
+ } else {
+
+ var alphaData = alphaImage.buffer.data;
+ var alphaFormat = alphaImage.buffer.format;
+ var alphaPremultiplied = alphaImage.buffer.premultiplied;
+
+ var alphaView = new ImageDataView (alphaImage, new Rectangle (alphaPoint.x, alphaPoint.y, destView.width, destView.height));
+ var alphaPosition, alphaPixel:RGBA;
+
+ for (y in 0...alphaView.height) {
+ sourcePosition = sourceView.row (y);
+ destPosition = destView.row (y);
+ alphaPosition = alphaView.row (y);
+
+ for (x in 0...alphaView.width) {
+
+ sourcePixel.readUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
+ destPixel.readUInt8 (destData, destPosition, destFormat, destPremultiplied);
+ alphaPixel.readUInt8 (alphaData, alphaPosition, alphaFormat, alphaPremultiplied);
+
+ sourceAlpha = alphaPixel.a / 0xFF;
+ destAlpha = destPixel.a / 0xFF;
+ oneMinusSourceAlpha = 1 - sourceAlpha;
+ blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha);
+
+ if (blendAlpha == 0) {
+
+ destPixel = 0;
+
+ } else {
+
+ destPixel.r = RGBA.__clamp[Math.round ((sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.g = RGBA.__clamp[Math.round ((sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.b = RGBA.__clamp[Math.round ((sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)];
+ destPixel.a = RGBA.__clamp[Math.round (blendAlpha * 255.0)];
+
+ }
+
+ destPixel.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
+
+ sourcePosition += 4;
+ destPosition += 4;
+
+ }
}
@@ -267,80 +298,43 @@ class ImageDataUtil {
public static function fillRect (image:Image, rect:Rectangle, color:Int, format:PixelFormat):Void {
- var r, g, b, a;
+ var fillColor:RGBA;
- if (format == ARGB) {
+ switch (format) {
- a = (image.transparent) ? (color >> 24) & 0xFF : 0xFF;
- r = (color >> 16) & 0xFF;
- g = (color >> 8) & 0xFF;
- b = color & 0xFF;
-
- } else {
-
- r = (color >> 24) & 0xFF;
- g = (color >> 16) & 0xFF;
- b = (color >> 8) & 0xFF;
- a = (image.transparent) ? color & 0xFF : 0xFF;
+ case ARGB32: fillColor = (color:ARGB);
+ case BGRA32: fillColor = (color:BGRA);
+ default: fillColor = color;
}
- var rgba = (r | (g << 8) | (b << 16) | (a << 24));
+ if (!image.transparent) {
+
+ fillColor.a = 0xFF;
+
+ }
var data = image.buffer.data;
if (data == null) return;
#if ((cpp || neko) && !disable_cffi)
- if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, rgba); else
+ if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, (fillColor >> 16) & 0xFFFF, (fillColor) & 0xFFFF); else // TODO: Better Int32 solution
#end
{
- if (rect.width == image.buffer.width && rect.height == image.buffer.height && rect.x == 0 && rect.y == 0 && image.offsetX == 0 && image.offsetY == 0) {
+ var format = image.buffer.format;
+ var premultiplied = image.buffer.premultiplied;
+
+ var dataView = new ImageDataView (image, rect);
+ var row;
+
+ for (y in 0...dataView.height) {
- var length = image.buffer.width * image.buffer.height;
+ row = dataView.row (y);
- var j = 0;
- for (i in 0...length) {
+ for (x in 0...dataView.width) {
- j = i * 4;
-
- //#if js
- data[j + 0] = r;
- data[j + 1] = g;
- data[j + 2] = b;
- data[j + 3] = a;
- //#else
- //data.setUInt32 (j, rgba);
- //#end
-
- }
-
- } else {
-
- var stride = image.buffer.width * 4;
- var offset:Int;
-
- var rowStart = Std.int (rect.y + image.offsetY);
- var rowEnd = Std.int (rect.bottom + image.offsetY);
- var columnStart = Std.int (rect.x + image.offsetX);
- var columnEnd = Std.int (rect.right + image.offsetX);
-
- for (row in rowStart...rowEnd) {
-
- for (column in columnStart...columnEnd) {
-
- offset = (row * stride) + (column * 4);
-
- //#if js
- data[offset] = r;
- data[offset + 1] = g;
- data[offset + 2] = b;
- data[offset + 3] = a;
- //#else
- //data.setUInt32 (offset, rgba);
- //#end
-
- }
+ fillColor.writeUInt8 (data, row + (x * 4), format, premultiplied);
}
@@ -358,25 +352,29 @@ class ImageDataUtil {
var data = image.buffer.data;
if (data == null) return;
- if (format == ARGB) color = ((color & 0xFFFFFF) << 8) | ((color >> 24) & 0xFF);
+ if (format == ARGB32) color = ((color & 0xFFFFFF) << 8) | ((color >> 24) & 0xFF);
#if ((cpp || neko) && !disable_cffi)
- if (!System.disableCFFI) lime_image_data_util_flood_fill (image, x, y, color); else
+ if (!System.disableCFFI) lime_image_data_util_flood_fill (image, x, y, (color >> 16) & 0xFFFF, (color) & 0xFFFF); else // TODO: Better Int32 solution
#end
{
- var offset = (((y + image.offsetY) * (image.buffer.width * 4)) + ((x + image.offsetX) * 4));
- var hitColorR = data[offset + 0];
- var hitColorG = data[offset + 1];
- var hitColorB = data[offset + 2];
- var hitColorA = image.transparent ? data[offset + 3] : 0xFF;
+ var format = image.buffer.format;
+ var premultiplied = image.buffer.premultiplied;
- var r = (color >> 24) & 0xFF;
- var g = (color >> 16) & 0xFF;
- var b = (color >> 8) & 0xFF;
- var a = image.transparent ? color & 0xFF : 0xFF;
+ var fillColor:RGBA = color;
- if (hitColorR == r && hitColorG == g && hitColorB == b && hitColorA == a) return;
+ var hitColor:RGBA;
+ hitColor.readUInt8 (data, ((y + image.offsetY) * (image.buffer.width * 4)) + ((x + image.offsetX) * 4), format, premultiplied);
+
+ if (!image.transparent) {
+
+ fillColor.a = 0xFF;
+ hitColor.a = 0xFF;
+
+ }
+
+ if (fillColor == hitColor) return;
var dx = [ 0, -1, 1, 0 ];
var dy = [ -1, 0, 0, 1 ];
@@ -390,15 +388,17 @@ class ImageDataUtil {
queue.push (x);
queue.push (y);
+ var curPointX, curPointY, nextPointX, nextPointY, nextPointOffset, readColor:RGBA;
+
while (queue.length > 0) {
- var curPointY = queue.pop ();
- var curPointX = queue.pop ();
+ curPointY = queue.pop ();
+ curPointX = queue.pop ();
for (i in 0...4) {
- var nextPointX = curPointX + dx[i];
- var nextPointY = curPointY + dy[i];
+ nextPointX = curPointX + dx[i];
+ nextPointY = curPointY + dy[i];
if (nextPointX < minX || nextPointY < minY || nextPointX >= maxX || nextPointY >= maxY) {
@@ -406,14 +406,12 @@ class ImageDataUtil {
}
- var nextPointOffset = (nextPointY * image.width + nextPointX) * 4;
+ nextPointOffset = (nextPointY * image.width + nextPointX) * 4;
+ readColor.readUInt8 (data, nextPointOffset, format, premultiplied);
- if (data[nextPointOffset + 0] == hitColorR && data[nextPointOffset + 1] == hitColorG && data[nextPointOffset + 2] == hitColorB && data[nextPointOffset + 3] == hitColorA) {
+ if (readColor == hitColor) {
- data[nextPointOffset + 0] = r;
- data[nextPointOffset + 1] = g;
- data[nextPointOffset + 2] = b;
- data[nextPointOffset + 3] = a;
+ fillColor.writeUInt8 (data, nextPointOffset, format, premultiplied);
queue.push (nextPointX);
queue.push (nextPointY);
@@ -441,7 +439,7 @@ class ImageDataUtil {
var r, g, b, a;
var mr, mg, mb, ma;
- if (format == ARGB) {
+ if (format == ARGB32) {
a = (image.transparent) ? (color >> 24) & 0xFF : 0xFF;
r = (color >> 16) & 0xFF;
@@ -600,28 +598,16 @@ class ImageDataUtil {
public static function getPixel (image:Image, x:Int, y:Int, format:PixelFormat):Int {
- var data = image.buffer.data;
- var offset = (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4);
- var pixel;
+ var pixel:RGBA;
- if (image.premultiplied) {
-
- var unmultiply = 255.0 / data[offset + 3];
- pixel = __clamp[Std.int (data[offset] * unmultiply)] << 24 | __clamp[Std.int (data[offset + 1] * unmultiply)] << 16 | __clamp[Std.int (data[offset + 2] * unmultiply)] << 8;
-
- } else {
-
- pixel = (data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8);
-
- }
+ pixel.readUInt8 (image.buffer.data, (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4), image.buffer.format, image.buffer.premultiplied);
+ pixel.a = 0;
- if (format == ARGB) {
+ switch (format) {
- return pixel >> 8 & 0xFFFFFF;
-
- } else {
-
- return pixel;
+ case ARGB32: return (pixel:ARGB);
+ case BGRA32: return (pixel:BGRA);
+ default: return pixel;
}
@@ -630,33 +616,15 @@ class ImageDataUtil {
public static function getPixel32 (image:Image, x:Int, y:Int, format:PixelFormat):Int {
- var data = image.buffer.data;
- var offset = (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4);
- var a = (image.transparent ? data[offset + 3] : 0xFF);
- var r, g, b;
+ var pixel:RGBA;
- if (image.premultiplied && a != 0) {
-
- var unmultiply = 255.0 / a;
- r = __clamp[Math.round (data[offset] * unmultiply)];
- g = __clamp[Math.round (data[offset + 1] * unmultiply)];
- b = __clamp[Math.round (data[offset + 2] * unmultiply)];
-
- } else {
-
- r = data[offset];
- g = data[offset + 1];
- b = data[offset + 2];
-
- }
+ pixel.readUInt8 (image.buffer.data, (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4), image.buffer.format, image.buffer.premultiplied);
- if (format == ARGB) {
+ switch (format) {
- return a << 24 | r << 16 | g << 8 | b;
-
- } else {
-
- return r << 24 | g << 16 | b << 8 | a;
+ case ARGB32: return (pixel:ARGB);
+ case BGRA32: return (pixel:BGRA);
+ default: return pixel;
}
@@ -681,73 +649,46 @@ class ImageDataUtil {
#end
{
- //#if (!js && !flash)
- //if (rect.width == image.width && rect.height == image.height && rect.x == 0 && rect.y == 0) {
- //
- //byteArray.blit (0, image.buffer.data.buffer, 0, length * 4);
- //return byteArray;
- //
- //}
- //#end
+ var data = image.buffer.data;
+ var sourceFormat = image.buffer.format;
+ var premultiplied = image.buffer.premultiplied;
- // TODO: optimize if the rect is the same as the full buffer size
+ var dataView = new ImageDataView (image, rect);
+ var position, argb:ARGB, bgra:BGRA, pixel:RGBA;
- var srcData = image.buffer.data;
- var srcStride = Std.int (image.buffer.width * 4);
- var srcPosition = Std.int ((rect.x * 4) + (srcStride * rect.y));
- var srcRowOffset = srcStride - Std.int (4 * rect.width);
- var srcRowEnd = Std.int (4 * (rect.x + rect.width));
-
- #if js
- byteArray.length = length * 4;
+ #if !flash
+ var destPosition = 0;
#end
- if (format == ARGB) {
+ for (y in 0...dataView.height) {
- for (i in 0...length) {
+ position = dataView.row (y);
+
+ for (x in 0...dataView.width) {
- #if flash
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
- #else
- byteArray.__set (i * 4 + 1, srcData[srcPosition++]);
- byteArray.__set (i * 4 + 2, srcData[srcPosition++]);
- byteArray.__set (i * 4 + 3, srcData[srcPosition++]);
- byteArray.__set (i * 4, srcData[srcPosition++]);
- #end
+ pixel.readUInt8 (data, position, sourceFormat, premultiplied);
- if ((srcPosition % srcStride) > srcRowEnd) {
+ switch (format) {
- srcPosition += srcRowOffset;
+ case ARGB32: argb = pixel; pixel = cast argb;
+ case BGRA32: bgra = pixel; pixel = cast bgra;
+ default:
}
- }
-
- } else {
-
- for (i in 0...length) {
-
#if flash
- // TODO
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
- byteArray.writeByte (srcData[srcPosition++]);
+ byteArray.writeByte (pixel.r);
+ byteArray.writeByte (pixel.g);
+ byteArray.writeByte (pixel.b);
+ byteArray.writeByte (pixel.a);
#else
- byteArray.__set (i * 4, srcData[srcPosition++]);
- byteArray.__set (i * 4 + 1, srcData[srcPosition++]);
- byteArray.__set (i * 4 + 2, srcData[srcPosition++]);
- byteArray.__set (i * 4 + 3, srcData[srcPosition++]);
+ byteArray.__set (destPosition++, pixel.r);
+ byteArray.__set (destPosition++, pixel.g);
+ byteArray.__set (destPosition++, pixel.b);
+ byteArray.__set (destPosition++, pixel.a);
#end
- if ((srcPosition % srcStride) > srcRowEnd) {
-
- srcPosition += srcRowOffset;
-
- }
+ position += 4;
}
@@ -770,28 +711,37 @@ class ImageDataUtil {
#end
{
- var rowOffset = Std.int (destPoint.y + image.offsetY - sourceRect.y - sourceImage.offsetY);
- var columnOffset = Std.int (destPoint.x + image.offsetX - sourceRect.x - sourceImage.offsetY);
+ var sourceView = new ImageDataView (sourceImage, sourceRect);
+ var destView = new ImageDataView (image, new Rectangle (destPoint.x, destPoint.y, sourceView.width, sourceView.height));
var sourceData = sourceImage.buffer.data;
- var sourceStride = sourceImage.buffer.width * 4;
- var sourceOffset:Int = 0;
+ var destData = image.buffer.data;
+ var sourceFormat = sourceImage.buffer.format;
+ var destFormat = image.buffer.format;
+ var sourcePremultiplied = sourceImage.buffer.premultiplied;
+ var destPremultiplied = image.buffer.premultiplied;
- var data = image.buffer.data;
- var stride = image.buffer.width * 4;
- var offset:Int = 0;
+ var sourcePosition, destPosition, sourcePixel:RGBA, destPixel:RGBA;
- for (row in Std.int (sourceRect.top + sourceImage.offsetY)...Std.int (sourceRect.bottom + sourceImage.offsetY)) {
+ for (y in 0...destView.height) {
- for (column in Std.int (sourceRect.left + sourceImage.offsetX)...Std.int (sourceRect.right + sourceImage.offsetX)) {
+ sourcePosition = sourceView.row (y);
+ destPosition = destView.row (y);
+
+ for (x in 0...destView.width) {
- sourceOffset = (row * sourceStride) + (column * 4);
- offset = ((row + rowOffset) * stride) + ((column + columnOffset) * 4);
+ sourcePixel.readUInt8 (sourceData, sourcePosition, sourceFormat, sourcePremultiplied);
+ destPixel.readUInt8 (destData, destPosition, destFormat, destPremultiplied);
- data[offset] = Std.int (((sourceData[offset] * redMultiplier) + (data[offset] * (256 - redMultiplier))) / 256);
- data[offset + 1] = Std.int (((sourceData[offset + 1] * greenMultiplier) + (data[offset + 1] * (256 - greenMultiplier))) / 256);
- data[offset + 2] = Std.int (((sourceData[offset + 2] * blueMultiplier) + (data[offset + 2] * (256 - blueMultiplier))) / 256);
- data[offset + 3] = Std.int (((sourceData[offset + 3] * alphaMultiplier) + (data[offset + 3] * (256 - alphaMultiplier))) / 256);
+ destPixel.r = Std.int (((sourcePixel.r * redMultiplier) + (destPixel.r * (256 - redMultiplier))) / 256);
+ destPixel.g = Std.int (((sourcePixel.g * greenMultiplier) + (destPixel.g * (256 - greenMultiplier))) / 256);
+ destPixel.b = Std.int (((sourcePixel.b * blueMultiplier) + (destPixel.b * (256 - blueMultiplier))) / 256);
+ destPixel.a = Std.int (((sourcePixel.a * alphaMultiplier) + (destPixel.a * (256 - alphaMultiplier))) / 256);
+
+ destPixel.writeUInt8 (destData, destPosition, destFormat, destPremultiplied);
+
+ sourcePosition += 4;
+ destPosition += 4;
}
@@ -814,17 +764,14 @@ class ImageDataUtil {
#end
{
- var index, a16;
+ var format = image.buffer.format;
var length = Std.int (data.length / 4);
+ var pixel:RGBA;
for (i in 0...length) {
- index = i * 4;
-
- a16 = __alpha16[data[index + 3]];
- data[index] = (data[index] * a16) >> 16;
- data[index + 1] = (data[index + 1] * a16) >> 16;
- data[index + 2] = (data[index + 2] * a16) >> 16;
+ pixel.readUInt8 (data, i * 4, format, false);
+ pixel.writeUInt8 (data, i * 4, format, true);
}
@@ -860,6 +807,8 @@ class ImageDataUtil {
for (x in 0...newWidth) {
+ // TODO: Handle more color formats
+
u = ((x + 0.5) / newWidth) * imageWidth - 0.5;
v = ((y + 0.5) / newHeight) * imageHeight - 0.5;
@@ -954,21 +903,21 @@ class ImageDataUtil {
switch (image.format) {
- case RGBA:
+ case RGBA32:
r1 = 0;
g1 = 1;
b1 = 2;
a1 = 3;
- case ARGB:
+ case ARGB32:
r1 = 1;
g1 = 2;
b1 = 3;
a1 = 0;
- case BGRA:
+ case BGRA32:
r1 = 2;
g1 = 1;
@@ -979,21 +928,21 @@ class ImageDataUtil {
switch (format) {
- case RGBA:
+ case RGBA32:
r2 = 0;
g2 = 1;
b2 = 2;
a2 = 3;
- case ARGB:
+ case ARGB32:
r2 = 1;
g2 = 2;
b2 = 3;
a2 = 0;
- case BGRA:
+ case BGRA32:
r2 = 2;
g2 = 1;
@@ -1028,14 +977,18 @@ class ImageDataUtil {
public static function setPixel (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
- var data = image.buffer.data;
- var offset = (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4);
- if (format == RGBA) color = color >> 8;
+ var pixel:RGBA;
- data[offset] = (color & 0xFF0000) >>> 16;
- data[offset + 1] = (color & 0x00FF00) >>> 8;
- data[offset + 2] = (color & 0x0000FF);
- if (image.transparent) data[offset + 3] = (0xFF);
+ switch (format) {
+
+ case ARGB32: pixel = (color:ARGB);
+ case BGRA32: pixel = (color:BGRA);
+ default: pixel = color;
+
+ }
+
+ pixel.a = 0xFF;
+ pixel.writeUInt8 (image.buffer.data, (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4), image.buffer.format, image.buffer.premultiplied);
image.dirty = true;
@@ -1044,59 +997,18 @@ class ImageDataUtil {
public static function setPixel32 (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void {
- var data = image.buffer.data;
- var offset = (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4);
- var a, r, g, b;
+ var pixel:RGBA;
- if (format == ARGB) {
+ switch (format) {
- a = image.transparent ? (color >> 24) & 0xFF : 0xFF;
- r = (color >> 16) & 0xFF;
- g = (color >> 8) & 0xFF;
- b = color & 0xFF;
-
- } else {
-
- r = (color >> 24) & 0xFF;
- g = (color >> 16) & 0xFF;
- b = (color >> 8) & 0xFF;
- a = image.transparent ? color & 0xFF : 0xFF;
+ case ARGB32: pixel = (color:ARGB);
+ case BGRA32: pixel = (color:BGRA);
+ default: pixel = color;
}
- // TODO(james4k): do a more sane endianness check, but this has changed
- // in the latest lime anyways.
-
- if (image.transparent && image.premultiplied) {
-
- var a16 = __alpha16[a];
- #if !(ps3 || wiiu)
- data[offset] = (r * a16) >> 16;
- data[offset + 1] = (g * a16) >> 16;
- data[offset + 2] = (b * a16) >> 16;
- data[offset + 3] = a;
- #else
- data[offset + 0] = a;
- data[offset + 1] = (b * a16) >> 16;
- data[offset + 2] = (g * a16) >> 16;
- data[offset + 3] = (r * a16) >> 16;
- #end
-
- } else {
-
- #if !(ps3 || wiiu)
- data[offset] = r;
- data[offset + 1] = g;
- data[offset + 2] = b;
- data[offset + 3] = a;
- #else
- data[offset + 0] = a;
- data[offset + 1] = b;
- data[offset + 2] = g;
- data[offset + 3] = r;
- #end
-
- }
+ if (!image.transparent) pixel.a = 0xFF;
+ pixel.writeUInt8 (image.buffer.data, (4 * (y + image.offsetY) * image.buffer.width + (x + image.offsetX) * 4), image.buffer.format, image.buffer.premultiplied);
image.dirty = true;
@@ -1112,61 +1024,31 @@ class ImageDataUtil {
#end
{
- var len = Math.round (rect.width * rect.height);
-
- //#if (!js && !flash)
- //if (rect.width == image.width && rect.height == image.height && rect.x == 0 && rect.y == 0) {
- //
- //image.buffer.data.buffer.blit (0, byteArray, 0, len * 4);
- //return;
- //
- //}
- //#end
-
- // TODO: optimize when rect is the same as the buffer size
-
var data = image.buffer.data;
- var offset = Math.round (image.buffer.width * (rect.y + image.offsetX) + (rect.x + image.offsetY));
- var pos = offset * 4;
- var boundR = Math.round ((rect.x + rect.width + image.offsetX));
- var width = image.buffer.width;
- var color;
+ var sourceFormat = image.buffer.format;
+ var premultiplied = image.buffer.premultiplied;
+ var dataView = new ImageDataView (image, rect);
+ var row, color, pixel:RGBA;
+ var transparent = image.transparent;
- if (format == ARGB) {
+ for (y in 0...dataView.height) {
- for (i in 0...len) {
-
- if (((pos) % (width * 4)) >= boundR * 4) {
-
- pos += (width - boundR) * 4;
-
- }
+ row = dataView.row (y);
+
+ for (x in 0...dataView.width) {
color = byteArray.readUnsignedInt ();
- data[pos++] = (color & 0xFF0000) >>> 16;
- data[pos++] = (color & 0x0000FF00) >>> 8;
- data[pos++] = (color & 0x000000FF);
- data[pos++] = (color & 0xFF000000) >>> 24;
-
- }
-
- } else {
-
- for (i in 0...len) {
-
- if (((pos) % (width * 4)) >= boundR * 4) {
+ switch (format) {
- pos += (width - boundR) * 4;
+ case ARGB32: pixel = (color:ARGB);
+ case BGRA32: pixel = (color:BGRA);
+ default: pixel = color;
}
- color = byteArray.readUnsignedInt ();
-
- data[pos++] = (color & 0xFF000000) >>> 24;
- data[pos++] = (color & 0xFF0000) >>> 16;
- data[pos++] = (color & 0x0000FF00) >>> 8;
- data[pos++] = (color & 0x000000FF);
+ if (!transparent) pixel.a = 0xFF;
+ pixel.writeUInt8 (data, row + (x * 4), sourceFormat, premultiplied);
}
@@ -1189,24 +1071,14 @@ class ImageDataUtil {
#end
{
- var index, a, unmultiply;
+ var format = image.buffer.format;
var length = Std.int (data.length / 4);
+ var pixel:RGBA;
for (i in 0...length) {
- index = i * 4;
-
- a = data[index + 3];
-
- if (a != 0) {
-
- unmultiply = 255.0 / a;
-
- data[index] = __clamp[Std.int (data[index] * unmultiply)];
- data[index + 1] = __clamp[Std.int (data[index + 1] * unmultiply)];
- data[index + 2] = __clamp[Std.int (data[index + 2] * unmultiply)];
-
- }
+ pixel.readUInt8 (data, i * 4, format, true);
+ pixel.writeUInt8 (data, i * 4, format, false);
}
@@ -1228,9 +1100,9 @@ class ImageDataUtil {
#if (cpp || neko || nodejs)
private static var lime_image_data_util_color_transform = System.load ("lime", "lime_image_data_util_color_transform", 3);
private static var lime_image_data_util_copy_channel = System.load ("lime", "lime_image_data_util_copy_channel", -1);
- private static var lime_image_data_util_copy_pixels = System.load ("lime", "lime_image_data_util_copy_pixels", 5);
- private static var lime_image_data_util_fill_rect = System.load ("lime", "lime_image_data_util_fill_rect", 3);
- private static var lime_image_data_util_flood_fill = System.load ("lime", "lime_image_data_util_flood_fill", 4);
+ private static var lime_image_data_util_copy_pixels = System.load ("lime", "lime_image_data_util_copy_pixels", -1);
+ private static var lime_image_data_util_fill_rect = System.load ("lime", "lime_image_data_util_fill_rect", 4);
+ private static var lime_image_data_util_flood_fill = System.load ("lime", "lime_image_data_util_flood_fill", 5);
private static var lime_image_data_util_get_pixels = System.load ("lime", "lime_image_data_util_get_pixels", 4);
private static var lime_image_data_util_merge = System.load ("lime", "lime_image_data_util_merge", -1);
private static var lime_image_data_util_multiply_alpha = System.load ("lime", "lime_image_data_util_multiply_alpha", 1);
@@ -1242,3 +1114,71 @@ class ImageDataUtil {
}
+
+
+private class ImageDataView {
+
+
+ public var x (default, null):Int;
+ public var y (default, null):Int;
+ public var height (default, null):Int;
+ public var width (default, null):Int;
+
+ private var image:Image;
+ private var offset:Int;
+ private var rect:Rectangle;
+ private var stride:Int;
+
+
+ public function new (image:Image, rect:Rectangle = null) {
+
+ this.image = image;
+
+ if (rect == null) {
+
+ this.rect = image.rect;
+
+ } else {
+
+ if (rect.x < 0) rect.x = 0;
+ if (rect.y < 0) rect.y = 0;
+ if (rect.x + rect.width > image.width) rect.width = image.width - rect.x;
+ if (rect.y + rect.height > image.height) rect.height = image.height - rect.y;
+ if (rect.width < 0) rect.width = 0;
+ if (rect.height < 0) rect.height = 0;
+ this.rect = rect;
+
+ }
+
+ stride = image.buffer.stride;
+
+ x = Math.ceil (this.rect.x);
+ y = Math.ceil (this.rect.y);
+ width = Math.floor (this.rect.width);
+ height = Math.floor (this.rect.height);
+ offset = (stride * (this.y + image.offsetY)) + ((this.x + image.offsetX) * 4);
+
+ }
+
+
+ public function clip (x:Int, y:Int, width:Int, height:Int):Void {
+
+ rect.__contract (x, y, width, height);
+
+ this.x = Math.ceil (rect.x);
+ this.y = Math.ceil (rect.y);
+ this.width = Math.floor (rect.width);
+ this.height = Math.floor (rect.height);
+ offset = (stride * (this.y + image.offsetY)) + ((this.x + image.offsetX) * 4);
+
+ }
+
+
+ public inline function row (y:Int):Int {
+
+ return offset + stride * y;
+
+ }
+
+
+}
diff --git a/lime/math/ColorMatrix.hx b/lime/math/ColorMatrix.hx
index 1250b1c4b..d01becb4c 100644
--- a/lime/math/ColorMatrix.hx
+++ b/lime/math/ColorMatrix.hx
@@ -2,6 +2,7 @@ package lime.math;
import lime.utils.Float32Array;
+import lime.utils.UInt8Array;
#if flash
import flash.geom.ColorTransform;
@@ -89,6 +90,90 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
}
+ public function getAlphaTable ():UInt8Array {
+
+ var table = new UInt8Array (256);
+ var multiplier = alphaMultiplier;
+ var offset = alphaOffset;
+ var value:Int;
+
+ for (i in 0...256) {
+
+ value = Math.floor (i * multiplier + offset);
+ if (value > 0xFF) value = 0xFF;
+ if (value < 0) value = 0;
+ table[i] = value;
+
+ }
+
+ return table;
+
+ }
+
+
+ public function getBlueTable ():UInt8Array {
+
+ var table = new UInt8Array (256);
+ var multiplier = blueMultiplier;
+ var offset = blueOffset;
+ var value:Int;
+
+ for (i in 0...256) {
+
+ value = Math.floor (i * multiplier + offset);
+ if (value > 0xFF) value = 0xFF;
+ if (value < 0) value = 0;
+ table[i] = value;
+
+ }
+
+ return table;
+
+ }
+
+
+ public function getGreenTable ():UInt8Array {
+
+ var table = new UInt8Array (256);
+ var multiplier = greenMultiplier;
+ var offset = greenOffset;
+ var value:Int;
+
+ for (i in 0...256) {
+
+ value = Math.floor (i * multiplier + offset);
+ if (value > 0xFF) value = 0xFF;
+ if (value < 0) value = 0;
+ table[i] = value;
+
+ }
+
+ return table;
+
+ }
+
+
+ public function getRedTable ():UInt8Array {
+
+ var table = new UInt8Array (256);
+ var multiplier = redMultiplier;
+ var offset = redOffset;
+ var value:Int;
+
+ for (i in 0...256) {
+
+ value = Math.floor (i * multiplier + offset);
+ if (value > 0xFF) value = 0xFF;
+ if (value < 0) value = 0;
+ table[i] = value;
+
+ }
+
+ return table;
+
+ }
+
+
private function __toFlashColorTransform ():#if flash ColorTransform #else Dynamic #end {
#if flash
@@ -116,8 +201,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_alphaMultiplier (value:Float):Float {
- this[18] = value;
- return value;
+ return this[18] = value;
}
@@ -131,8 +215,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_alphaOffset (value:Float):Float {
- this[19] = value / 255;
- return value;
+ return this[19] = value / 255;
}
@@ -146,8 +229,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_blueMultiplier (value:Float):Float {
- this[12] = value;
- return value;
+ return this[12] = value;
}
@@ -161,8 +243,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_blueOffset (value:Float):Float {
- this[14] = value / 255;
- return value;
+ return this[14] = value / 255;
}
@@ -198,8 +279,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_greenMultiplier (value:Float):Float {
- this[6] = value;
- return value;
+ return this[6] = value;
}
@@ -213,8 +293,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_greenOffset (value:Float):Float {
- this[9] = value / 255;
- return value;
+ return this[9] = value / 255;
}
@@ -228,8 +307,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_redMultiplier (value:Float):Float {
- this[0] = value;
- return value;
+ return this[0] = value;
}
@@ -243,8 +321,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
private inline function set_redOffset (value:Float):Float {
- this[4] = value / 255;
- return value;
+ return this[4] = value / 255;
}
@@ -258,8 +335,7 @@ abstract ColorMatrix(Float32Array) from Float32Array to Float32Array {
@:arrayAccess public function set (index:Int, value:Float):Float {
- this[index] = value;
- return value;
+ return this[index] = value;
}
diff --git a/lime/math/Rectangle.hx b/lime/math/Rectangle.hx
index d6a39485d..365687837 100644
--- a/lime/math/Rectangle.hx
+++ b/lime/math/Rectangle.hx
@@ -250,8 +250,8 @@ class Rectangle {
}
- var cacheRight = right;
- var cacheBottom = bottom;
+ //var cacheRight = right;
+ //var cacheBottom = bottom;
if (this.x < x) this.x = x;
if (this.y < y) this.y = y;
diff --git a/lime/math/color/ARGB.hx b/lime/math/color/ARGB.hx
new file mode 100644
index 000000000..dcbd16abd
--- /dev/null
+++ b/lime/math/color/ARGB.hx
@@ -0,0 +1,217 @@
+package lime.math.color;
+
+
+import lime.graphics.PixelFormat;
+import lime.utils.UInt32Array;
+import lime.utils.UInt8Array;
+
+
+abstract ARGB(Int) from Int to Int {
+
+
+ private static var a16:Int;
+ private static var unmult:Float;
+
+ public var a (get, set):Int;
+ public var b (get, set):Int;
+ public var g (get, set):Int;
+ public var r (get, set):Int;
+
+
+ public inline function new (argb:Int = 0) {
+
+ this = argb;
+
+ }
+
+
+ public static inline function create (a:Int, r:Int, g:Int, b:Int):ARGB {
+
+ var argb = new ARGB ();
+ argb.set (a, r, g, b);
+ return argb;
+
+ }
+
+
+ public inline function multiplyAlpha () {
+
+ if (a == 0) {
+
+ this = 0;
+
+ } else if (a != 0xFF) {
+
+ a16 = RGBA.__alpha16[a];
+ set (a, (r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16);
+
+ }
+
+ }
+
+
+ public inline function readUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ switch (format) {
+
+ case BGRA32:
+
+ set (data[offset + 1], data[offset], data[offset + 3], data[offset + 2]);
+
+ case RGBA32:
+
+ set (data[offset + 1], data[offset + 2], data[offset + 3], data[offset]);
+
+ case ARGB32:
+
+ set (data[offset + 2], data[offset + 3], data[offset], data[offset + 1]);
+
+ }
+
+ if (premultiplied) {
+
+ unmultiplyAlpha ();
+
+ }
+
+ }
+
+
+ public inline function set (a:Int, r:Int, g:Int, b:Int):Void {
+
+ this = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF);
+
+ }
+
+
+ public inline function unmultiplyAlpha () {
+
+ if (a != 0 && a != 0xFF) {
+
+ unmult = 255.0 / a;
+ set (a, RGBA.__clamp[Math.floor (r * unmult)], RGBA.__clamp[Math.floor (g * unmult)], RGBA.__clamp[Math.floor (b * unmult)]);
+
+ }
+
+ }
+
+
+ public inline function writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ if (premultiplied) {
+
+ multiplyAlpha ();
+
+ }
+
+ switch (format) {
+
+ case BGRA32:
+
+ data[offset] = b;
+ data[offset + 1] = g;
+ data[offset + 2] = r;
+ data[offset + 3] = a;
+
+ case RGBA32:
+
+ data[offset] = r;
+ data[offset + 1] = g;
+ data[offset + 2] = b;
+ data[offset + 3] = a;
+
+ case ARGB32:
+
+ data[offset] = a;
+ data[offset + 1] = r;
+ data[offset + 2] = g;
+ data[offset + 3] = b;
+
+ }
+
+ }
+
+
+ @:from private static inline function __fromBGRA (bgra:BGRA):ARGB {
+
+ return ARGB.create (bgra.a, bgra.r, bgra.g, bgra.b);
+
+ }
+
+
+ @:from private static inline function __fromRGBA (rgba:RGBA):ARGB {
+
+ return ARGB.create (rgba.a, rgba.r, rgba.g, rgba.b);
+
+ }
+
+
+
+
+ // Get & Set Methods
+
+
+
+
+ private inline function get_a ():Int {
+
+ return (this >> 24) & 0xFF;
+
+
+ }
+
+
+ private inline function set_a (value:Int):Int {
+
+ set (value, r, g, b);
+ return value;
+
+ }
+
+
+ private inline function get_b ():Int {
+
+ return this & 0xFF;
+
+ }
+
+
+ private inline function set_b (value:Int):Int {
+
+ set (a, r, g, value);
+ return value;
+
+ }
+
+
+ private inline function get_g ():Int {
+
+ return (this >> 8) & 0xFF;
+
+ }
+
+
+ private inline function set_g (value:Int):Int {
+
+ set (a, r, value, b);
+ return value;
+
+ }
+
+
+ private inline function get_r ():Int {
+
+ return (this >> 16) & 0xFF;
+
+ }
+
+
+ private inline function set_r (value:Int):Int {
+
+ set (a, value, g, b);
+ return value;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/lime/math/color/BGRA.hx b/lime/math/color/BGRA.hx
new file mode 100644
index 000000000..7bba30d32
--- /dev/null
+++ b/lime/math/color/BGRA.hx
@@ -0,0 +1,216 @@
+package lime.math.color;
+
+
+import lime.graphics.PixelFormat;
+import lime.utils.UInt32Array;
+import lime.utils.UInt8Array;
+
+
+abstract BGRA(Int) from Int to Int {
+
+
+ private static var a16:Int;
+ private static var unmult:Float;
+
+ public var a (get, set):Int;
+ public var b (get, set):Int;
+ public var g (get, set):Int;
+ public var r (get, set):Int;
+
+
+ public inline function new (bgra:Int = 0) {
+
+ this = bgra;
+
+ }
+
+
+ public static inline function create (b:Int, g:Int, r:Int, a:Int):BGRA {
+
+ var bgra = new BGRA ();
+ bgra.set (b, g, r, a);
+ return bgra;
+
+ }
+
+
+ public inline function multiplyAlpha () {
+
+ if (a == 0) {
+
+ this = 0;
+
+ } else if (a != 0xFF) {
+
+ a16 = RGBA.__alpha16[a];
+ set ((b * a16) >> 16, (g * a16) >> 16, (r * a16) >> 16, a);
+
+ }
+
+ }
+
+
+ public inline function readUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ switch (format) {
+
+ case BGRA32:
+
+ set (data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
+
+ case RGBA32:
+
+ set (data[offset + 2], data[offset + 1], data[offset], data[offset + 3]);
+
+ case ARGB32:
+
+ set (data[offset + 3], data[offset + 2], data[offset + 1], data[offset]);
+
+ }
+
+ if (premultiplied) {
+
+ unmultiplyAlpha ();
+
+ }
+
+ }
+
+
+ public inline function set (b:Int, g:Int, r:Int, a:Int):Void {
+
+ this = ((b & 0xFF) << 24) | ((g & 0xFF) << 16) | ((r & 0xFF) << 8) | (a & 0xFF);
+
+ }
+
+
+ public inline function unmultiplyAlpha () {
+
+ if (a != 0 && a != 0xFF) {
+
+ unmult = 255.0 / a;
+ set (RGBA.__clamp[Math.floor (b * unmult)], RGBA.__clamp[Math.floor (g * unmult)], RGBA.__clamp[Math.floor (r * unmult)], a);
+
+ }
+
+ }
+
+
+ public inline function writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ if (premultiplied) {
+
+ multiplyAlpha ();
+
+ }
+
+ switch (format) {
+
+ case BGRA32:
+
+ data[offset] = b;
+ data[offset + 1] = g;
+ data[offset + 2] = r;
+ data[offset + 3] = a;
+
+ case RGBA32:
+
+ data[offset] = r;
+ data[offset + 1] = g;
+ data[offset + 2] = b;
+ data[offset + 3] = a;
+
+ case ARGB32:
+
+ data[offset] = a;
+ data[offset + 1] = r;
+ data[offset + 2] = g;
+ data[offset + 3] = b;
+
+ }
+
+ }
+
+
+ @:from private static inline function __fromARGB (argb:ARGB):BGRA {
+
+ return BGRA.create (argb.b, argb.g, argb.r, argb.a);
+
+ }
+
+
+ @:from private static inline function __fromRGBA (rgba:RGBA):BGRA {
+
+ return BGRA.create (rgba.b, rgba.g, rgba.r, rgba.a);
+
+ }
+
+
+
+
+ // Get & Set Methods
+
+
+
+
+ private inline function get_a ():Int {
+
+ return this & 0xFF;
+
+ }
+
+
+ private inline function set_a (value:Int):Int {
+
+ set (b, g, r, value);
+ return value;
+
+ }
+
+
+ private inline function get_b ():Int {
+
+ return (this >> 24) & 0xFF;
+
+ }
+
+
+ private inline function set_b (value:Int):Int {
+
+ set (value, g, r, a);
+ return value;
+
+ }
+
+
+ private inline function get_g ():Int {
+
+ return (this >> 16) & 0xFF;
+
+ }
+
+
+ private inline function set_g (value:Int):Int {
+
+ set (b, value, r, a);
+ return value;
+
+ }
+
+
+ private inline function get_r ():Int {
+
+ return (this >> 8) & 0xFF;
+
+ }
+
+
+ private inline function set_r (value:Int):Int {
+
+ set (b, g, value, a);
+ return value;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/lime/math/color/RGBA.hx b/lime/math/color/RGBA.hx
new file mode 100644
index 000000000..6f6753dec
--- /dev/null
+++ b/lime/math/color/RGBA.hx
@@ -0,0 +1,251 @@
+package lime.math.color;
+
+
+import lime.graphics.PixelFormat;
+import lime.utils.UInt32Array;
+import lime.utils.UInt8Array;
+
+@:allow(lime.math.color)
+
+
+abstract RGBA(Int) from Int to Int {
+
+
+ private static var __alpha16:UInt32Array;
+ private static var __clamp:UInt8Array;
+ private static var a16:Int;
+ private static var unmult:Float;
+
+ public var a (get, set):Int;
+ public var b (get, set):Int;
+ public var g (get, set):Int;
+ public var r (get, set):Int;
+
+
+ private static function __init__ ():Void {
+
+ __alpha16 = new UInt32Array (256);
+
+ for (i in 0...256) {
+
+ __alpha16[i] = Math.ceil ((i) * ((1 << 16) / 0xFF));
+
+ }
+
+ __clamp = new UInt8Array (0xFF + 0xFF);
+
+ for (i in 0...0xFF) {
+
+ __clamp[i] = i;
+
+ }
+
+ for (i in 0xFF...(0xFF + 0xFF + 1)) {
+
+ __clamp[i] = 0xFF;
+
+ }
+
+ }
+
+
+ public inline function new (rgba:Int = 0) {
+
+ this = rgba;
+
+ }
+
+
+ public static inline function create (r:Int, g:Int, b:Int, a:Int):RGBA {
+
+ var rgba = new RGBA ();
+ rgba.set (r, g, b, a);
+ return rgba;
+
+ }
+
+
+ public inline function multiplyAlpha () {
+
+ if (a == 0) {
+
+ if (this != 0) {
+
+ this = 0;
+
+ }
+
+ } else if (a != 0xFF) {
+
+ a16 = __alpha16[a];
+ set ((r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16, a);
+
+ }
+
+ }
+
+
+ public inline function readUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ switch (format) {
+
+ case BGRA32:
+
+ set (data[offset + 2], data[offset + 1], data[offset], data[offset + 3]);
+
+ case RGBA32:
+
+ set (data[offset], data[offset + 1], data[offset + 2], data[offset + 3]);
+
+ case ARGB32:
+
+ set (data[offset + 1], data[offset + 2], data[offset + 3], data[offset]);
+
+ }
+
+ if (premultiplied) {
+
+ unmultiplyAlpha ();
+
+ }
+
+ }
+
+
+ public inline function set (r:Int, g:Int, b:Int, a:Int):Void {
+
+ this = ((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF);
+
+ }
+
+
+ public inline function unmultiplyAlpha () {
+
+ if (a != 0 && a != 0xFF) {
+
+ unmult = 255.0 / a;
+ set (__clamp[Math.round (r * unmult)], __clamp[Math.round (g * unmult)], __clamp[Math.round (b * unmult)], a);
+
+ }
+
+ }
+
+
+ public inline function writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void {
+
+ if (premultiplied) {
+
+ multiplyAlpha ();
+
+ }
+
+ switch (format) {
+
+ case BGRA32:
+
+ data[offset] = b;
+ data[offset + 1] = g;
+ data[offset + 2] = r;
+ data[offset + 3] = a;
+
+ case RGBA32:
+
+ data[offset] = r;
+ data[offset + 1] = g;
+ data[offset + 2] = b;
+ data[offset + 3] = a;
+
+ case ARGB32:
+
+ data[offset] = a;
+ data[offset + 1] = r;
+ data[offset + 2] = g;
+ data[offset + 3] = b;
+
+ }
+
+ }
+
+
+ @:from private static inline function __fromARGB (argb:ARGB):RGBA {
+
+ return RGBA.create (argb.r, argb.g, argb.b, argb.a);
+
+ }
+
+
+ @:from private static inline function __fromBGRA (bgra:BGRA):RGBA {
+
+ return RGBA.create (bgra.r, bgra.g, bgra.b, bgra.a);
+
+ }
+
+
+
+
+ // Get & Set Methods
+
+
+
+
+ private inline function get_a ():Int {
+
+ return this & 0xFF;
+
+ }
+
+
+ private inline function set_a (value:Int):Int {
+
+ set (r, g, b, value);
+ return value;
+
+ }
+
+
+ private inline function get_b ():Int {
+
+ return (this >> 8) & 0xFF;
+
+ }
+
+
+ private inline function set_b (value:Int):Int {
+
+ set (r, g, value, a);
+ return value;
+
+ }
+
+
+ private inline function get_g ():Int {
+
+ return (this >> 16) & 0xFF;
+
+ }
+
+
+ private inline function set_g (value:Int):Int {
+
+ set (r, value, b, a);
+ return value;
+
+ }
+
+
+ private inline function get_r ():Int {
+
+ return (this >> 24) & 0xFF;
+
+ }
+
+
+ private inline function set_r (value:Int):Int {
+
+ set (value, g, b, a);
+ return value;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/lime/net/curl/CURLCode.hx b/lime/net/curl/CURLCode.hx
index 3e647ada5..0d0a5b9e8 100644
--- a/lime/net/curl/CURLCode.hx
+++ b/lime/net/curl/CURLCode.hx
@@ -1,7 +1,7 @@
package lime.net.curl;
-@:enum abstract CURLCode(Int) {
+@:enum abstract CURLCode(Int) from Int to Int {
var OK = 0;
var UNSUPPORTED_PROTOCOL = 1;
diff --git a/lime/net/curl/CURLInfo.hx b/lime/net/curl/CURLInfo.hx
index 238162c34..17a1ce8e2 100644
--- a/lime/net/curl/CURLInfo.hx
+++ b/lime/net/curl/CURLInfo.hx
@@ -1,7 +1,7 @@
package lime.net.curl;
-@:enum abstract CURLInfo(Int) {
+@:enum abstract CURLInfo(Int) from Int to Int {
var NONE = 0;
var EFFECTIVE_URL = 0x100000 + 1;
diff --git a/lime/net/curl/CURLOption.hx b/lime/net/curl/CURLOption.hx
index e3e3ecd3c..075e7d6ef 100644
--- a/lime/net/curl/CURLOption.hx
+++ b/lime/net/curl/CURLOption.hx
@@ -1,7 +1,7 @@
package lime.net.curl;
-@:enum abstract CURLOption(Int) {
+@:enum abstract CURLOption(Int) from Int to Int {
//var FILE = 10001;
//var WRITEDATA = 10001;
diff --git a/lime/net/curl/CURLVersion.hx b/lime/net/curl/CURLVersion.hx
index 008bc2a9f..052952b73 100644
--- a/lime/net/curl/CURLVersion.hx
+++ b/lime/net/curl/CURLVersion.hx
@@ -1,7 +1,7 @@
package lime.net.curl;
-@:enum abstract CURLVersion(Int) {
+@:enum abstract CURLVersion(Int) from Int to Int {
var FIRST = 0;
var SECOND = 1;
diff --git a/lime/project/HXProject.hx b/lime/project/HXProject.hx
index 1090ac437..46c11a312 100644
--- a/lime/project/HXProject.hx
+++ b/lime/project/HXProject.hx
@@ -136,7 +136,7 @@ class HXProject {
defaultWindow.width = 0;
defaultWindow.height = 0;
- defaultWindow.fps = 0;
+ defaultWindow.fps = 60;
case ANDROID, BLACKBERRY, IOS, TIZEN, WEBOS:
diff --git a/lime/project/Library.hx b/lime/project/Library.hx
index 06ccad052..d6d8597f6 100644
--- a/lime/project/Library.hx
+++ b/lime/project/Library.hx
@@ -10,12 +10,13 @@ class Library {
public var embed:Null;
public var generate:Bool;
public var name:String;
+ public var prefix:String;
public var preload:Bool;
public var sourcePath:String;
public var type:String;
- public function new (sourcePath:String, name:String = "", type:String = null, embed:Null = null, preload:Bool = false, generate:Bool = false) {
+ public function new (sourcePath:String, name:String = "", type:String = null, embed:Null = null, preload:Bool = false, generate:Bool = false, prefix:String = "") {
this.sourcePath = sourcePath;
@@ -33,13 +34,14 @@ class Library {
this.embed = embed;
this.preload = preload;
this.generate = generate;
+ this.prefix = prefix;
}
public function clone ():Library {
- return new Library (sourcePath, name, type, embed, preload, generate);
+ return new Library (sourcePath, name, type, embed, preload, generate, prefix);
}
diff --git a/lime/project/ProjectXMLParser.hx b/lime/project/ProjectXMLParser.hx
index 9692dda16..64fb29587 100644
--- a/lime/project/ProjectXMLParser.hx
+++ b/lime/project/ProjectXMLParser.hx
@@ -1214,6 +1214,7 @@ class ProjectXMLParser extends HXProject {
var embed:Null = null;
var preload = false;
var generate = false;
+ var prefix = "";
if (element.has.name) {
@@ -1251,7 +1252,13 @@ class ProjectXMLParser extends HXProject {
}
- libraries.push (new Library (path, name, type, embed, preload, generate));
+ if (element.has.prefix) {
+
+ prefix = substitute (element.att.prefix);
+
+ }
+
+ libraries.push (new Library (path, name, type, embed, preload, generate, prefix));
}
diff --git a/lime/system/BackgroundWorker.hx b/lime/system/BackgroundWorker.hx
index 5888067ab..d1ffe3643 100644
--- a/lime/system/BackgroundWorker.hx
+++ b/lime/system/BackgroundWorker.hx
@@ -74,7 +74,7 @@ class BackgroundWorker {
}
- public function sendComplete (message:Dynamic):Void {
+ public function sendComplete (message:Dynamic = null):Void {
#if (cpp || neko)
@@ -95,7 +95,7 @@ class BackgroundWorker {
}
- public function sendError (message:Dynamic):Void {
+ public function sendError (message:Dynamic = null):Void {
#if (cpp || neko)
@@ -116,7 +116,7 @@ class BackgroundWorker {
}
- public function sendProgress (message:Dynamic):Void {
+ public function sendProgress (message:Dynamic = null):Void {
#if (cpp || neko)
diff --git a/lime/system/ThreadPool.hx b/lime/system/ThreadPool.hx
new file mode 100644
index 000000000..f60ee3c17
--- /dev/null
+++ b/lime/system/ThreadPool.hx
@@ -0,0 +1,240 @@
+package lime.system;
+
+
+import lime.app.Application;
+import lime.app.Event;
+
+#if cpp
+import cpp.vm.Deque;
+import cpp.vm.Thread;
+#elseif neko
+import neko.vm.Deque;
+import neko.vm.Thread;
+#end
+
+
+class ThreadPool {
+
+
+ public var currentThreads (default, null):Int;
+ public var doWork = new EventDynamic->Void> ();
+ public var maxThreads:Int;
+ public var minThreads:Int;
+ public var onComplete = new EventDynamic->Void> ();
+ public var onError = new EventDynamic->Void> ();
+ public var onProgress = new EventDynamic->Void> ();
+
+ #if (cpp || neko)
+ private var __workCompleted:Int;
+ private var __workIncoming = new Deque ();
+ private var __workQueued:Int;
+ private var __workResult = new Deque ();
+ #end
+
+
+ public function new (minThreads:Int = 0, maxThreads:Int = 1) {
+
+ this.minThreads = minThreads;
+ this.maxThreads = maxThreads;
+
+ currentThreads = 0;
+
+ #if (cpp || neko)
+ __workQueued = 0;
+ __workCompleted = 0;
+ #end
+
+ }
+
+
+ //public function cancel (id:String):Void {
+ //
+ //
+ //
+ //}
+
+
+ //public function isCanceled (id:String):Bool {
+ //
+ //
+ //
+ //}
+
+
+ public function queue (id:String, message:Dynamic = null):Void {
+
+ #if (cpp || neko)
+
+ __workIncoming.add (new ThreadPoolMessage (WORK, id, message));
+ __workQueued++;
+
+ if (currentThreads < maxThreads && currentThreads < (__workQueued - __workCompleted)) {
+
+ currentThreads++;
+ Thread.create (__doWork);
+
+ }
+
+ if (!Application.current.onUpdate.has (__update)) {
+
+ Application.current.onUpdate.add (__update);
+
+ }
+
+ #else
+
+ doWork.dispatch (id, message);
+
+ #end
+
+ }
+
+
+ public function sendComplete (id:String, message:Dynamic = null):Void {
+
+ #if (cpp || neko)
+ __workResult.add (new ThreadPoolMessage (COMPLETE, id, message));
+ #else
+ onComplete.dispatch (id, message);
+ #end
+
+ }
+
+
+ public function sendError (id:String, message:Dynamic = null):Void {
+
+ #if (cpp || neko)
+ __workResult.add (new ThreadPoolMessage (ERROR, id, message));
+ #else
+ onError.dispatch (id, message);
+ #end
+
+ }
+
+
+ public function sendProgress (id:String, message:Dynamic = null):Void {
+
+ #if (cpp || neko)
+ __workResult.add (new ThreadPoolMessage (PROGRESS, id, message));
+ #else
+ onProgress.dispatch (id, message);
+ #end
+
+ }
+
+
+ #if (cpp || neko)
+
+ private function __doWork ():Void {
+
+ while (true) {
+
+ var message = __workIncoming.pop (true);
+
+ if (message.type == WORK) {
+
+ doWork.dispatch (message.id, message.message);
+
+ } else if (message.type == EXIT) {
+
+ break;
+
+ }
+
+ }
+
+ }
+
+
+ private function __update (deltaTime:Int):Void {
+
+ if (__workQueued > __workCompleted) {
+
+ var message = __workResult.pop (false);
+
+ while (message != null) {
+
+ switch (message.type) {
+
+ case PROGRESS:
+
+ onProgress.dispatch (message.id, message.message);
+
+ case COMPLETE, ERROR:
+
+ __workCompleted++;
+
+ if (currentThreads > (__workQueued - __workCompleted) || currentThreads > maxThreads) {
+
+ currentThreads--;
+ __workIncoming.add (new ThreadPoolMessage (EXIT, null, null));
+
+ }
+
+ if (message.type == COMPLETE) {
+
+ onComplete.dispatch (message.id, message.message);
+
+ } else {
+
+ onError.dispatch (message.id, message.message);
+
+ }
+
+ default:
+
+ }
+
+ message = __workResult.pop (false);
+
+ }
+
+ } else {
+
+ // TODO: Add sleep if keeping minThreads running with no work?
+
+ if (currentThreads == 0 && minThreads <= 0) {
+
+ Application.current.onUpdate.remove (__update);
+
+ }
+
+ }
+
+ }
+
+ #end
+
+
+}
+
+
+private enum ThreadPoolMessageType {
+
+ COMPLETE;
+ ERROR;
+ EXIT;
+ PROGRESS;
+ WORK;
+
+}
+
+
+private class ThreadPoolMessage {
+
+
+ public var id:String;
+ public var message:Dynamic;
+ public var type:ThreadPoolMessageType;
+
+
+ public function new (type:ThreadPoolMessageType, id:String, message:Dynamic) {
+
+ this.type = type;
+ this.id = id;
+ this.message = message;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/lime/text/TextLayout.hx b/lime/text/TextLayout.hx
index 71f552b06..f1efc1f08 100644
--- a/lime/text/TextLayout.hx
+++ b/lime/text/TextLayout.hx
@@ -100,15 +100,18 @@ class TextLayout {
@:noCompletion private function get_positions ():Array {
- if ( __dirty )
- {
+ if (__dirty) {
+
__dirty = false;
- __position();
+ __position ();
+
}
return positions;
+
}
+
@:noCompletion private function get_direction ():TextDirection {
return __direction;
diff --git a/lime/tools/helpers/FlashHelper.hx b/lime/tools/helpers/FlashHelper.hx
index 1c931733d..3e052431e 100644
--- a/lime/tools/helpers/FlashHelper.hx
+++ b/lime/tools/helpers/FlashHelper.hx
@@ -1012,7 +1012,7 @@ class FlashHelper {
}
- Sys.sleep (1);
+ Sys.sleep (0.3);
}
diff --git a/lime/tools/helpers/IconHelper.hx b/lime/tools/helpers/IconHelper.hx
index af6f82972..1b4e5db4e 100644
--- a/lime/tools/helpers/IconHelper.hx
+++ b/lime/tools/helpers/IconHelper.hx
@@ -122,7 +122,7 @@ class IconHelper {
for (c in 0...4) out.writeByte (code.charCodeAt(c));
var n = s * s;
- var pixels = image.getPixels (new Rectangle (0, 0, s, s), ARGB);
+ var pixels = image.getPixels (new Rectangle (0, 0, s, s), ARGB32);
var bytes_r = packBits (pixels, 1, s * s);
var bytes_g = packBits (pixels, 2, s * s);
diff --git a/lime/tools/platforms/AndroidPlatform.hx b/lime/tools/platforms/AndroidPlatform.hx
index 3495b9e40..97de3b7d0 100644
--- a/lime/tools/platforms/AndroidPlatform.hx
+++ b/lime/tools/platforms/AndroidPlatform.hx
@@ -16,6 +16,7 @@ import lime.tools.helpers.ProcessHelper;
import lime.project.Architecture;
import lime.project.AssetType;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.PlatformTarget;
import sys.io.File;
import sys.FileSystem;
@@ -322,10 +323,17 @@ class AndroidPlatform extends PlatformTarget {
var iconTypes = [ "ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi" ];
var iconSizes = [ 36, 48, 72, 96, 144, 192 ];
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
for (i in 0...iconTypes.length) {
- if (IconHelper.createIcon (project.icons, iconSizes[i], iconSizes[i], destination + "/res/drawable-" + iconTypes[i] + "/icon.png")) {
+ if (IconHelper.createIcon (icons, iconSizes[i], iconSizes[i], destination + "/res/drawable-" + iconTypes[i] + "/icon.png")) {
context.HAS_ICON = true;
@@ -333,7 +341,7 @@ class AndroidPlatform extends PlatformTarget {
}
- IconHelper.createIcon (project.icons, 732, 412, destination + "/res/drawable-xhdpi/ouya_icon.png");
+ IconHelper.createIcon (icons, 732, 412, destination + "/res/drawable-xhdpi/ouya_icon.png");
var packageDirectory = project.meta.packageName;
packageDirectory = destination + "/src/" + packageDirectory.split (".").join ("/");
diff --git a/lime/tools/platforms/BlackBerryPlatform.hx b/lime/tools/platforms/BlackBerryPlatform.hx
index c2c3fbaef..04387b3b1 100644
--- a/lime/tools/platforms/BlackBerryPlatform.hx
+++ b/lime/tools/platforms/BlackBerryPlatform.hx
@@ -16,6 +16,7 @@ import lime.tools.helpers.ProcessHelper;
import lime.project.AssetType;
import lime.project.Haxelib;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.NDLL;
import lime.project.PlatformTarget;
import sys.io.File;
@@ -320,9 +321,17 @@ class BlackBerryPlatform extends PlatformTarget {
context.ICONS = [];
context.HAS_ICON = false;
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
for (size in [ 114, 86 ]) {
- if (IconHelper.createIcon (project.icons, size, size, PathHelper.combine (destination, "icon-" + size + ".png"))) {
+ if (IconHelper.createIcon (icons, size, size, PathHelper.combine (destination, "icon-" + size + ".png"))) {
context.ICONS.push ("icon-" + size + ".png");
context.HAS_ICON = true;
diff --git a/lime/tools/platforms/FirefoxPlatform.hx b/lime/tools/platforms/FirefoxPlatform.hx
index 4e2543024..597f180f3 100644
--- a/lime/tools/platforms/FirefoxPlatform.hx
+++ b/lime/tools/platforms/FirefoxPlatform.hx
@@ -8,6 +8,7 @@ import lime.tools.helpers.IconHelper;
import lime.tools.helpers.PathHelper;
import lime.tools.helpers.LogHelper;
import lime.project.HXProject;
+import lime.project.Icon;
import sys.FileSystem;
@@ -68,10 +69,17 @@ class FirefoxPlatform extends HTML5Platform {
FileHelper.recursiveCopyTemplate (project.templatePaths, "firefox/template", destination, context);
var sizes = [ 32, 48, 60, 64, 128, 512 ];
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
for (size in sizes) {
- IconHelper.createIcon (project.icons, size, size, PathHelper.combine (destination, "icon-" + size + ".png"));
+ IconHelper.createIcon (icons, size, size, PathHelper.combine (destination, "icon-" + size + ".png"));
}
diff --git a/lime/tools/platforms/FlashPlatform.hx b/lime/tools/platforms/FlashPlatform.hx
index e10e5dffc..cdd9cf8ee 100644
--- a/lime/tools/platforms/FlashPlatform.hx
+++ b/lime/tools/platforms/FlashPlatform.hx
@@ -8,6 +8,7 @@ import lime.tools.helpers.CompatibilityHelper;
import lime.tools.helpers.DeploymentHelper;
import lime.tools.helpers.FileHelper;
import lime.tools.helpers.FlashHelper;
+import lime.tools.helpers.LogHelper;
import lime.tools.helpers.PathHelper;
import lime.tools.helpers.PlatformHelper;
import lime.tools.helpers.ProcessHelper;
@@ -172,6 +173,12 @@ class FlashPlatform extends PlatformTarget {
}
+ if (LogHelper.verbose) {
+
+ project.haxedefs.set ("verbose", 1);
+
+ }
+
var context = project.templateContext;
context.WIN_FLASHBACKGROUND = StringTools.hex (project.window.background, 6);
var assets:Array = cast context.assets;
diff --git a/lime/tools/platforms/HTML5Platform.hx b/lime/tools/platforms/HTML5Platform.hx
index c204ddea8..caa00cd15 100644
--- a/lime/tools/platforms/HTML5Platform.hx
+++ b/lime/tools/platforms/HTML5Platform.hx
@@ -171,6 +171,12 @@ class HTML5Platform extends PlatformTarget {
}
+ if (LogHelper.verbose) {
+
+ project.haxedefs.set ("verbose", 1);
+
+ }
+
var context = project.templateContext;
context.WIN_FLASHBACKGROUND = StringTools.hex (project.window.background, 6);
diff --git a/lime/tools/platforms/IOSPlatform.hx b/lime/tools/platforms/IOSPlatform.hx
index 6c269f631..98fe8c4a6 100644
--- a/lime/tools/platforms/IOSPlatform.hx
+++ b/lime/tools/platforms/IOSPlatform.hx
@@ -23,6 +23,7 @@ import lime.project.Asset;
import lime.project.AssetType;
import lime.project.Haxelib;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.Keystore;
import lime.project.NDLL;
import lime.project.Platform;
@@ -384,15 +385,23 @@ class IOSPlatform extends PlatformTarget {
{ name : "Icon-76@2x.png", size : 152 },
{ name : "Icon-60@3x.png", size : 180 },
];
-
+
context.HAS_ICON = true;
var iconPath = PathHelper.combine (projectDirectory, "Images.xcassets/AppIcon.appiconset");
PathHelper.mkdir (iconPath);
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
for (iconSize in iconSizes) {
- if (!IconHelper.createIcon (project.icons, iconSize.size, iconSize.size, PathHelper.combine (iconPath, iconSize.name))) {
+ if (!IconHelper.createIcon (icons, iconSize.size, iconSize.size, PathHelper.combine (iconPath, iconSize.name))) {
context.HAS_ICON = false;
diff --git a/lime/tools/platforms/LinuxPlatform.hx b/lime/tools/platforms/LinuxPlatform.hx
index 87e2752ab..621c931e4 100644
--- a/lime/tools/platforms/LinuxPlatform.hx
+++ b/lime/tools/platforms/LinuxPlatform.hx
@@ -7,6 +7,7 @@ import lime.tools.helpers.AssetHelper;
import lime.tools.helpers.CPPHelper;
import lime.tools.helpers.DeploymentHelper;
import lime.tools.helpers.FileHelper;
+import lime.tools.helpers.LogHelper;
import lime.tools.helpers.NekoHelper;
import lime.tools.helpers.NodeJSHelper;
import lime.tools.helpers.PathHelper;
@@ -273,6 +274,12 @@ class LinuxPlatform extends PlatformTarget {
var arguments = additionalArguments.copy ();
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
if (targetType == "nodejs") {
NodeJSHelper.run (project, targetDirectory + "/bin/ApplicationMain.js", arguments);
diff --git a/lime/tools/platforms/MacPlatform.hx b/lime/tools/platforms/MacPlatform.hx
index d09faa683..8b7e8f916 100644
--- a/lime/tools/platforms/MacPlatform.hx
+++ b/lime/tools/platforms/MacPlatform.hx
@@ -9,6 +9,7 @@ import lime.tools.helpers.DeploymentHelper;
import lime.tools.helpers.FileHelper;
import lime.tools.helpers.IconHelper;
import lime.tools.helpers.JavaHelper;
+import lime.tools.helpers.LogHelper;
import lime.tools.helpers.NekoHelper;
import lime.tools.helpers.NodeJSHelper;
import lime.tools.helpers.PathHelper;
@@ -18,6 +19,7 @@ import lime.project.AssetType;
import lime.project.Architecture;
import lime.project.Haxelib;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.Platform;
import lime.project.PlatformTarget;
import sys.io.File;
@@ -244,6 +246,12 @@ class MacPlatform extends PlatformTarget {
var arguments = additionalArguments.copy ();
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
if (targetType == "nodejs") {
NodeJSHelper.run (project, executableDirectory + "/ApplicationMain.js", arguments);
@@ -310,7 +318,15 @@ class MacPlatform extends PlatformTarget {
FileHelper.copyFileTemplate (project.templatePaths, "mac/Info.plist", targetDirectory + "/bin/" + project.app.file + ".app/Contents/Info.plist", context);
FileHelper.copyFileTemplate (project.templatePaths, "mac/Entitlements.plist", targetDirectory + "/bin/" + project.app.file + ".app/Contents/Entitlements.plist", context);
- context.HAS_ICON = IconHelper.createMacIcon (project.icons, PathHelper.combine (contentDirectory,"icon.icns"));
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ context.HAS_ICON = IconHelper.createMacIcon (icons, PathHelper.combine (contentDirectory, "icon.icns"));
for (asset in project.assets) {
diff --git a/lime/tools/platforms/TizenPlatform.hx b/lime/tools/platforms/TizenPlatform.hx
index 8df063698..d51e47290 100644
--- a/lime/tools/platforms/TizenPlatform.hx
+++ b/lime/tools/platforms/TizenPlatform.hx
@@ -13,6 +13,7 @@ import lime.tools.helpers.ProcessHelper;
import lime.tools.helpers.TizenHelper;
import lime.project.AssetType;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.PlatformTarget;
import sys.io.File;
import sys.FileSystem;
@@ -180,7 +181,15 @@ class TizenPlatform extends PlatformTarget {
PathHelper.mkdir (destination + "shared/res/screen-density-xhigh");
- if (IconHelper.createIcon (project.icons, 117, 117, PathHelper.combine (destination + "shared/res/screen-density-xhigh", "mainmenu.png"))) {
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ if (IconHelper.createIcon (icons, 117, 117, PathHelper.combine (destination + "shared/res/screen-density-xhigh", "mainmenu.png"))) {
context.APP_ICON = "mainmenu.png";
diff --git a/lime/tools/platforms/WebOSPlatform.hx b/lime/tools/platforms/WebOSPlatform.hx
index 288b65829..7e857b496 100644
--- a/lime/tools/platforms/WebOSPlatform.hx
+++ b/lime/tools/platforms/WebOSPlatform.hx
@@ -13,6 +13,7 @@ import lime.tools.helpers.ProcessHelper;
import lime.tools.helpers.WebOSHelper;
import lime.project.AssetType;
import lime.project.HXProject;
+import lime.project.Icon;
import lime.project.PlatformTarget;
import sys.io.File;
import sys.FileSystem;
@@ -151,7 +152,15 @@ class WebOSPlatform extends PlatformTarget {
var context = project.templateContext;
context.CPP_DIR = targetDirectory + "/obj";
- if (IconHelper.createIcon (project.icons, 64, 64, PathHelper.combine (destination, "icon.png"))) {
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
+ if (IconHelper.createIcon (icons, 64, 64, PathHelper.combine (destination, "icon.png"))) {
context.APP_ICON = "icon.png";
diff --git a/lime/tools/platforms/WindowsPlatform.hx b/lime/tools/platforms/WindowsPlatform.hx
index 60d85a3d9..f6e11c1bc 100644
--- a/lime/tools/platforms/WindowsPlatform.hx
+++ b/lime/tools/platforms/WindowsPlatform.hx
@@ -3,11 +3,13 @@ package lime.tools.platforms;
import haxe.io.Path;
import haxe.Template;
+import lime.project.Icon;
import lime.tools.helpers.AssetHelper;
import lime.tools.helpers.CPPHelper;
import lime.tools.helpers.DeploymentHelper;
import lime.tools.helpers.FileHelper;
import lime.tools.helpers.IconHelper;
+import lime.tools.helpers.LogHelper;
import lime.tools.helpers.NekoHelper;
import lime.tools.helpers.NodeJSHelper;
import lime.tools.helpers.PathHelper;
@@ -94,6 +96,14 @@ class WindowsPlatform extends PlatformTarget {
}
+ var icons = project.icons;
+
+ if (icons.length == 0) {
+
+ icons = [ new Icon (PathHelper.findTemplate (project.templatePaths, "default/icon.svg")) ];
+
+ }
+
//IconHelper.createIcon (project.icons, 32, 32, PathHelper.combine (applicationDirectory, "icon.png"));
if (targetType == "neko") {
@@ -102,7 +112,7 @@ class WindowsPlatform extends PlatformTarget {
var iconPath = PathHelper.combine (applicationDirectory, "icon.ico");
- if (!IconHelper.createWindowsIcon (project.icons, iconPath)) {
+ if (!IconHelper.createWindowsIcon (icons, iconPath)) {
iconPath = null;
@@ -148,7 +158,7 @@ class WindowsPlatform extends PlatformTarget {
var iconPath = PathHelper.combine (applicationDirectory, "icon.ico");
- if (IconHelper.createWindowsIcon (project.icons, iconPath) && PlatformHelper.hostPlatform == WINDOWS) {
+ if (IconHelper.createWindowsIcon (icons, iconPath) && PlatformHelper.hostPlatform == WINDOWS) {
var templates = [ PathHelper.getHaxelib (new Haxelib ("lime")) + "/templates" ].concat (project.templatePaths);
ProcessHelper.runCommand ("", PathHelper.findTemplate (templates, "bin/ReplaceVistaIcon.exe"), [ executablePath, iconPath, "1" ], true, true);
@@ -231,6 +241,12 @@ class WindowsPlatform extends PlatformTarget {
var arguments = additionalArguments.copy ();
+ if (LogHelper.verbose) {
+
+ arguments.push ("-verbose");
+
+ }
+
if (targetType == "nodejs") {
NodeJSHelper.run (project, targetDirectory + "/bin/ApplicationMain.js", arguments);
diff --git a/lime/utils/ArrayBufferView.hx b/lime/utils/ArrayBufferView.hx
index c3faa486a..117c90b1e 100644
--- a/lime/utils/ArrayBufferView.hx
+++ b/lime/utils/ArrayBufferView.hx
@@ -130,7 +130,7 @@ class ArrayBufferView {
public function set( ?view:ArrayBufferView, ?array:Array, offset:Int = 0 ) : Void {
if(view != null && array == null) {
- buffer.blit( toByteLength(offset), view.buffer, view.byteOffset, view.buffer.length );
+ buffer.blit( toByteLength(offset), view.buffer, view.byteOffset, view.byteLength );
} else if(array != null && view == null) {
copyFromArray(cast array, offset);
} else {
@@ -241,7 +241,9 @@ class ArrayBufferView {
#if !no_typedarray_inline inline #end
function toString() {
-
+
+ if (this == null) return null;
+
var name =
switch(type) {
case Int8: 'Int8Array';
@@ -517,8 +519,8 @@ private abstract TypedArrayType(Int) from Int to Int {
#if cpp
untyped return __global__.__hxcpp_memory_get_i32(buffer.getData(), byteOffset);
#else
- #if (haxe_ver > 3103)
- return buffer.getI32(byteOffset);
+ #if (haxe_ver >= 3.2)
+ return buffer.getInt32(byteOffset);
#else
var ch1 = getInt8(buffer, byteOffset );
@@ -542,8 +544,8 @@ private abstract TypedArrayType(Int) from Int to Int {
#if cpp
untyped __global__.__hxcpp_memory_set_i32(buffer.getData(), byteOffset, value);
#else
- #if (haxe_ver > 3103)
- buffer.setI32(byteOffset,value);
+ #if ((haxe_ver >= 3.2) && !neko) // causes error on some int values?
+ buffer.setInt32(byteOffset,value);
#else
if (littleEndian) {
setInt8(buffer, byteOffset , value );
diff --git a/lime/utils/ByteArray.hx b/lime/utils/ByteArray.hx
index fd13fd40c..712f2b95c 100644
--- a/lime/utils/ByteArray.hx
+++ b/lime/utils/ByteArray.hx
@@ -328,11 +328,11 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa
public static function readFile (path:String):ByteArray {
- #if html5
- return null;
- #else
- return ByteArray.fromBytes (File.getBytes (path));
+ #if !html5
+ var data = lime_bytes_read_file (path);
+ if (data != null) return ByteArray.fromBytes (@:privateAccess new Bytes (data.length, data.b));
#end
+ return null;
}
@@ -905,6 +905,16 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa
}
+ #if (cpp || neko || nodejs)
+ public static function __fromNativePointer (data:Dynamic, length:Int):ByteArray {
+
+ var bytes = lime_bytes_from_data_pointer (data, length);
+ return ByteArray.fromBytes (@:privateAccess new Bytes (bytes.length, bytes.b));
+
+ }
+ #end
+
+
@:keep public inline function __get (pos:Int):Int {
#if js
@@ -1092,7 +1102,9 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa
+ private static var lime_bytes_from_data_pointer = System.load ("lime", "lime_bytes_from_data_pointer", 2);
private static var lime_bytes_get_data_pointer = System.load ("lime", "lime_bytes_get_data_pointer", 1);
+ private static var lime_bytes_read_file = System.load ("lime", "lime_bytes_read_file", 1);
}
diff --git a/lime/utils/Float32Array.hx b/lime/utils/Float32Array.hx
index 258a9e539..54963271a 100644
--- a/lime/utils/Float32Array.hx
+++ b/lime/utils/Float32Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'Float32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Float32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -107,7 +107,7 @@ abstract Float32Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
//Internal
- function toString() return 'Float32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Float32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
inline function get_length() return this.length;
diff --git a/lime/utils/Float64Array.hx b/lime/utils/Float64Array.hx
index 7046cfa77..d84329620 100644
--- a/lime/utils/Float64Array.hx
+++ b/lime/utils/Float64Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'Float64Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Float64Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract Float64Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setFloat64(this.buffer, this.byteOffset+(idx*BYTES_PER_ELEMENT), val);
}
- function toString() return 'Float64Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Float64Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/Int16Array.hx b/lime/utils/Int16Array.hx
index 432ed36a6..517441fd8 100644
--- a/lime/utils/Int16Array.hx
+++ b/lime/utils/Int16Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'Int16Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int16Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract Int16Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setInt16(this.buffer, this.byteOffset+(idx*BYTES_PER_ELEMENT), val);
}
- function toString() return 'Int16Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int16Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/Int32Array.hx b/lime/utils/Int32Array.hx
index 7baaeba09..c89b07b50 100644
--- a/lime/utils/Int32Array.hx
+++ b/lime/utils/Int32Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'Int32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract Int32Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setInt32(this.buffer, this.byteOffset+(idx*BYTES_PER_ELEMENT), val);
}
- function toString() return 'Int32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/Int8Array.hx b/lime/utils/Int8Array.hx
index a56682848..2785966fb 100644
--- a/lime/utils/Int8Array.hx
+++ b/lime/utils/Int8Array.hx
@@ -51,7 +51,7 @@ package lime.utils;
#end
}
- function toString() return 'Int8Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int8Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract Int8Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setInt8(this.buffer, this.byteOffset+idx, val);
}
- function toString() return 'Int8Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'Int8Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/Log.hx b/lime/utils/Log.hx
new file mode 100644
index 000000000..e6c232dc0
--- /dev/null
+++ b/lime/utils/Log.hx
@@ -0,0 +1,148 @@
+package lime.utils;
+
+
+import haxe.PosInfos;
+
+
+class Log {
+
+
+ public static var level:LogLevel;
+
+
+ public static function debug (message:String, ?info:PosInfos):Void {
+
+ if (level >= DEBUG) {
+
+ println ("[" + info.className + "] " + message);
+
+ }
+
+ }
+
+
+ public static function error (message:String, ?info:PosInfos):Void {
+
+ if (level >= ERROR) {
+
+ println ("[" + info.className + "] ERROR: " + message);
+
+ }
+
+ }
+
+
+ public static function info (message:String, ?info:PosInfos):Void {
+
+ if (level >= INFO) {
+
+ println ("[" + info.className + "] " + message);
+
+ }
+
+ }
+
+
+ public static inline function print (message:String):Void {
+
+ #if sys
+ Sys.print (message);
+ #elseif flash
+ untyped __global__["trace"] (message);
+ #elseif js
+ untyped __js__("console").log (message);
+ #else
+ trace (message);
+ #end
+
+ }
+
+
+ public static inline function println (message:String):Void {
+
+ #if sys
+ Sys.println (message);
+ #elseif flash
+ untyped __global__["trace"] (message);
+ #elseif js
+ untyped __js__("console").log (message);
+ #else
+ trace (message);
+ #end
+
+ }
+
+
+ public static function verbose (message:String, ?info:PosInfos):Void {
+
+ if (level >= VERBOSE) {
+
+ println ("[" + info.className + "] " + message);
+
+ }
+
+ }
+
+
+ public static function warn (message:String, ?info:PosInfos):Void {
+
+ if (level >= WARN) {
+
+ println ("[" + info.className + "] WARNING: " + message);
+
+ }
+
+ }
+
+
+ private static function __init__ ():Void {
+
+ #if no_traces
+ level = NONE;
+ #elseif verbose
+ level = VERBOSE;
+ #else
+ #if sys
+ var args = Sys.args ();
+ if (args.indexOf ("-v") > -1 || args.indexOf ("-verbose") > -1) {
+ level = VERBOSE;
+ return;
+ }
+ #end
+ #if debug
+ level = DEBUG;
+ #else
+ level = INFO;
+ #end
+ #end
+
+ #if js
+ if (untyped __js__("typeof console") == "undefined") {
+ untyped __js__("console = {}");
+ }
+ if (untyped __js__("console").log == null) {
+ untyped __js__("console").log = function () {};
+ }
+ #end
+
+ }
+
+
+}
+
+
+@:enum abstract LogLevel(Int) from Int to Int {
+
+ var NONE = 0;
+ var ERROR = 1;
+ var WARN = 2;
+ var INFO = 3;
+ var DEBUG = 4;
+ var VERBOSE = 5;
+
+ @:op(A > B) private static inline function gt (a:LogLevel, b:LogLevel):Bool { return (a:Int) > (b:Int); }
+ @:op(A >= B) private static inline function gte (a:LogLevel, b:LogLevel):Bool { return (a:Int) >= (b:Int); }
+ @:op(A < B) private static inline function lt (a:LogLevel, b:LogLevel):Bool { return (a:Int) < (b:Int); }
+ @:op(A <= B) private static inline function lte (a:LogLevel, b:LogLevel):Bool { return (a:Int) <= (b:Int); }
+
+}
\ No newline at end of file
diff --git a/lime/utils/UInt16Array.hx b/lime/utils/UInt16Array.hx
index 3c3a5b249..69af7a87d 100644
--- a/lime/utils/UInt16Array.hx
+++ b/lime/utils/UInt16Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'UInt16Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt16Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract UInt16Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setUint16(this.buffer, this.byteOffset+(idx*BYTES_PER_ELEMENT), val);
}
- function toString() return 'UInt16Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt16Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/UInt32Array.hx b/lime/utils/UInt32Array.hx
index 1dcb82f71..b8e0070bf 100644
--- a/lime/utils/UInt32Array.hx
+++ b/lime/utils/UInt32Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'UInt32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -121,7 +121,7 @@ abstract UInt32Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
return ArrayBufferIO.setUint32(this.buffer, this.byteOffset+(idx*BYTES_PER_ELEMENT), val);
}
- function toString() return 'UInt32Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt32Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/lime/utils/UInt8Array.hx b/lime/utils/UInt8Array.hx
index f586bd7e5..4b1e18f65 100644
--- a/lime/utils/UInt8Array.hx
+++ b/lime/utils/UInt8Array.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'UInt8Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt8Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
@@ -106,7 +106,7 @@ abstract UInt8Array(ArrayBufferView) from ArrayBufferView to ArrayBufferView {
//Internal
- function toString() return 'UInt8Array [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt8Array [byteLength:${this.byteLength}, length:${this.length}]' : null;
inline function get_length() return this.length;
diff --git a/lime/utils/UInt8ClampedArray.hx b/lime/utils/UInt8ClampedArray.hx
index 8d2cd8e4f..b78264790 100644
--- a/lime/utils/UInt8ClampedArray.hx
+++ b/lime/utils/UInt8ClampedArray.hx
@@ -53,7 +53,7 @@ package lime.utils;
#end
}
- function toString() return 'UInt8ClampedArray [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt8ClampedArray [byteLength:${this.byteLength}, length:${this.length}]' : null;
//internal
//clamp a Int to a 0-255 Uint8
@@ -129,7 +129,7 @@ abstract UInt8ClampedArray(ArrayBufferView) from ArrayBufferView to ArrayBufferV
return ArrayBufferIO.setUint8Clamped(this.buffer, this.byteOffset+idx, val);
}
- function toString() return 'UInt8ClampedArray [byteLength:${this.byteLength}, length:${this.length}]';
+ function toString() return this != null ? 'UInt8ClampedArray [byteLength:${this.byteLength}, length:${this.length}]' : null;
}
diff --git a/project/Build.xml b/project/Build.xml
index 7f17042d6..1732717ec 100644
--- a/project/Build.xml
+++ b/project/Build.xml
@@ -29,6 +29,7 @@
+
diff --git a/project/include/graphics/Image.h b/project/include/graphics/Image.h
index 0fc3074fb..50e631aa1 100644
--- a/project/include/graphics/Image.h
+++ b/project/include/graphics/Image.h
@@ -23,7 +23,6 @@ namespace lime {
int height;
int offsetX;
int offsetY;
- bool transparent;
int width;
private:
diff --git a/project/include/graphics/ImageBuffer.h b/project/include/graphics/ImageBuffer.h
index 91f01489c..3dbf4fc52 100644
--- a/project/include/graphics/ImageBuffer.h
+++ b/project/include/graphics/ImageBuffer.h
@@ -28,8 +28,9 @@ namespace lime {
Bytes *data;
PixelFormat format;
int height;
- int width;
+ bool premultiplied;
bool transparent;
+ int width;
private:
diff --git a/project/include/graphics/PixelFormat.h b/project/include/graphics/PixelFormat.h
index fb35c7cb1..328f410bb 100644
--- a/project/include/graphics/PixelFormat.h
+++ b/project/include/graphics/PixelFormat.h
@@ -7,9 +7,9 @@ namespace lime {
enum PixelFormat {
- RGBA,
- ARGB,
- BGRA
+ RGBA32,
+ ARGB32,
+ BGRA32
};
diff --git a/project/include/graphics/Renderer.h b/project/include/graphics/Renderer.h
index 2b9186067..5f1bb69ac 100644
--- a/project/include/graphics/Renderer.h
+++ b/project/include/graphics/Renderer.h
@@ -16,6 +16,7 @@ namespace lime {
virtual void Flip () = 0;
virtual value Lock () = 0;
+ virtual const char* Type () = 0;
virtual void Unlock () = 0;
Window* currentWindow;
diff --git a/project/include/graphics/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h
index 02e1e86fc..b411e7992 100644
--- a/project/include/graphics/utils/ImageDataUtil.h
+++ b/project/include/graphics/utils/ImageDataUtil.h
@@ -10,6 +10,7 @@
#include