From 6d107b6517318e34d7c82dd57610f7e7724a8fe6 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 8 Jul 2015 09:02:49 -0700 Subject: [PATCH 01/76] Fix legacy mouse events --- legacy/project/src/sdl2/SDL2Stage.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/legacy/project/src/sdl2/SDL2Stage.cpp b/legacy/project/src/sdl2/SDL2Stage.cpp index 5071ce712..689a6b56e 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); From 89d67f9927c249f8b0b9632bf91406970fec6761 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 9 Jul 2015 10:29:24 -0700 Subject: [PATCH 02/76] Guard against garbage collection in bytes (fixes #498) --- project/include/utils/Bytes.h | 1 + project/src/utils/Bytes.cpp | 46 +++++++++++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/project/include/utils/Bytes.h b/project/include/utils/Bytes.h index d680b83c6..4ef8178e3 100644 --- a/project/include/utils/Bytes.h +++ b/project/include/utils/Bytes.h @@ -29,6 +29,7 @@ namespace lime { unsigned char *_data; int _length; + value *_root; value _value; diff --git a/project/src/utils/Bytes.cpp b/project/src/utils/Bytes.cpp index 15912af29..ae49b0761 100644 --- a/project/src/utils/Bytes.cpp +++ b/project/src/utils/Bytes.cpp @@ -40,6 +40,7 @@ namespace lime { _data = 0; _length = 0; _value = 0; + _root = 0; } @@ -51,6 +52,7 @@ namespace lime { _data = 0; _length = 0; _value = 0; + _root = 0; Resize (size); @@ -61,6 +63,11 @@ namespace lime { initialize (); + _data = 0; + _length = 0; + _value = 0; + _root = 0; + Set (bytes); } @@ -73,6 +80,7 @@ namespace lime { _data = 0; _length = 0; _value = 0; + _root = 0; FILE_HANDLE *file = lime::fopen (path, "rb"); @@ -102,6 +110,11 @@ namespace lime { initialize (); + _data = 0; + _length = 0; + _value = 0; + _root = 0; + Set (data); } @@ -109,11 +122,12 @@ namespace lime { Bytes::~Bytes () { - //if (!_value && _data) { - // - //free (_data); - // - //} + if (_root) { + + *_root = 0; + free_root (_root); + + } } @@ -146,6 +160,8 @@ namespace lime { if (!_value) { _value = alloc_empty_object (); + _root = alloc_root (); + *_root = _value; } @@ -204,9 +220,20 @@ namespace lime { _data = 0; _value = 0; + if (_root) { + + *_root = 0; + free_root (_root); + + } + + _root = 0; + } else { _value = bytes; + _root = alloc_root (); + *_root = _value; _length = val_int (val_field (bytes, id_length)); if (_length > 0) { @@ -248,6 +275,15 @@ namespace lime { _data = 0; _length = 0; + if (_root) { + + *_root = 0; + free_root (_root); + + } + + _root = 0; + } } From 32b1b5cd652892f6f229c8200a8126a8e67a7639 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 9 Jul 2015 15:34:43 -0700 Subject: [PATCH 03/76] Update to 2.4.8 --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index 4034cf160..bc3dfa0a9 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.4.8", + "releasenote": "Bytes, BackgroundWorker and iOS improvements", "contributors": [ "singmajesty" ] } From 7b05cad660cf67c5538e69b1881c68361efa60c2 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 9 Jul 2015 15:34:52 -0700 Subject: [PATCH 04/76] Update CHANGELOG --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad8334ff..340fdbaf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +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) ------------------ From 90f9510889d380e2720418c8b885b5f5277f09f6 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 9 Jul 2015 16:20:27 -0700 Subject: [PATCH 05/76] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 340fdbaf3..91230c557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,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 From 5d7a2b0cc500b7ce09169c3a16368c1bfc9fe679 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 10 Jul 2015 11:15:15 -0700 Subject: [PATCH 06/76] Disable axTLS non-blocking in Lime 2, keep enabled in legacy --- project/Build.xml | 1 + project/lib/curl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/project/Build.xml b/project/Build.xml index de15ae25a..de7e4bbb9 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -29,6 +29,7 @@ + diff --git a/project/lib/curl b/project/lib/curl index b5b913c01..7084474ab 160000 --- a/project/lib/curl +++ b/project/lib/curl @@ -1 +1 @@ -Subproject commit b5b913c01427297d87da69d34ddbbc06a6591697 +Subproject commit 7084474ab4eb76efa3ba1dc6eb4e407ae07a72ba From 31bc27795979d5ed2f4870aa65824a47dfd2a7f0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 10 Jul 2015 17:22:44 -0700 Subject: [PATCH 07/76] Add event.has and default BackgroundWorker send* events to null messages --- lime/app/Event.hx | 8 ++++++++ lime/system/BackgroundWorker.hx | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) 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/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) From 961ef1e594c426407ffa62fc3b2c275926e5d496 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 10 Jul 2015 17:22:54 -0700 Subject: [PATCH 08/76] Add lime.system.ThreadPool --- lime/system/ThreadPool.hx | 240 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 lime/system/ThreadPool.hx diff --git a/lime/system/ThreadPool.hx b/lime/system/ThreadPool.hx new file mode 100644 index 000000000..385b7808a --- /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++; + 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 From 74604c9077067ce15eb8af9d60064345736b1ad9 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 10 Jul 2015 17:35:06 -0700 Subject: [PATCH 09/76] Use TheadPool instead of BackgroundWorker to limit Assets.load* requests at once --- lime/system/ThreadPool.hx | 2 +- templates/haxe/DefaultAssetLibrary.hx | 48 ++++++++++++++++++--------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/lime/system/ThreadPool.hx b/lime/system/ThreadPool.hx index 385b7808a..f60ee3c17 100644 --- a/lime/system/ThreadPool.hx +++ b/lime/system/ThreadPool.hx @@ -68,7 +68,7 @@ class ThreadPool { __workIncoming.add (new ThreadPoolMessage (WORK, id, message)); __workQueued++; - if (currentThreads < maxThreads) { + if (currentThreads < maxThreads && currentThreads < (__workQueued - __workCompleted)) { currentThreads++; Thread.create (__doWork); diff --git a/templates/haxe/DefaultAssetLibrary.hx b/templates/haxe/DefaultAssetLibrary.hx index a0ff0a1ae..6dba668c7 100644 --- a/templates/haxe/DefaultAssetLibrary.hx +++ b/templates/haxe/DefaultAssetLibrary.hx @@ -8,7 +8,7 @@ import lime.audio.AudioSource; import lime.audio.openal.AL; import lime.audio.AudioBuffer; import lime.graphics.Image; -import lime.system.BackgroundWorker; +import lime.system.ThreadPool; import lime.text.Font; import lime.utils.ByteArray; import lime.utils.UInt8Array; @@ -40,6 +40,8 @@ class DefaultAssetLibrary extends AssetLibrary { public var type (default, null) = new Map (); private var lastModified:Float; + private var loadHandlers:Map; + private var threadPool:ThreadPool; private var timer:Timer; @@ -132,6 +134,24 @@ class DefaultAssetLibrary extends AssetLibrary { } + private function createThreadPool ():Void { + + threadPool = new ThreadPool (0, 2); + threadPool.doWork.add (function (id, getMethod) { + + threadPool.sendComplete (id, getMethod (id)); + + }); + threadPool.onComplete.add (function (id, data) { + + var handler = loadHandlers.get (id); + handler (data); + + }); + + } + + public override function exists (id:String, type:String):Bool { var requestedType = type != null ? cast (type, AssetType) : null; @@ -548,16 +568,15 @@ class DefaultAssetLibrary extends AssetLibrary { #else - var worker = new BackgroundWorker (); - - worker.doWork.add (function (_) { + if (threadPool == null) { - worker.sendComplete (getBytes (id)); + loadHandlers = new Map (); + createThreadPool (); - }); + } - worker.onComplete.add (handler); - worker.run (); + loadHandlers.set (id, handler); + threadPool.queue (id, getBytes); #end @@ -605,16 +624,15 @@ class DefaultAssetLibrary extends AssetLibrary { #else - var worker = new BackgroundWorker (); - - worker.doWork.add (function (_) { + if (threadPool == null) { - worker.sendComplete (getImage (id)); + loadHandlers = new Map (); + createThreadPool (); - }); + } - worker.onComplete.add (handler); - worker.run (); + loadHandlers.set (id, handler); + threadPool.queue (id, getImage); #end From f5605267fa0beceab03089e677264f52503b1079 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 13:56:27 -0700 Subject: [PATCH 10/76] Allow cURL Int abstracts to convert from/to Int --- lime/net/curl/CURLCode.hx | 2 +- lime/net/curl/CURLInfo.hx | 2 +- lime/net/curl/CURLOption.hx | 2 +- lime/net/curl/CURLVersion.hx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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; From bddc66d2daf2f63e8c410851580758f4047c93d0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 13:58:16 -0700 Subject: [PATCH 11/76] Make Flash logging faster --- lime/tools/helpers/FlashHelper.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } From 0a50efa96b5498622c409031f984a3b3a51389ba Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 13:58:55 -0700 Subject: [PATCH 12/76] Pass verbose define (Flash/HTML5) or flag (desktop) when doing a -verbose build --- lime/tools/platforms/FlashPlatform.hx | 7 +++++++ lime/tools/platforms/HTML5Platform.hx | 6 ++++++ lime/tools/platforms/LinuxPlatform.hx | 7 +++++++ lime/tools/platforms/MacPlatform.hx | 7 +++++++ lime/tools/platforms/WindowsPlatform.hx | 7 +++++++ 5 files changed, 34 insertions(+) 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/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..e107edf4c 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; @@ -244,6 +245,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); diff --git a/lime/tools/platforms/WindowsPlatform.hx b/lime/tools/platforms/WindowsPlatform.hx index 31d9831a0..672fe1863 100644 --- a/lime/tools/platforms/WindowsPlatform.hx +++ b/lime/tools/platforms/WindowsPlatform.hx @@ -8,6 +8,7 @@ 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; @@ -232,6 +233,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); From ffdf15f0808427e40b56444e50afddb412d02b80 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 13:59:08 -0700 Subject: [PATCH 13/76] Add lime.utils.Log --- lime/utils/Log.hx | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 lime/utils/Log.hx 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 From 8920ff5317c7d150f5828f788d6cabd4abfcd1e8 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 20:30:47 -0700 Subject: [PATCH 14/76] Use a default icon --- lime/tools/platforms/AndroidPlatform.hx | 12 +- lime/tools/platforms/BlackBerryPlatform.hx | 11 +- lime/tools/platforms/FirefoxPlatform.hx | 10 +- lime/tools/platforms/IOSPlatform.hx | 13 ++- lime/tools/platforms/MacPlatform.hx | 11 +- lime/tools/platforms/TizenPlatform.hx | 11 +- lime/tools/platforms/WebOSPlatform.hx | 11 +- lime/tools/platforms/WindowsPlatform.hx | 13 ++- .../Assets/lime.svg => default/icon.svg} | 108 +++++++++--------- templates/project/Assets/.gitignore | 0 templates/project/project.xml | 3 +- 11 files changed, 136 insertions(+), 67 deletions(-) rename templates/{project/Assets/lime.svg => default/icon.svg} (98%) create mode 100644 templates/project/Assets/.gitignore 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/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/MacPlatform.hx b/lime/tools/platforms/MacPlatform.hx index e107edf4c..8b7e8f916 100644 --- a/lime/tools/platforms/MacPlatform.hx +++ b/lime/tools/platforms/MacPlatform.hx @@ -19,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; @@ -317,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 672fe1863..a0a3414c7 100644 --- a/lime/tools/platforms/WindowsPlatform.hx +++ b/lime/tools/platforms/WindowsPlatform.hx @@ -3,6 +3,7 @@ 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; @@ -95,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") { @@ -103,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; @@ -150,7 +159,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); diff --git a/templates/project/Assets/lime.svg b/templates/default/icon.svg similarity index 98% rename from templates/project/Assets/lime.svg rename to templates/default/icon.svg index 0e20a1c77..98fa1766c 100644 --- a/templates/project/Assets/lime.svg +++ b/templates/default/icon.svg @@ -1,54 +1,54 @@ - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/project/Assets/.gitignore b/templates/project/Assets/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/templates/project/project.xml b/templates/project/project.xml index 9f63eddf0..d65fddc13 100644 --- a/templates/project/project.xml +++ b/templates/project/project.xml @@ -8,7 +8,6 @@ - - + \ No newline at end of file From 08a8294a5ce9092fbddab273cf0bd8ad46ac8e56 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sat, 11 Jul 2015 20:40:05 -0700 Subject: [PATCH 15/76] Allow lime-samples to handle its structure --- include.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include.xml b/include.xml index b622e7d11..caeb49718 100644 --- a/include.xml +++ b/include.xml @@ -62,7 +62,7 @@ - +
From 1c7d70646fc98ec2695b74d7ec3f5df466fe558f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 11:27:54 -0700 Subject: [PATCH 16/76] Help find GIT when not in PATH on Windows --- tools/utils/PlatformSetup.hx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/utils/PlatformSetup.hx b/tools/utils/PlatformSetup.hx index 578017de6..335647dd8 100644 --- a/tools/utils/PlatformSetup.hx +++ b/tools/utils/PlatformSetup.hx @@ -2126,6 +2126,18 @@ class PlatformSetup { LogHelper.info ("\x1b[32;1mUpdating \"" + haxelib.name + "\"\x1b[0m"); + if (PlatformHelper.hostPlatform == Platform.WINDOWS) { + + var path = Sys.getEnv ("PATH"); + + if (path.indexOf ("Git") == -1) { + + Sys.putEnv ("PATH", "C:\\Program Files (x86)\\Git\\bin;" + path); + + } + + } + ProcessHelper.runCommand (lib, "git", [ "pull" ]); ProcessHelper.runCommand (lib, "git", [ "submodule", "init" ]); ProcessHelper.runCommand (lib, "git", [ "submodule", "update" ]); From ec34739a85c25917d2078fe8265f85150d97ce15 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 13:03:46 -0700 Subject: [PATCH 17/76] Crop rectangle in image.copyChannel --- lime/graphics/utils/ImageDataUtil.hx | 43 +++++++++++++++----- project/src/graphics/utils/ImageDataUtil.cpp | 43 +++++++++++++++----- 2 files changed, 66 insertions(+), 20 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 6413ebd06..547b1d04f 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -128,19 +128,47 @@ class ImageDataUtil { #end { + var width = sourceRect.width; + var height = sourceRect.height; + + if (destPoint.x + width > image.width) { + + width = image.width - destPoint.x; + + } + + if (sourceRect.x + width > sourceImage.width) { + + width = sourceImage.width - sourceRect.x; + + } + + if (destPoint.y + height > image.height) { + + height = image.height - destPoint.y; + + } + + if (sourceRect.y + height > sourceImage.height) { + + height = sourceImage.height - sourceRect.y; + + } + + if (width <= 0 || height <= 0) return; + 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 srcRowOffset = srcStride - Std.int (4 * width); + var srcRowEnd = Std.int (4 * (sourceRect.x + sourceImage.offsetX + width)); var srcData = sourceImage.buffer.data; 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 destRowOffset = destStride - Std.int (4 * width); var destData = image.buffer.data; - var length = Std.int (sourceRect.width * sourceRect.height); + var length = Std.int (width * height); for (i in 0...length) { @@ -152,11 +180,6 @@ class ImageDataUtil { if ((srcPosition % srcStride) > srcRowEnd) { srcPosition += srcRowOffset; - - } - - if ((destPosition % destStride) > destRowEnd) { - destPosition += destRowOffset; } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 20bfd4307..3636e1488 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -87,19 +87,47 @@ namespace lime { void ImageDataUtil::CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { + int width = sourceRect->width; + int height = sourceRect->height; + + if (destPoint->x + width > image->width) { + + width = image->width - destPoint->x; + + } + + if (sourceRect->x + width > sourceImage->width) { + + width = sourceImage->width - sourceRect->x; + + } + + if (destPoint->y + height > image->height) { + + height = image->height - destPoint->y; + + } + + if (sourceRect->y + height > sourceImage->height) { + + height = sourceImage->height - sourceRect->y; + + } + + if (width <= 0 || height <= 0) return; + int srcStride = sourceImage->buffer->Stride (); int srcPosition = ((sourceRect->x + sourceImage->offsetX) * 4) + (srcStride * (sourceRect->y + sourceImage->offsetY)) + srcChannel; - int srcRowOffset = srcStride - int (4 * (sourceRect->width + sourceImage->offsetX)); - int srcRowEnd = 4 * (sourceRect->x + sourceImage->offsetX + sourceRect->width); + int srcRowOffset = srcStride - int (4 * width); + int srcRowEnd = 4 * (sourceRect->x + sourceImage->offsetX + width); uint8_t* srcData = (uint8_t*)sourceImage->buffer->data->Data (); int destStride = image->buffer->Stride (); int destPosition = ((destPoint->x + image->offsetX) * 4) + (destStride * (destPoint->y + image->offsetY)) + destChannel; - int destRowOffset = destStride - int (4 * (sourceRect->width + image->offsetX)); - int destRowEnd = 4 * (destPoint->x + image->offsetX + sourceRect->width); + int destRowOffset = destStride - int (4 * width); uint8_t* destData = (uint8_t*)image->buffer->data->Data (); - int length = sourceRect->width * sourceRect->height; + int length = width * height; for (int i = 0; i < length; i++) { @@ -111,11 +139,6 @@ namespace lime { if ((srcPosition % srcStride) > srcRowEnd) { srcPosition += srcRowOffset; - - } - - if ((destPosition % destStride) > destRowEnd) { - destPosition += destRowOffset; } From 808d6ffe15e6ab887992be7620b37528c3699224 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 16:35:18 -0700 Subject: [PATCH 18/76] Improve Image clone --- lime/graphics/Image.hx | 1 + lime/graphics/ImageBuffer.hx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index 7843096ed..90518cd57 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -158,6 +158,7 @@ class Image { public function clone ():Image { var image = new Image (buffer.clone (), offsetX, offsetY, width, height, null, type); + image.dirty = dirty; return image; } diff --git a/lime/graphics/ImageBuffer.hx b/lime/graphics/ImageBuffer.hx index ca1bb1368..f09122d66 100644 --- a/lime/graphics/ImageBuffer.hx +++ b/lime/graphics/ImageBuffer.hx @@ -108,6 +108,8 @@ class ImageBuffer { } #end + buffer.bitsPerPixel = bitsPerPixel; + buffer.format = format; buffer.premultiplied = premultiplied; buffer.transparent = transparent; return buffer; From 5434424003024bad1c87ffda5ff2365b9bd0bd41 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 16:36:27 -0700 Subject: [PATCH 19/76] Improve case if ImageBuffer data is present, but there is no ImageData object --- lime/graphics/utils/ImageCanvasUtil.hx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index 7720ff945..e9d58571d 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -156,9 +156,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 (buffer.data); + + } - buffer.__srcImageData = buffer.__srcContext.getImageData (0, 0, buffer.width, buffer.height); buffer.data = new UInt8Array (cast buffer.__srcImageData.data.buffer); } From 21d711550ba15a6e0e9aff98de020b32ec909365 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 16:49:07 -0700 Subject: [PATCH 20/76] Handle case where Image has data, but no canvas, and is used in a canvas render --- lime/graphics/utils/ImageCanvasUtil.hx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index e9d58571d..ebdf81721 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); + } } From 3b6b47d278fa1bcfee4321b97dbffaf4bd05347a Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 16:54:07 -0700 Subject: [PATCH 21/76] Fix canvas Image clone --- lime/graphics/Image.hx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index 90518cd57..dc59ea4bf 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -158,6 +158,13 @@ class Image { public function clone ():Image { var image = new Image (buffer.clone (), offsetX, offsetY, width, height, null, type); + + if (image.type == CANVAS && image.buffer.data != null && image.buffer.__srcCanvas == null) { + + ImageCanvasUtil.convertToCanvas (image); + + } + image.dirty = dirty; return image; From 66fc421472c5d40f793af4aa5cd4fe07ee8f8c70 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 17:44:22 -0700 Subject: [PATCH 22/76] Handle null toString in typed arrays --- lime/utils/ArrayBufferView.hx | 4 +++- lime/utils/Float32Array.hx | 4 ++-- lime/utils/Float64Array.hx | 4 ++-- lime/utils/Int16Array.hx | 4 ++-- lime/utils/Int32Array.hx | 4 ++-- lime/utils/Int8Array.hx | 4 ++-- lime/utils/UInt16Array.hx | 4 ++-- lime/utils/UInt32Array.hx | 4 ++-- lime/utils/UInt8Array.hx | 4 ++-- lime/utils/UInt8ClampedArray.hx | 4 ++-- 10 files changed, 21 insertions(+), 19 deletions(-) diff --git a/lime/utils/ArrayBufferView.hx b/lime/utils/ArrayBufferView.hx index 8979b9d8d..d3fc7206a 100644 --- a/lime/utils/ArrayBufferView.hx +++ b/lime/utils/ArrayBufferView.hx @@ -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'; 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/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; } From af57a481396221639fca0e05a4db7a5ebf8e648d Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 17:45:00 -0700 Subject: [PATCH 23/76] Fix canvas Image clone, add image.scroll --- lime/graphics/Image.hx | 55 ++++++++++++++++++++++---- lime/graphics/utils/ImageCanvasUtil.hx | 13 ++++++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index dc59ea4bf..908f70b11 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -157,17 +157,27 @@ class Image { public function clone ():Image { - var image = new Image (buffer.clone (), offsetX, offsetY, width, height, null, type); - - if (image.type == CANVAS && image.buffer.data != null && image.buffer.__srcCanvas == null) { + if (buffer != null) { - ImageCanvasUtil.convertToCanvas (image); + 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); } - image.dirty = dirty; - return image; - } @@ -710,6 +720,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; diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index ebdf81721..7fb286321 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -297,6 +297,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); From 6445a95fd77d240398cfc2daceba7ad2c58b77e0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 17:48:56 -0700 Subject: [PATCH 24/76] Try with a cast --- lime/graphics/utils/ImageCanvasUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index 7fb286321..d306bc067 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -170,7 +170,7 @@ class ImageCanvasUtil { } else { buffer.__srcImageData = buffer.__srcContext.createImageData (buffer.width, buffer.height); - buffer.__srcImageData.data.set (buffer.data); + buffer.__srcImageData.data.set (cast buffer.data); } From d0d6f497f898b1159d28f4fc015456b29c12d62c Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 19:11:29 -0700 Subject: [PATCH 25/76] Update to 2.4.9 --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index bc3dfa0a9..11f7d529c 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.8", - "releasenote": "Bytes, BackgroundWorker and iOS improvements", + "version": "2.4.9", + "releasenote": "Added ThreadPool, Log and made other improvements", "contributors": [ "singmajesty" ] } From e9a579384fc94c19ddc39949531c18aaf70b8b14 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 13 Jul 2015 19:15:15 -0700 Subject: [PATCH 26/76] Update CHANGELOG --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91230c557..9c810c189 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +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) ------------------ From 924f478a81b0afbe9da89654c3ccf310da1efbd8 Mon Sep 17 00:00:00 2001 From: "Lars A. Doucet" Date: Tue, 14 Jul 2015 10:36:01 -0500 Subject: [PATCH 27/76] added legacy support for wiimote gamepad detection --- legacy/project/src/sdl2/SDL2Stage.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/legacy/project/src/sdl2/SDL2Stage.cpp b/legacy/project/src/sdl2/SDL2Stage.cpp index 689a6b56e..46047009c 100644 --- a/legacy/project/src/sdl2/SDL2Stage.cpp +++ b/legacy/project/src/sdl2/SDL2Stage.cpp @@ -1409,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; From 18f2e401d295bc246526efb44ef3e9994cd05e8c Mon Sep 17 00:00:00 2001 From: Nilsen Filc Date: Wed, 15 Jul 2015 04:51:31 +0200 Subject: [PATCH 28/76] Guard against doppleganger gamepad connection Gamepad connect can fire twice in a row the event for the same device (tested on Mac OSX). Prevent that. --- lime/_backend/native/NativeApplication.hx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index fc8645d0e..bfb02bf86 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -144,9 +144,11 @@ class NativeApplication { 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: @@ -753,4 +755,4 @@ private class WindowEventInfo { var WINDOW_RESIZE = 9; var WINDOW_RESTORE = 10; -} \ No newline at end of file +} From 250d4b488bb3b1ef1313512e2af716d22b2d9805 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 14 Jul 2015 21:33:41 -0700 Subject: [PATCH 29/76] Add explicit assetLibrary.unload when calling Assets.unloadLibrary --- lime/Assets.hx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lime/Assets.hx b/lime/Assets.hx index 0182aa001..71a9dae1c 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 { } + private function unload ():Void { + + + + } + + } From 42b1c80b4ac6649375d6f9d03c134f601c94be23 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 11:00:13 -0700 Subject: [PATCH 30/76] Minor fix --- lime/Assets.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/Assets.hx b/lime/Assets.hx index 71a9dae1c..4e48443ce 100644 --- a/lime/Assets.hx +++ b/lime/Assets.hx @@ -1141,7 +1141,7 @@ class AssetLibrary { } - private function unload ():Void { + public function unload ():Void { From b50d0525484b60e36c93755597e4e45ffe7b3985 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 11:00:23 -0700 Subject: [PATCH 31/76] Fix regression in ByteArray.readFile on Android --- lime/utils/ByteArray.hx | 9 +++++---- project/src/ExternalInterface.cpp | 9 +++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lime/utils/ByteArray.hx b/lime/utils/ByteArray.hx index fd13fd40c..c64da9d1d 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; } @@ -1093,6 +1093,7 @@ class ByteArray #if !js extends Bytes implements ArrayAccess implements IDa 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/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index d1e3de508..8835cc269 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -135,6 +135,14 @@ namespace lime { } + value lime_bytes_read_file (value path) { + + Bytes data = Bytes (val_os_string (path)); + return data.Value (); + + } + + void lime_font_destroy (value handle) { Font *font = (Font*)(intptr_t)val_float (handle); @@ -1104,6 +1112,7 @@ namespace lime { DEFINE_PRIM (lime_application_update, 1); DEFINE_PRIM (lime_audio_load, 1); DEFINE_PRIM (lime_bytes_get_data_pointer, 1); + DEFINE_PRIM (lime_bytes_read_file, 1); DEFINE_PRIM (lime_font_get_ascender, 1); DEFINE_PRIM (lime_font_get_descender, 1); DEFINE_PRIM (lime_font_get_family_name, 1); From 0b4c55362204d709918b5b112b58009eace92ce0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 16:40:53 -0700 Subject: [PATCH 32/76] Add CairoImageSurface, properly separate image surface methods from the CairoSurface type --- lime/_backend/native/NativeRenderer.hx | 11 +- lime/graphics/cairo/CairoImageSurface.hx | 131 +++++++++++++++++++ lime/graphics/cairo/CairoSurface.hx | 71 ---------- lime/utils/ByteArray.hx | 11 ++ project/src/ExternalInterface.cpp | 18 +++ project/src/graphics/cairo/CairoBindings.cpp | 28 +++- 6 files changed, 193 insertions(+), 77 deletions(-) create mode 100644 lime/graphics/cairo/CairoImageSurface.hx diff --git a/lime/_backend/native/NativeRenderer.hx b/lime/_backend/native/NativeRenderer.hx index ace13fdf1..1447db885 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; @@ -97,14 +98,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 +116,6 @@ class NativeRenderer { } - } cacheLock = lock; diff --git a/lime/graphics/cairo/CairoImageSurface.hx b/lime/graphics/cairo/CairoImageSurface.hx new file mode 100644 index 000000000..930791e1a --- /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 = 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/utils/ByteArray.hx b/lime/utils/ByteArray.hx index c64da9d1d..712f2b95c 100644 --- a/lime/utils/ByteArray.hx +++ b/lime/utils/ByteArray.hx @@ -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,6 +1102,7 @@ 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/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 8835cc269..764b204d0 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -127,6 +127,23 @@ namespace lime { } + value lime_bytes_from_data_pointer (value data, value length) { + + int size = val_int (length); + intptr_t ptr = (intptr_t)val_float (data); + Bytes bytes = Bytes (size); + + if (ptr) { + + memcpy (bytes.Data (), (const void*)ptr, size); + + } + + return bytes.Value (); + + } + + value lime_bytes_get_data_pointer (value bytes) { Bytes data = Bytes (bytes); @@ -1111,6 +1128,7 @@ namespace lime { DEFINE_PRIM (lime_application_set_frame_rate, 2); DEFINE_PRIM (lime_application_update, 1); DEFINE_PRIM (lime_audio_load, 1); + DEFINE_PRIM (lime_bytes_from_data_pointer, 2); DEFINE_PRIM (lime_bytes_get_data_pointer, 1); DEFINE_PRIM (lime_bytes_read_file, 1); DEFINE_PRIM (lime_font_get_ascender, 1); diff --git a/project/src/graphics/cairo/CairoBindings.cpp b/project/src/graphics/cairo/CairoBindings.cpp index 09b2d63ef..ec3ac8a79 100644 --- a/project/src/graphics/cairo/CairoBindings.cpp +++ b/project/src/graphics/cairo/CairoBindings.cpp @@ -368,16 +368,37 @@ namespace lime { } + value lime_cairo_image_surface_get_data (value handle) { + + return alloc_float ((intptr_t)cairo_image_surface_get_data ((cairo_surface_t*)(intptr_t)val_float (handle))); + + } + + + value lime_cairo_image_surface_get_format (value handle) { + + return alloc_int ((int)cairo_image_surface_get_format ((cairo_surface_t*)(intptr_t)val_float (handle))); + + } + + value lime_cairo_image_surface_get_height (value handle) { - return alloc_int ((intptr_t)cairo_image_surface_get_height ((cairo_surface_t*)(intptr_t)val_float (handle))); + return alloc_int (cairo_image_surface_get_height ((cairo_surface_t*)(intptr_t)val_float (handle))); + + } + + + value lime_cairo_image_surface_get_stride (value handle) { + + return alloc_int (cairo_image_surface_get_stride ((cairo_surface_t*)(intptr_t)val_float (handle))); } value lime_cairo_image_surface_get_width (value handle) { - return alloc_int ((intptr_t)cairo_image_surface_get_width ((cairo_surface_t*)(intptr_t)val_float (handle))); + return alloc_int (cairo_image_surface_get_width ((cairo_surface_t*)(intptr_t)val_float (handle))); } @@ -993,7 +1014,10 @@ namespace lime { DEFINE_PRIM (lime_cairo_identity_matrix, 1); DEFINE_PRIM (lime_cairo_image_surface_create, 3); DEFINE_PRIM (lime_cairo_image_surface_create_for_data, 5); + DEFINE_PRIM (lime_cairo_image_surface_get_data, 1); + DEFINE_PRIM (lime_cairo_image_surface_get_format, 1); DEFINE_PRIM (lime_cairo_image_surface_get_height, 1); + DEFINE_PRIM (lime_cairo_image_surface_get_stride, 1); DEFINE_PRIM (lime_cairo_image_surface_get_width, 1); DEFINE_PRIM (lime_cairo_in_clip, 3); DEFINE_PRIM (lime_cairo_in_fill, 3); From 8e8c927cd3e7cfe347e469f47e2c17e93fc8bd76 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 17:07:04 -0700 Subject: [PATCH 33/76] Compile fix --- lime/graphics/cairo/CairoImageSurface.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/graphics/cairo/CairoImageSurface.hx b/lime/graphics/cairo/CairoImageSurface.hx index 930791e1a..0f83305df 100644 --- a/lime/graphics/cairo/CairoImageSurface.hx +++ b/lime/graphics/cairo/CairoImageSurface.hx @@ -19,7 +19,7 @@ import lime.system.System; #if lime_cairo this = lime_cairo_image_surface_create (format, width, height); #else - this = 0; + this = cast 0; #end } From ee6d7edf70af2263332ff1ba91e8d381425603c2 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 17:07:19 -0700 Subject: [PATCH 34/76] Set the default frameRate for HTML5 --- lime/_backend/html5/HTML5Application.hx | 1 + lime/project/HXProject.hx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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/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: From 7e1cab39ef1bd322db14ceda40d501835bb2d392 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 22:27:03 -0700 Subject: [PATCH 35/76] Minor change --- lime/_backend/native/NativeApplication.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index bfb02bf86..786437889 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -144,10 +144,12 @@ class NativeApplication { case CONNECT: - if (!Gamepad.devices.exists(gamepadEventInfo.id)) { + 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: From 81dd6519f89da770eeeeb87d7b6982d09d0f9d4f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 15 Jul 2015 23:07:02 -0700 Subject: [PATCH 36/76] Safety against null gamepad --- lime/_backend/native/NativeApplication.hx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index 786437889..69ef70bd5 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -132,15 +132,18 @@ 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: @@ -157,7 +160,7 @@ class NativeApplication { 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); } From 902bd24ef36c5733d4c375f14b057d9a89ded23a Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 16 Jul 2015 07:28:52 -0700 Subject: [PATCH 37/76] Image sync fix --- lime/graphics/utils/ImageCanvasUtil.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index d306bc067..222ebc3b4 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -343,7 +343,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; From 7537b018a4ee8c9bb6897bb5cfda8ea9ecea72ba Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 08:40:45 -0700 Subject: [PATCH 38/76] Quiet 'known incorrect' color profile messages from libpng --- project/lib/png | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/lib/png b/project/lib/png index 95d51b67a..601ea3ce9 160000 --- a/project/lib/png +++ b/project/lib/png @@ -1 +1 @@ -Subproject commit 95d51b67a1be7b8112b411f0d7f8f0cb70e68b58 +Subproject commit 601ea3ce9b4af315bed7f371348305b28b3a231c From d4f0011de125a954f1be7670a447940950d36a6a Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 08:57:16 -0700 Subject: [PATCH 39/76] ArrayBufferView fix --- lime/utils/ArrayBufferView.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/utils/ArrayBufferView.hx b/lime/utils/ArrayBufferView.hx index d3fc7206a..9797f8d44 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 { From 0c9bd8916f3a70a06aa8fc10faee5f805022913f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 10:34:46 -0700 Subject: [PATCH 40/76] Try to ignore XML files that are not project files when running Lime commands in the wrong directory --- tools/CommandLineTools.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CommandLineTools.hx b/tools/CommandLineTools.hx index 8c36f0280..b268642c8 100644 --- a/tools/CommandLineTools.hx +++ b/tools/CommandLineTools.hx @@ -1259,7 +1259,7 @@ class CommandLineTools { } - if (project == null) { + if (project == null || project.sources.length == 0) { LogHelper.error ("You must have a \"project.xml\" file or specify another valid project file when using the '" + command + "' command"); return null; From 0e585e54c7b616ed99cde17b5d3a2c4df5dafd83 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 10:51:28 -0700 Subject: [PATCH 41/76] Fix rebuild --- tools/CommandLineTools.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CommandLineTools.hx b/tools/CommandLineTools.hx index b268642c8..7a2ada712 100644 --- a/tools/CommandLineTools.hx +++ b/tools/CommandLineTools.hx @@ -1259,7 +1259,7 @@ class CommandLineTools { } - if (project == null || project.sources.length == 0) { + if (project == null || (command != "rebuild" && project.sources.length == 0)) { LogHelper.error ("You must have a \"project.xml\" file or specify another valid project file when using the '" + command + "' command"); return null; From 0478a54e37e853bfd4825472f98a6bf128e5eb5e Mon Sep 17 00:00:00 2001 From: Nilsen Filc Date: Fri, 17 Jul 2015 22:30:13 +0200 Subject: [PATCH 42/76] Gamepad controller axis deadzone low filter Added gamepad controller axis deadzone low filter, removing unnecessary spam from controller analog sticks natural jitter. Base filter set default at value 1000. Tested with multiple gamepads connected at the same time (Sony PS3). --- project/src/backend/sdl/SDLApplication.cpp | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index 94a6216d3..cfbc9461b 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -15,7 +15,8 @@ namespace lime { AutoGCRoot* Application::callback = 0; SDLApplication* SDLApplication::currentApplication = 0; - + std::map > gamepadsAxisMap; + const int analogAxisDeadZone = 1000; SDLApplication::SDLApplication () { @@ -239,9 +240,36 @@ namespace lime { case SDL_CONTROLLERAXISMOTION: + if (gamepadsAxisMap[event->caxis.which].empty()) { + + gamepadsAxisMap[event->caxis.which][event->caxis.axis] = event->caxis.value; + + } + else if (gamepadsAxisMap[event->caxis.which][event->caxis.axis] == event->caxis.value) { + + break; + + } + gamepadEvent.type = AXIS_MOVE; gamepadEvent.axis = event->caxis.axis; gamepadEvent.id = event->caxis.which; + + if (event->caxis.value > -analogAxisDeadZone && event->caxis.value < analogAxisDeadZone) { + + if (gamepadsAxisMap[event->caxis.which][event->caxis.axis] != 0) { + + gamepadsAxisMap[event->caxis.which][event->caxis.axis] = 0; + gamepadEvent.axisValue = 0; + GamepadEvent::Dispatch (&gamepadEvent); + + } + + break; + + } + + gamepadsAxisMap[event->caxis.which][event->caxis.axis] = event->caxis.value; gamepadEvent.axisValue = event->caxis.value / 32768.0; GamepadEvent::Dispatch (&gamepadEvent); From 7bed38562c2bc354724813774420f4b8c48e0ed9 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 16:46:07 -0700 Subject: [PATCH 43/76] Fix use of Assets.load* with the same ID and different callbacks --- templates/haxe/DefaultAssetLibrary.hx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/templates/haxe/DefaultAssetLibrary.hx b/templates/haxe/DefaultAssetLibrary.hx index 6dba668c7..fa9febadd 100644 --- a/templates/haxe/DefaultAssetLibrary.hx +++ b/templates/haxe/DefaultAssetLibrary.hx @@ -40,7 +40,6 @@ class DefaultAssetLibrary extends AssetLibrary { public var type (default, null) = new Map (); private var lastModified:Float; - private var loadHandlers:Map; private var threadPool:ThreadPool; private var timer:Timer; @@ -137,15 +136,15 @@ class DefaultAssetLibrary extends AssetLibrary { private function createThreadPool ():Void { threadPool = new ThreadPool (0, 2); - threadPool.doWork.add (function (id, getMethod) { + threadPool.doWork.add (function (id, data) { - threadPool.sendComplete (id, getMethod (id)); + data.result = data.getMethod (id); + threadPool.sendComplete (data.handler, data); }); threadPool.onComplete.add (function (id, data) { - var handler = loadHandlers.get (id); - handler (data); + data.handler (data.result); }); @@ -570,13 +569,11 @@ class DefaultAssetLibrary extends AssetLibrary { if (threadPool == null) { - loadHandlers = new Map (); createThreadPool (); } - loadHandlers.set (id, handler); - threadPool.queue (id, getBytes); + threadPool.queue (id, { handler: handler, getMethod: getBytes }); #end @@ -626,13 +623,11 @@ class DefaultAssetLibrary extends AssetLibrary { if (threadPool == null) { - loadHandlers = new Map (); createThreadPool (); } - loadHandlers.set (id, handler); - threadPool.queue (id, getImage); + threadPool.queue (id, { handler: handler, getMethod: getImage }); #end From ca6bbb4bd6ea5893d9fbde75af7860641cd4fd2e Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 16:56:29 -0700 Subject: [PATCH 44/76] Update to 2.5.0 --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index 11f7d529c..b51512542 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.9", - "releasenote": "Added ThreadPool, Log and made other improvements", + "version": "2.5.0", + "releasenote": "Improvements to gamepad and Cairo support, stability updates", "contributors": [ "singmajesty" ] } From 9b207c2b8d1e330f7428e041613c3ebcda466d16 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Fri, 17 Jul 2015 16:56:38 -0700 Subject: [PATCH 45/76] Update CHANGELOG --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c810c189..43be4c17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +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) ------------------ From fd8ef590284b68a93c78c8f11e32906dd5914706 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Sun, 19 Jul 2015 10:24:37 -0700 Subject: [PATCH 46/76] Add a library 'prefix' value, for generated class names --- lime/project/Library.hx | 6 ++++-- lime/project/ProjectXMLParser.hx | 9 ++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) 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)); } From 75b807f91a274de1904608786d01c37517d473ea Mon Sep 17 00:00:00 2001 From: Matan Uberstein Date: Mon, 20 Jul 2015 11:39:14 +0200 Subject: [PATCH 47/76] Fixed html5 image loading through DefaultAssetLibrary where id and path doesn't match. --- templates/haxe/DefaultAssetLibrary.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/haxe/DefaultAssetLibrary.hx b/templates/haxe/DefaultAssetLibrary.hx index fa9febadd..dae62895f 100644 --- a/templates/haxe/DefaultAssetLibrary.hx +++ b/templates/haxe/DefaultAssetLibrary.hx @@ -611,7 +611,7 @@ class DefaultAssetLibrary extends AssetLibrary { handler (Image.fromImageElement (image)); } - image.src = id; + image.src = path.get (id); } else { From 26154a4bab34de48ed8f4c6b3d9c071197f010da Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 20 Jul 2015 22:19:38 -0700 Subject: [PATCH 48/76] Add support for all pixel formats in Image, switch PixelFormat to RGBA32 (etc) to denote color order and pixel size --- lime/graphics/Image.hx | 16 +- lime/graphics/ImageBuffer.hx | 2 +- lime/graphics/PixelFormat.hx | 6 +- lime/graphics/format/BMP.hx | 2 +- lime/graphics/utils/ImageCanvasUtil.hx | 2 +- lime/graphics/utils/ImageDataUtil.hx | 864 +++++++++++-------------- lime/math/ColorMatrix.hx | 112 +++- lime/math/color/ARGB.hx | 209 ++++++ lime/math/color/BGRA.hx | 208 ++++++ lime/math/color/RGBA.hx | 239 +++++++ lime/tools/helpers/IconHelper.hx | 2 +- 11 files changed, 1151 insertions(+), 511 deletions(-) create mode 100644 lime/math/color/ARGB.hx create mode 100644 lime/math/color/BGRA.hx create mode 100644 lime/math/color/RGBA.hx diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index 908f70b11..f085edb9a 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -388,7 +388,7 @@ class Image { case FLASH: rect.offset (offsetX, offsetY); - if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8); + if (format == null || format == RGBA32) color = ((color & 0xFF) << 24) | (color >> 8); buffer.__srcBitmapData.fillRect (rect.__toFlashRectangle (), color); default: @@ -418,7 +418,7 @@ class Image { case FLASH: - if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8); + if (format == null || format == RGBA32) color = ((color & 0xFF) << 24) | (color >> 8); buffer.__srcBitmapData.floodFill (x + offsetX, y + offsetY, color); default: @@ -538,7 +538,7 @@ class Image { var color = buffer.__srcBitmapData.getPixel (x + offsetX, y + offsetY); - if (format == null || format == RGBA) { + if (format == null || format == RGBA32) { return ((color & 0xFF) << 24) | (color >> 8); @@ -579,7 +579,7 @@ class Image { var color = buffer.__srcBitmapData.getPixel32 (x + offsetX, y + offsetY); - if (format == null || format == RGBA) { + if (format == null || format == RGBA32) { return ((color & 0xFF) << 24) | (color >> 8); @@ -621,7 +621,7 @@ class Image { rect.offset (offsetX, offsetY); var byteArray = buffer.__srcBitmapData.getPixels (rect.__toFlashRectangle ()); - if (format == null || format == RGBA) { + if (format == null || format == RGBA32) { var color; var length = Std.int (byteArray.length / 4); @@ -771,7 +771,7 @@ class Image { case FLASH: - if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8); + if (format == null || format == RGBA32) color = ((color & 0xFF) << 24) | (color >> 8); buffer.__srcBitmapData.setPixel (x + offsetX, y + offsetX, color); default: @@ -801,7 +801,7 @@ class Image { case FLASH: - if (format == null || format == RGBA) color = ((color & 0xFF) << 24) | (color >> 8); + if (format == null || format == RGBA32) color = ((color & 0xFF) << 24) | (color >> 8); buffer.__srcBitmapData.setPixel32 (x + offsetX, y + offsetY, color); default: @@ -833,7 +833,7 @@ class Image { case FLASH: rect.offset (offsetX, offsetY); - if (format == null || format == RGBA) { + if (format == null || format == RGBA32) { var srcData = byteArray; byteArray = new ByteArray (); diff --git a/lime/graphics/ImageBuffer.hx b/lime/graphics/ImageBuffer.hx index f09122d66..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; } 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/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 222ebc3b4..8214068a8 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -201,7 +201,7 @@ class ImageCanvasUtil { var r, g, b, a; - if (format == ARGB) { + if (format == ARGB32) { r = (color >> 16) & 0xFF; g = (color >> 8) & 0xFF; diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 547b1d04f..a7919f875 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -2,10 +2,15 @@ package lime.graphics.utils; import haxe.ds.Vector; +import haxe.Int32; import haxe.io.Bytes; +import haxe.io.UInt32Array; 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,79 +18,45 @@ 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; if (data == null) return; - #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_color_transform (image, rect, colorMatrix); else - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_color_transform (image, rect, colorMatrix); else + //#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); } @@ -123,64 +94,53 @@ class ImageDataUtil { if (srcData == null || destData == null) return; - #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else + //#end { - var width = sourceRect.width; - var height = sourceRect.height; + var srcView = new ImageDataView (sourceImage, sourceRect); + var destView = new ImageDataView (image, new Rectangle (destPoint.x, destPoint.y, srcView.width, srcView.height)); - if (destPoint.x + width > image.width) { - - width = image.width - destPoint.x; - - } + var srcFormat = sourceImage.buffer.format; + var destFormat = image.buffer.format; + var srcPremultiplied = sourceImage.buffer.premultiplied; + var destPremultiplied = image.buffer.premultiplied; - if (sourceRect.x + width > sourceImage.width) { - - width = sourceImage.width - sourceRect.x; - - } + var srcPosition, destPosition, srcPixel:RGBA, destPixel:RGBA, value = 0; - if (destPoint.y + height > image.height) { + for (y in 0...destView.height) { - height = image.height - destPoint.y; + srcPosition = srcView.row (y); + destPosition = destView.row (y); - } - - if (sourceRect.y + height > sourceImage.height) { - - height = sourceImage.height - sourceRect.y; - - } - - if (width <= 0 || height <= 0) return; - - 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 * width); - var srcRowEnd = Std.int (4 * (sourceRect.x + sourceImage.offsetX + width)); - var srcData = sourceImage.buffer.data; - - 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 * width); - var destData = image.buffer.data; - - var length = Std.int (width * height); - - for (i in 0...length) { - - destData[destPosition] = srcData[srcPosition]; - - srcPosition += 4; - destPosition += 4; - - if ((srcPosition % srcStride) > srcRowEnd) { + for (x in 0...destView.width) { - srcPosition += srcRowOffset; - destPosition += destRowOffset; + srcPixel.readUInt8 (srcData, srcPosition, srcFormat, srcPremultiplied); + destPixel.readUInt8 (destData, destPosition, destFormat, destPremultiplied); + + switch (srcIdx) { + + case 0: value = srcPixel.r; + case 1: value = srcPixel.g; + case 2: value = srcPixel.b; + case 3: value = srcPixel.a; + + } + + 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; } @@ -195,56 +155,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 - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, 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; } @@ -252,28 +196,77 @@ 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); + + 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); + + 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; + + } } @@ -290,80 +283,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 - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, rgba); else + //#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); } @@ -381,25 +337,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 - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_flood_fill (image, x, y, color); else + //#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 ]; @@ -413,15 +373,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) { @@ -429,14 +391,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); @@ -464,7 +424,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; @@ -623,28 +583,15 @@ 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 >> 8 & 0xFFFFFF; + default: return pixel; } @@ -653,33 +600,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; } @@ -699,78 +628,47 @@ class ImageDataUtil { byteArray.position = 0; #end - #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_get_pixels (image, rect, format, byteArray); else - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_get_pixels (image, rect, format, byteArray); else + //#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; - #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 (position, pixel.r); + byteArray.__set (position + 1, pixel.g); + byteArray.__set (position + 2, pixel.b); + byteArray.__set (position + 3, pixel.a); #end - if ((srcPosition % srcStride) > srcRowEnd) { - - srcPosition += srcRowOffset; - - } + position += 4; } @@ -788,33 +686,42 @@ class ImageDataUtil { if (image.buffer.data == null || sourceImage.buffer.data == null) return; - #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); else - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); 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 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; } @@ -837,17 +744,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); } @@ -883,6 +787,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; @@ -977,21 +883,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; @@ -1002,21 +908,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; @@ -1051,14 +957,12 @@ 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; + if (format == RGBA32) color = color >> 8; - data[offset] = (color & 0xFF0000) >>> 16; - data[offset + 1] = (color & 0x00FF00) >>> 8; - data[offset + 2] = (color & 0x0000FF); - if (image.transparent) data[offset + 3] = (0xFF); + var pixel:RGBA = 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; @@ -1067,42 +971,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; } - if (image.transparent && image.premultiplied) { - - var a16 = __alpha16[a]; - data[offset] = (r * a16) >> 16; - data[offset + 1] = (g * a16) >> 16; - data[offset + 2] = (b * a16) >> 16; - data[offset + 3] = a; - - } else { - - data[offset] = r; - data[offset + 1] = g; - data[offset + 2] = b; - data[offset + 3] = a; - - } + 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; @@ -1113,66 +993,36 @@ class ImageDataUtil { if (image.buffer.data == null) return; - #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format); else - #end + //#if ((cpp || neko) && !disable_cffi) + //if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format); else + //#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); } @@ -1195,24 +1045,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); } @@ -1247,4 +1087,72 @@ class ImageDataUtil { #end +} + + +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; + + } + + } \ No newline at end of file diff --git a/lime/math/ColorMatrix.hx b/lime/math/ColorMatrix.hx index 1250b1c4b..caf2dd0c1 100644 --- a/lime/math/ColorMatrix.hx +++ b/lime/math/ColorMatrix.hx @@ -1,6 +1,7 @@ package lime.math; +import haxe.io.UInt8Array; import lime.utils.Float32Array; #if flash @@ -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/color/ARGB.hx b/lime/math/color/ARGB.hx new file mode 100644 index 000000000..f1ffbfcf6 --- /dev/null +++ b/lime/math/color/ARGB.hx @@ -0,0 +1,209 @@ +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 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 multiplyAlpha () { + + a16 = RGBA.__alpha16[a]; + set (a, (r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16); + + } + + + public inline function unmultiplyAlpha () { + + if (a != 0) { + + 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 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 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..f644f7101 --- /dev/null +++ b/lime/math/color/BGRA.hx @@ -0,0 +1,208 @@ +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 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 multiplyAlpha () { + + a16 = RGBA.__alpha16[a]; + set ((b * a16) >> 16, (g * a16) >> 16, (r * a16) >> 16, a); + + } + + + public inline function unmultiplyAlpha () { + + if (a != 0) { + + 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 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 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..b3e0c83e3 --- /dev/null +++ b/lime/math/color/RGBA.hx @@ -0,0 +1,239 @@ +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.floor (i * (1 << 16) / 255); + + } + + __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 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 multiplyAlpha () { + + a16 = __alpha16[a]; + set ((r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16, a); + + } + + + public inline function unmultiplyAlpha () { + + if (a != 0) { + + unmult = 255.0 / a; + set (__clamp[Math.floor (r * unmult)], __clamp[Math.floor (g * unmult)], __clamp[Math.floor (b * unmult)], a); + + } + + } + + + 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 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/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); From 784e957e9496edc1ad713beb7aecefdfa89362e8 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 20 Jul 2015 22:56:26 -0700 Subject: [PATCH 49/76] Fix import --- lime/math/ColorMatrix.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/math/ColorMatrix.hx b/lime/math/ColorMatrix.hx index caf2dd0c1..d01becb4c 100644 --- a/lime/math/ColorMatrix.hx +++ b/lime/math/ColorMatrix.hx @@ -1,8 +1,8 @@ package lime.math; -import haxe.io.UInt8Array; import lime.utils.Float32Array; +import lime.utils.UInt8Array; #if flash import flash.geom.ColorTransform; From 1354a5106bcf0b9a5e3935d94e578bcb2353a4c5 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Mon, 20 Jul 2015 22:59:47 -0700 Subject: [PATCH 50/76] Clean up import --- lime/graphics/utils/ImageDataUtil.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index a7919f875..028f70e85 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -4,7 +4,6 @@ package lime.graphics.utils; import haxe.ds.Vector; import haxe.Int32; import haxe.io.Bytes; -import haxe.io.UInt32Array; import lime.graphics.Image; import lime.graphics.ImageBuffer; import lime.graphics.PixelFormat; From c0ef737af07d4f41836a3695914c470875d1f252 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 09:07:52 -0700 Subject: [PATCH 51/76] Begin implementation of C++ Image data methods again --- lime/graphics/utils/ImageDataUtil.hx | 22 +- lime/math/Rectangle.hx | 4 +- lime/math/color/ARGB.hx | 30 ++- lime/math/color/BGRA.hx | 30 ++- lime/math/color/RGBA.hx | 34 ++- project/include/graphics/ImageBuffer.h | 3 +- project/include/graphics/PixelFormat.h | 6 +- .../include/graphics/utils/ImageDataUtil.h | 26 +++ project/include/math/ColorMatrix.h | 11 +- project/include/math/Rectangle.h | 2 + project/include/math/color/ARGB.h | 40 ++++ project/include/math/color/BGRA.h | 40 ++++ project/include/math/color/RGBA.h | 204 ++++++++++++++++++ project/src/graphics/ImageBuffer.cpp | 10 +- project/src/graphics/utils/ImageDataUtil.cpp | 154 ++++++------- project/src/math/ColorMatrix.cpp | 62 +++++- project/src/math/Rectangle.cpp | 19 ++ 17 files changed, 566 insertions(+), 131 deletions(-) create mode 100644 project/include/math/color/ARGB.h create mode 100644 project/include/math/color/BGRA.h create mode 100644 project/include/math/color/RGBA.h diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index 028f70e85..ce4f36b32 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -28,9 +28,9 @@ class ImageDataUtil { var data = image.buffer.data; if (data == null) return; - //#if ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_color_transform (image, rect, colorMatrix); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_color_transform (image, rect, colorMatrix); else + #end { var format = image.buffer.format; @@ -215,10 +215,18 @@ class ImageDataUtil { oneMinusSourceAlpha = 1 - sourceAlpha; blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha); - 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)]; + 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); 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 index f1ffbfcf6..dcbd16abd 100644 --- a/lime/math/color/ARGB.hx +++ b/lime/math/color/ARGB.hx @@ -34,6 +34,22 @@ abstract ARGB(Int) from Int to Int { } + 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) { @@ -61,17 +77,16 @@ abstract ARGB(Int) from Int to Int { } - public inline function multiplyAlpha () { + public inline function set (a:Int, r:Int, g:Int, b:Int):Void { - a16 = RGBA.__alpha16[a]; - set (a, (r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16); + this = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF); } public inline function unmultiplyAlpha () { - if (a != 0) { + 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)]); @@ -81,13 +96,6 @@ abstract ARGB(Int) from Int to Int { } - 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 writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void { if (premultiplied) { diff --git a/lime/math/color/BGRA.hx b/lime/math/color/BGRA.hx index f644f7101..7bba30d32 100644 --- a/lime/math/color/BGRA.hx +++ b/lime/math/color/BGRA.hx @@ -34,6 +34,22 @@ abstract BGRA(Int) from Int to Int { } + 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) { @@ -61,17 +77,16 @@ abstract BGRA(Int) from Int to Int { } - public inline function multiplyAlpha () { + public inline function set (b:Int, g:Int, r:Int, a:Int):Void { - a16 = RGBA.__alpha16[a]; - set ((b * a16) >> 16, (g * a16) >> 16, (r * a16) >> 16, a); + this = ((b & 0xFF) << 24) | ((g & 0xFF) << 16) | ((r & 0xFF) << 8) | (a & 0xFF); } public inline function unmultiplyAlpha () { - if (a != 0) { + 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); @@ -81,13 +96,6 @@ abstract BGRA(Int) from Int to Int { } - 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 writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void { if (premultiplied) { diff --git a/lime/math/color/RGBA.hx b/lime/math/color/RGBA.hx index b3e0c83e3..e86f73b5a 100644 --- a/lime/math/color/RGBA.hx +++ b/lime/math/color/RGBA.hx @@ -65,6 +65,26 @@ abstract RGBA(Int) from Int to Int { } + 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) { @@ -92,17 +112,16 @@ abstract RGBA(Int) from Int to Int { } - public inline function multiplyAlpha () { + public inline function set (r:Int, g:Int, b:Int, a:Int):Void { - a16 = __alpha16[a]; - set ((r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16, a); + this = ((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF); } public inline function unmultiplyAlpha () { - if (a != 0) { + if (a != 0 && a != 0xFF) { unmult = 255.0 / a; set (__clamp[Math.floor (r * unmult)], __clamp[Math.floor (g * unmult)], __clamp[Math.floor (b * unmult)], a); @@ -112,13 +131,6 @@ abstract RGBA(Int) from Int to Int { } - 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 writeUInt8 (data:UInt8Array, offset:Int, format:PixelFormat = RGBA32, premultiplied:Bool = false):Void { if (premultiplied) { 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/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h index 02e1e86fc..e67ec5299 100644 --- a/project/include/graphics/utils/ImageDataUtil.h +++ b/project/include/graphics/utils/ImageDataUtil.h @@ -37,6 +37,32 @@ namespace lime { }; + class ImageDataView { + + + public: + + ImageDataView (Image* image, Rectangle* rect); + + void Clip (int x, int y, int width, int height); + int Row (int y); + + int x; + int y; + int width; + int height; + + private: + + Image* image; + int offset; + Rectangle* rect; + int stride; + + + }; + + } diff --git a/project/include/math/ColorMatrix.h b/project/include/math/ColorMatrix.h index 8d3b80fc8..1de6c652b 100644 --- a/project/include/math/ColorMatrix.h +++ b/project/include/math/ColorMatrix.h @@ -4,6 +4,7 @@ #include #include +#include namespace lime { @@ -20,16 +21,24 @@ namespace lime { float GetAlphaMultiplier (); float GetAlphaOffset (); + void GetAlphaTable (unsigned char* table); float GetBlueMultiplier (); float GetBlueOffset (); - int GetColor (); + void GetBlueTable (unsigned char* table); + int32_t GetColor (); float GetGreenMultiplier (); float GetGreenOffset (); + void GetGreenTable (unsigned char* table); float GetRedMultiplier (); float GetRedOffset (); + void GetRedTable (unsigned char* table); float data[20]; + private: + + void GetDataTable (unsigned char* table, float multiplier, float offset); + }; diff --git a/project/include/math/Rectangle.h b/project/include/math/Rectangle.h index a6b94f9e2..5c3cbf84d 100644 --- a/project/include/math/Rectangle.h +++ b/project/include/math/Rectangle.h @@ -17,6 +17,8 @@ namespace lime { Rectangle (double x, double y, double width, double height); Rectangle (value rect); + void Contract (double x, double y, double width, double height); + double height; double width; double x; diff --git a/project/include/math/color/ARGB.h b/project/include/math/color/ARGB.h new file mode 100644 index 000000000..8d3b80fc8 --- /dev/null +++ b/project/include/math/color/ARGB.h @@ -0,0 +1,40 @@ +#ifndef LIME_MATH_COLOR_MATRIX_H +#define LIME_MATH_COLOR_MATRIX_H + + +#include +#include + + +namespace lime { + + + class ColorMatrix { + + + public: + + ColorMatrix (); + ColorMatrix (value colorMatrix); + ~ColorMatrix (); + + float GetAlphaMultiplier (); + float GetAlphaOffset (); + float GetBlueMultiplier (); + float GetBlueOffset (); + int GetColor (); + float GetGreenMultiplier (); + float GetGreenOffset (); + float GetRedMultiplier (); + float GetRedOffset (); + + float data[20]; + + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/include/math/color/BGRA.h b/project/include/math/color/BGRA.h new file mode 100644 index 000000000..8d3b80fc8 --- /dev/null +++ b/project/include/math/color/BGRA.h @@ -0,0 +1,40 @@ +#ifndef LIME_MATH_COLOR_MATRIX_H +#define LIME_MATH_COLOR_MATRIX_H + + +#include +#include + + +namespace lime { + + + class ColorMatrix { + + + public: + + ColorMatrix (); + ColorMatrix (value colorMatrix); + ~ColorMatrix (); + + float GetAlphaMultiplier (); + float GetAlphaOffset (); + float GetBlueMultiplier (); + float GetBlueOffset (); + int GetColor (); + float GetGreenMultiplier (); + float GetGreenOffset (); + float GetRedMultiplier (); + float GetRedOffset (); + + float data[20]; + + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/include/math/color/RGBA.h b/project/include/math/color/RGBA.h new file mode 100644 index 000000000..fc96ccee3 --- /dev/null +++ b/project/include/math/color/RGBA.h @@ -0,0 +1,204 @@ +#ifndef LIME_MATH_COLOR_RGBA_H +#define LIME_MATH_COLOR_RGBA_H + + +#include +#include + + +namespace lime { + + + int __alpha16[0xFF + 1]; + int __clamp[0xFF + 0xFF + 1]; + static int a16; + static double unmult; + + int initValues () { + + for (int i = 0; i < 256; i++) { + + // Seem to need +1 to get the same results as Haxe in multiplyAlpha + __alpha16[i] = (i + 1) * ((1 << 16) / 0xFF); + + } + + for (int i = 0; i < 0xFF; i++) { + + __clamp[i] = i; + + } + + for (int i = 0xFF; i < (0xFF + 0xFF + 1); i++) { + + __clamp[i] = 0xFF; + + } + + return 0; + + } + + static int initValues_ = initValues (); + + + struct RGBA { + + + public: + + inline RGBA () { + + r = 0; + g = 0; + b = 0; + a = 0; + + } + + + inline RGBA (int32_t rgba) { + + r = (rgba >> 24) & 0xFF; + g = (rgba >> 16) & 0xFF; + b = (rgba >> 8) & 0xFF; + a = rgba & 0xFF; + + } + + + inline RGBA (unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + + Set (r, g, b, a); + + } + + + inline int32_t Get () { + + int32_t value = ((r & 0xFF) << 24) | ((g & 0xFF) << 16) | ((b & 0xFF) << 8) | (a & 0xFF); + return value; + + } + + + inline void MultiplyAlpha () { + + if (a == 0) { + + Set (0, 0, 0, 0); + + } else if (a != 0xFF) { + + a16 = __alpha16[a]; + Set ((r * a16) >> 16, (g * a16) >> 16, (b * a16) >> 16, a); + + } + + } + + + inline void UnmultiplyAlpha () { + + if (a != 0 && a != 0xFF) { + + unmult = 255.0 / a; + Set (__clamp[(int)(r * unmult)], __clamp[(int)(g * unmult)], __clamp[(int)(b * unmult)], a); + + } + + } + + + inline void ReadUInt8 (const unsigned char* data, int offset, PixelFormat format, bool premultiplied) { + + switch (format) { + + case BGRA32: + + Set (data[offset + 2], data[offset + 1], data[offset], data[offset + 3]); + break; + + case RGBA32: + + Set (data[offset], data[offset + 1], data[offset + 2], data[offset + 3]); + break; + + case ARGB32: + + Set (data[offset + 1], data[offset + 2], data[offset + 3], data[offset]); + break; + + } + + if (premultiplied) { + + UnmultiplyAlpha (); + + } + + } + + + inline void Set (unsigned char r, unsigned char g, unsigned char b, unsigned char a) { + + this->r = r; + this->g = g; + this->b = b; + this->a = a; + + } + + + inline void WriteUInt8 (unsigned char* data, int offset, PixelFormat format, bool premultiplied) { + + if (premultiplied) { + + MultiplyAlpha (); + + } + + switch (format) { + + case BGRA32: + + data[offset] = b; + data[offset + 1] = g; + data[offset + 2] = r; + data[offset + 3] = a; + break; + + case RGBA32: + + data[offset] = r; + data[offset + 1] = g; + data[offset + 2] = b; + data[offset + 3] = a; + break; + + case ARGB32: + + data[offset] = a; + data[offset + 1] = r; + data[offset + 2] = g; + data[offset + 3] = b; + break; + + } + + } + + + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/src/graphics/ImageBuffer.cpp b/project/src/graphics/ImageBuffer.cpp index d6c669c4b..4129d06fa 100644 --- a/project/src/graphics/ImageBuffer.cpp +++ b/project/src/graphics/ImageBuffer.cpp @@ -9,8 +9,9 @@ namespace lime { static int id_data; static int id_format; static int id_height; - static int id_width; + static int id_premultiplied; static int id_transparent; + static int id_width; static bool init = false; @@ -19,8 +20,9 @@ namespace lime { width = 0; height = 0; bitsPerPixel = 32; - format = RGBA; + format = RGBA32; data = 0; + premultiplied = false; transparent = false; } @@ -37,6 +39,7 @@ namespace lime { id_height = val_id ("height"); id_data = val_id ("data"); id_format = val_id ("format"); + id_premultiplied = val_id ("premultiplied"); init = true; } @@ -48,6 +51,7 @@ namespace lime { transparent = val_bool (val_field (imageBuffer, id_transparent)); value data_value = val_field (imageBuffer, id_data); value buffer_value = val_field (data_value, id_buffer); + premultiplied = val_bool (val_field (imageBuffer, id_premultiplied)); data = new Bytes (buffer_value); } @@ -119,6 +123,7 @@ namespace lime { id_height = val_id ("height"); id_data = val_id ("data"); id_format = val_id ("format"); + id_premultiplied = val_id ("premultiplied"); init = true; } @@ -130,6 +135,7 @@ namespace lime { alloc_field (mValue, id_data, data ? data->Value () : alloc_null ()); alloc_field (mValue, id_transparent, alloc_bool (transparent)); alloc_field (mValue, id_format, alloc_int (format)); + alloc_field (mValue, id_premultiplied, alloc_bool (premultiplied)); return mValue; } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 3636e1488..41427ecb7 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -6,77 +7,39 @@ namespace lime { - static int __alpha16[0xFF + 1]; - static int __clamp[0xFF + 0xFF + 1]; - - int initValues () { - - for (int i = 0; i < 256; i++) { - - // Seem to need +1 to get the same results as Haxe in multiplyAlpha - __alpha16[i] = (i + 1) * ((1 << 16) / 0xFF); - - } - - for (int i = 0; i < 0xFF; i++) { - - __clamp[i] = i; - - } - - for (int i = 0xFF; i < (0xFF + 0xFF + 1); i++) { - - __clamp[i] = 0xFF; - - } - - return 0; - - } - - static int initValues_ = initValues (); - - void ImageDataUtil::ColorTransform (Image* image, Rectangle* rect, ColorMatrix* colorMatrix) { - int stride = image->buffer->Stride (); - int offset; - - int rowStart = int (rect->y + image->offsetY); - int rowEnd = int (rect->y + rect->height + image->offsetY); - int columnStart = int (rect->x + image->offsetX); - int columnEnd = int (rect->x + rect->width + image->offsetX); - + PixelFormat format = image->buffer->format; + bool premultiplied = image->buffer->premultiplied; uint8_t* data = (uint8_t*)image->buffer->data->Data (); - int r, g, b, a, ex = 0; - float alphaMultiplier = colorMatrix->GetAlphaMultiplier (); - float redMultiplier = colorMatrix->GetRedMultiplier (); - float greenMultiplier = colorMatrix->GetGreenMultiplier (); - float blueMultiplier = colorMatrix->GetBlueMultiplier (); - int alphaOffset = colorMatrix->GetAlphaOffset (); - int redOffset = colorMatrix->GetRedOffset (); - int greenOffset = colorMatrix->GetGreenOffset (); - int blueOffset = colorMatrix->GetBlueOffset (); + ImageDataView dataView = ImageDataView (image, rect); - for (int row = rowStart; row < rowEnd; row++) { + unsigned char alphaTable[256]; + unsigned char redTable[256]; + unsigned char greenTable[256]; + unsigned char blueTable[256]; + + colorMatrix->GetAlphaTable (alphaTable); + colorMatrix->GetRedTable (redTable); + colorMatrix->GetGreenTable (greenTable); + colorMatrix->GetBlueTable (blueTable); + + int row; + int offset; + RGBA pixel; + + for (int y = 0; y < dataView.height; y++) { - for (int column = columnStart; column < columnEnd; column++) { + row = dataView.Row (y); + + for (int x = 0; x < dataView.width; x++) { - offset = (row * stride) + (column * 4); + offset = row + (x * 4); - a = (data[offset + 3] * alphaMultiplier) + alphaOffset; - ex = a > 0xFF ? a - 0xFF : 0; - b = (data[offset + 2] * blueMultiplier) + blueOffset + ex; - ex = b > 0xFF ? b - 0xFF : 0; - g = (data[offset + 1] * greenMultiplier) + greenOffset + ex; - ex = g > 0xFF ? g - 0xFF : 0; - r = (data[offset] * redMultiplier) + 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); } @@ -336,7 +299,7 @@ namespace lime { int length = int (rect->width * rect->height); pixels->Resize (length * 4); - if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { + if (format == RGBA32 && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { memcpy (pixels->Data (), image->buffer->data->Data (), image->buffer->data->Length ()); return; @@ -351,7 +314,7 @@ namespace lime { int srcRowOffset = srcStride - int (4 * rect->width); int srcRowEnd = int (4 * (rect->x + rect->width)); - if (format == ARGB) { + if (format == ARGB32) { for (int i = 0; i < length; i++) { @@ -510,7 +473,7 @@ namespace lime { switch (image->buffer->format) { - case RGBA: + case RGBA32: r1 = 0; g1 = 1; @@ -518,7 +481,7 @@ namespace lime { a1 = 3; break; - case ARGB: + case ARGB32: r1 = 1; g1 = 2; @@ -526,7 +489,7 @@ namespace lime { a1 = 0; break; - case BGRA: + case BGRA32: r1 = 2; g1 = 1; @@ -538,7 +501,7 @@ namespace lime { switch (format) { - case RGBA: + case RGBA32: r2 = 0; g2 = 1; @@ -546,7 +509,7 @@ namespace lime { a2 = 3; break; - case ARGB: + case ARGB32: r2 = 1; g2 = 2; @@ -554,7 +517,7 @@ namespace lime { a2 = 0; break; - case BGRA: + case BGRA32: r2 = 2; g2 = 1; @@ -587,7 +550,7 @@ namespace lime { void ImageDataUtil::SetPixels (Image* image, Rectangle* rect, Bytes* bytes, PixelFormat format) { - if (format == RGBA && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { + if (format == RGBA32 && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { memcpy (image->buffer->data->Data (), bytes->Data (), bytes->Length ()); return; @@ -599,7 +562,7 @@ namespace lime { int width = image->buffer->width; int color; - if (format == ARGB) { + if (format == ARGB32) { int pos = offset * 4; int len = int (rect->width * rect->height * 4); @@ -676,4 +639,49 @@ namespace lime { } + ImageDataView::ImageDataView (Image* image, Rectangle* rect) { + + this->image = image; + + 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 = ceil (this->rect->x); + y = ceil (this->rect->y); + width = floor (this->rect->width); + height = floor (this->rect->height); + offset = (stride * (this->y + image->offsetY)) + ((this->x + image->offsetX) * 4); + + + } + + + void ImageDataView::Clip (int x, int y, int width, int height) { + + rect->Contract (x, y, width, height); + + this->x = ceil (rect->x); + this->y = ceil (rect->y); + this->width = floor (rect->width); + this->height = floor (rect->height); + offset = (stride * (this->y + image->offsetY)) + ((this->x + image->offsetX) * 4); + + + } + + + inline int ImageDataView::Row (int y) { + + return offset + stride * y; + + } + + } \ No newline at end of file diff --git a/project/src/math/ColorMatrix.cpp b/project/src/math/ColorMatrix.cpp index 34263b3ae..40b4a8725 100644 --- a/project/src/math/ColorMatrix.cpp +++ b/project/src/math/ColorMatrix.cpp @@ -57,67 +57,111 @@ namespace lime { } - float ColorMatrix::GetAlphaMultiplier () { + float inline ColorMatrix::GetAlphaMultiplier () { return data[18]; } - float ColorMatrix::GetAlphaOffset () { + float inline ColorMatrix::GetAlphaOffset () { return data[19] * 255; } - float ColorMatrix::GetBlueMultiplier () { + void ColorMatrix::GetAlphaTable (unsigned char* table) { + + GetDataTable (table, GetAlphaMultiplier (), GetAlphaOffset ()); + + } + + + float inline ColorMatrix::GetBlueMultiplier () { return data[12]; } - float ColorMatrix::GetBlueOffset () { + float inline ColorMatrix::GetBlueOffset () { return data[14] * 255; } - int ColorMatrix::GetColor () { + void ColorMatrix::GetBlueTable (unsigned char* table) { + + GetDataTable (table, GetBlueMultiplier (), GetBlueOffset ()); + + } + + + int32_t inline ColorMatrix::GetColor () { return ((int (GetRedOffset ()) << 16) | (int (GetGreenOffset ()) << 8) | int (GetBlueOffset ())); } - float ColorMatrix::GetGreenMultiplier () { + void inline ColorMatrix::GetDataTable (unsigned char* table, float multiplier, float offset) { + + int32_t value; + + for (int i = 0; i < 256; i++) { + + value = floor (i * multiplier + offset); + if (value > 0xFF) value = 0xFF; + if (value < 0) value = 0; + table[i] = value; + + } + + } + + + float inline ColorMatrix::GetGreenMultiplier () { return data[6]; } - float ColorMatrix::GetGreenOffset () { + float inline ColorMatrix::GetGreenOffset () { return data[9] * 255; } - float ColorMatrix::GetRedMultiplier () { + void ColorMatrix::GetGreenTable (unsigned char* table) { + + GetDataTable (table, GetGreenMultiplier (), GetGreenOffset ()); + + } + + + float inline ColorMatrix::GetRedMultiplier () { return data[0]; } - float ColorMatrix::GetRedOffset () { + float inline ColorMatrix::GetRedOffset () { return data[4] * 255; } + void ColorMatrix::GetRedTable (unsigned char* table) { + + GetDataTable (table, GetRedMultiplier (), GetRedOffset ()); + + } + + } \ No newline at end of file diff --git a/project/src/math/Rectangle.cpp b/project/src/math/Rectangle.cpp index dcdc0c5bf..0ce21c467 100644 --- a/project/src/math/Rectangle.cpp +++ b/project/src/math/Rectangle.cpp @@ -51,4 +51,23 @@ namespace lime { } + void Rectangle::Contract (double x, double y, double width, double height) { + + if (this->width == 0 && this->height == 0) { + + return; + + } + + //double cacheRight = this->x + this->width; + //double cacheBottom = this->y + this->height; + + if (this->x < x) this->x = x; + if (this->y < y) this->y = y; + if (this->x + this->width > x + width) this->width = x + width - this->x; + if (this->y + this->height > y + height) this->height = y + height - this->y; + + } + + } \ No newline at end of file From e54502354c40e4d837e6da9be38c2e208c38c82c Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 09:15:09 -0700 Subject: [PATCH 52/76] Fix divide by zero (thanks @larsiusprime, @hasufel) --- lime/graphics/utils/ImageDataUtil.hx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index ce4f36b32..ee5cc2cdf 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -263,10 +263,18 @@ class ImageDataUtil { oneMinusSourceAlpha = 1 - sourceAlpha; blendAlpha = sourceAlpha + (destAlpha * oneMinusSourceAlpha); - 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)]; + 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); From 07db467ab6bdea7893f1cd3468ad467314d601b9 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 09:21:49 -0700 Subject: [PATCH 53/76] Port new copyChannel to native --- lime/graphics/utils/ImageDataUtil.hx | 6 +- project/src/graphics/utils/ImageDataUtil.cpp | 88 ++++++++++---------- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index ee5cc2cdf..dbab59695 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -93,9 +93,9 @@ class ImageDataUtil { if (srcData == null || destData == null) return; - //#if ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_copy_channel (image, sourceImage, sourceRect, destPoint, srcIdx, destIdx); else + #end { var srcView = new ImageDataView (sourceImage, sourceRect); diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 41427ecb7..d301cee22 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -50,59 +50,55 @@ namespace lime { void ImageDataUtil::CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel) { - int width = sourceRect->width; - int height = sourceRect->height; - - if (destPoint->x + width > image->width) { - - width = image->width - destPoint->x; - - } - - if (sourceRect->x + width > sourceImage->width) { - - width = sourceImage->width - sourceRect->x; - - } - - if (destPoint->y + height > image->height) { - - height = image->height - destPoint->y; - - } - - if (sourceRect->y + height > sourceImage->height) { - - height = sourceImage->height - sourceRect->y; - - } - - if (width <= 0 || height <= 0) return; - - int srcStride = sourceImage->buffer->Stride (); - int srcPosition = ((sourceRect->x + sourceImage->offsetX) * 4) + (srcStride * (sourceRect->y + sourceImage->offsetY)) + srcChannel; - int srcRowOffset = srcStride - int (4 * width); - int srcRowEnd = 4 * (sourceRect->x + sourceImage->offsetX + width); uint8_t* srcData = (uint8_t*)sourceImage->buffer->data->Data (); - - int destStride = image->buffer->Stride (); - int destPosition = ((destPoint->x + image->offsetX) * 4) + (destStride * (destPoint->y + image->offsetY)) + destChannel; - int destRowOffset = destStride - int (4 * width); uint8_t* destData = (uint8_t*)image->buffer->data->Data (); - int length = width * height; + ImageDataView srcView = ImageDataView (sourceImage, sourceRect); + ImageDataView destView = ImageDataView (image, &Rectangle (destPoint->x, destPoint->y, srcView.width, srcView.height)); - for (int i = 0; i < length; i++) { + PixelFormat srcFormat = sourceImage->buffer->format; + PixelFormat destFormat = image->buffer->format; + bool srcPremultiplied = sourceImage->buffer->premultiplied; + bool destPremultiplied = image->buffer->premultiplied; + + int srcPosition; + int destPosition; + RGBA srcPixel; + RGBA destPixel; + unsigned char value = 0; + + for (int y = 0; y < destView.height; y++) { - destData[destPosition] = srcData[srcPosition]; + srcPosition = srcView.Row (y); + destPosition = destView.Row (y); - srcPosition += 4; - destPosition += 4; - - if ((srcPosition % srcStride) > srcRowEnd) { + for (int x = 0; x < destView.width; x++) { - srcPosition += srcRowOffset; - destPosition += destRowOffset; + srcPixel.ReadUInt8 (srcData, srcPosition, srcFormat, srcPremultiplied); + destPixel.ReadUInt8 (destData, destPosition, destFormat, destPremultiplied); + + switch (srcChannel) { + + case 0: value = srcPixel.r; break; + case 1: value = srcPixel.g; break; + case 2: value = srcPixel.b; break; + case 3: value = srcPixel.a; break; + + } + + switch (destChannel) { + + case 0: destPixel.r = value; break; + case 1: destPixel.g = value; break; + case 2: destPixel.b = value; break; + case 3: destPixel.a = value; break; + + } + + destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied); + + srcPosition += 4; + destPosition += 4; } From d6750818fcf957a5d529d6a160efe1199e7bbc46 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 10:08:29 -0700 Subject: [PATCH 54/76] More work on pixel operations --- lime/graphics/utils/ImageDataUtil.hx | 14 +- .../include/graphics/utils/ImageDataUtil.h | 2 +- project/include/math/color/RGBA.h | 7 + project/src/ExternalInterface.cpp | 29 ++- project/src/graphics/utils/ImageDataUtil.cpp | 227 +++++++++++------- 5 files changed, 173 insertions(+), 106 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index dbab59695..df59562b3 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -154,9 +154,9 @@ 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 ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, mergeAlpha); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_copy_pixels (image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha); else + #end { var sourceData = sourceImage.buffer.data; @@ -317,9 +317,9 @@ class ImageDataUtil { 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 - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, fillColor); else + #end { var format = image.buffer.format; @@ -1089,7 +1089,7 @@ 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_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", 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_get_pixels = System.load ("lime", "lime_image_data_util_get_pixels", 4); diff --git a/project/include/graphics/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h index e67ec5299..21d72a786 100644 --- a/project/include/graphics/utils/ImageDataUtil.h +++ b/project/include/graphics/utils/ImageDataUtil.h @@ -22,7 +22,7 @@ namespace lime { static void ColorTransform (Image* image, Rectangle* rect, ColorMatrix* ColorMatrix); static void CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel); - static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha); + static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha); static void FillRect (Image* image, Rectangle* rect, int color); static void FloodFill (Image* image, int x, int y, int color); static void GetPixels (Image* image, Rectangle* rect, PixelFormat format, Bytes* pixels); diff --git a/project/include/math/color/RGBA.h b/project/include/math/color/RGBA.h index fc96ccee3..02a6f0f8e 100644 --- a/project/include/math/color/RGBA.h +++ b/project/include/math/color/RGBA.h @@ -189,6 +189,13 @@ namespace lime { } + inline bool operator == (RGBA& rgba) { + + return (a == rgba.a && r == rgba.r && g == rgba.g && b == rgba.b); + + } + + unsigned char r; unsigned char g; unsigned char b; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 764b204d0..d4dded491 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -532,13 +532,28 @@ namespace lime { } - value lime_image_data_util_copy_pixels (value image, value sourceImage, value sourceRect, value destPoint, value mergeAlpha) { + value lime_image_data_util_copy_pixels (value *arg, int nargs) { + + enum { image, sourceImage, sourceRect, destPoint, alphaImage, alphaPoint, mergeAlpha }; + + Image _image = Image (arg[image]); + Image _sourceImage = Image (arg[sourceImage]); + Rectangle _sourceRect = Rectangle (arg[sourceRect]); + Vector2 _destPoint = Vector2 (arg[destPoint]); + + if (val_is_null (arg[alphaImage])) { + + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, 0, 0, val_bool (arg[mergeAlpha])); + + } else { + + Image _alphaImage = Image (arg[alphaImage]); + Vector2 _alphaPoint = Vector2 (arg[alphaPoint]); + + ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, &_alphaImage, &_alphaPoint, val_bool (arg[mergeAlpha])); + + } - Image _image = Image (image); - Image _sourceImage = Image (sourceImage); - Rectangle _sourceRect = Rectangle (sourceRect); - Vector2 _destPoint = Vector2 (destPoint); - ImageDataUtil::CopyPixels (&_image, &_sourceImage, &_sourceRect, &_destPoint, val_bool (mergeAlpha)); return alloc_null (); } @@ -1153,7 +1168,7 @@ namespace lime { DEFINE_PRIM (lime_gamepad_get_device_name, 1); DEFINE_PRIM (lime_image_data_util_color_transform, 3); DEFINE_PRIM_MULT (lime_image_data_util_copy_channel); - DEFINE_PRIM (lime_image_data_util_copy_pixels, 5); + DEFINE_PRIM_MULT (lime_image_data_util_copy_pixels); DEFINE_PRIM (lime_image_data_util_fill_rect, 3); DEFINE_PRIM (lime_image_data_util_flood_fill, 4); DEFINE_PRIM (lime_image_data_util_get_pixels, 4); diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index d301cee22..50246c792 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace lime { @@ -25,8 +26,7 @@ namespace lime { colorMatrix->GetGreenTable (greenTable); colorMatrix->GetBlueTable (blueTable); - int row; - int offset; + int row, offset; RGBA pixel; for (int y = 0; y < dataView.height; y++) { @@ -61,10 +61,8 @@ namespace lime { bool srcPremultiplied = sourceImage->buffer->premultiplied; bool destPremultiplied = image->buffer->premultiplied; - int srcPosition; - int destPosition; - RGBA srcPixel; - RGBA destPixel; + int srcPosition, destPosition; + RGBA srcPixel, destPixel; unsigned char value = 0; for (int y = 0; y < destView.height; y++) { @@ -107,35 +105,36 @@ namespace lime { } - void ImageDataUtil::CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, bool mergeAlpha) { - - int rowOffset = int (destPoint->y + image->offsetY - sourceRect->y - sourceImage->offsetY); - int columnOffset = int (destPoint->x + image->offsetX - sourceRect->x - sourceImage->offsetY); + void ImageDataUtil::CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha) { uint8_t* sourceData = (uint8_t*)sourceImage->buffer->data->Data (); - int sourceStride = sourceImage->buffer->Stride (); - int sourceOffset = 0; + uint8_t* destData = (uint8_t*)image->buffer->data->Data (); - uint8_t* data = (uint8_t*)image->buffer->data->Data (); - int stride = image->buffer->Stride (); - int offset = 0; + ImageDataView sourceView = ImageDataView (sourceImage, sourceRect); + ImageDataView destView = ImageDataView (image, &Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height)); - int rows = sourceRect->y + sourceRect->height + sourceImage->offsetY; - int columns = sourceRect->x + sourceRect->width + sourceImage->offsetX; + PixelFormat sourceFormat = sourceImage->buffer->format; + PixelFormat destFormat = image->buffer->format; + bool sourcePremultiplied = sourceImage->buffer->premultiplied; + bool destPremultiplied = image->buffer->premultiplied; - if (!mergeAlpha || !sourceImage->buffer->transparent) { + int sourcePosition, destPosition; + RGBA sourcePixel; + + if (!mergeAlpha || !sourceImage->transparent) { - for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) { + for (int y = 0; y < destView.height; y++) { - for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) { + sourcePosition = sourceView.Row (y); + destPosition = destView.Row (y); + + for (int x = 0; x < destView.width; x++) { - 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; } @@ -143,27 +142,94 @@ namespace lime { } else { - float sourceAlpha; - float destAlpha; - float outA; - float oneMinusSourceAlpha; + float sourceAlpha, destAlpha, oneMinusSourceAlpha, blendAlpha; + RGBA destPixel; - for (int row = sourceRect->y + sourceImage->offsetY; row < rows; row++) { + if (alphaImage == 0) { - for (int column = sourceRect->x + sourceImage->offsetX; column < columns; column++) { + for (int y = 0; y < destView.height; y++) { - 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 (int x = 0; x < destView.width; x++) { + + 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.Set (0, 0, 0, 0); + + } else { + + destPixel.r = __clamp[int (0.5 + (sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.g = __clamp[int (0.5 + (sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.b = __clamp[int (0.5 + (sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.a = __clamp[int (0.5 + blendAlpha * 255.0)]; + + } + + destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied); + + sourcePosition += 4; + destPosition += 4; + + } - outA = sourceAlpha + destAlpha * oneMinusSourceAlpha; - data[offset + 0] = __clamp[int (0.5 + ((sourceData[sourceOffset + 0] * sourceAlpha + data[offset + 0] * destAlpha * oneMinusSourceAlpha) / outA))]; - data[offset + 1] = __clamp[int (0.5 + ((sourceData[sourceOffset + 1] * sourceAlpha + data[offset + 1] * destAlpha * oneMinusSourceAlpha) / outA))]; - data[offset + 2] = __clamp[int (0.5 + ((sourceData[sourceOffset + 2] * sourceAlpha + data[offset + 2] * destAlpha * oneMinusSourceAlpha) / outA))]; - data[offset + 3] = __clamp[int (0.5 + (outA * 255.0))]; + } + + } else { + + uint8_t* alphaData = (uint8_t*)alphaImage->buffer->data->Data (); + PixelFormat alphaFormat = alphaImage->buffer->format; + bool alphaPremultiplied = alphaImage->buffer->premultiplied; + + ImageDataView alphaView = ImageDataView (alphaImage, &Rectangle (alphaPoint->x, alphaPoint->y, destView.width, destView.height)); + int alphaPosition; + RGBA alphaPixel; + + for (int y = 0; y < alphaView.height; y++) { + + sourcePosition = sourceView.Row (y); + destPosition = destView.Row (y); + alphaPosition = alphaView.Row (y); + + for (int x = 0; x < alphaView.width; x++) { + + 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.Set (0, 0, 0, 0); + + } else { + + destPixel.r = __clamp[int (0.5 + (sourcePixel.r * sourceAlpha + destPixel.r * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.g = __clamp[int (0.5 + (sourcePixel.g * sourceAlpha + destPixel.g * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.b = __clamp[int (0.5 + (sourcePixel.b * sourceAlpha + destPixel.b * destAlpha * oneMinusSourceAlpha) / blendAlpha)]; + destPixel.a = __clamp[int (0.5 + blendAlpha * 255.0)]; + + } + + destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied); + + sourcePosition += 4; + destPosition += 4; + + } } @@ -176,44 +242,21 @@ namespace lime { void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int color) { - int* data = (int*)image->buffer->data->Data (); + uint8_t* data = (uint8_t*)image->buffer->data->Data (); + PixelFormat format = image->buffer->format; + bool premultiplied = image->buffer->premultiplied; - if (rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0 && image->offsetX == 0 && image->offsetY == 0) { + ImageDataView dataView = ImageDataView (image, rect); + int row; + RGBA fillColor (color); + + for (int y = 0; y < dataView.height; y++) { - int length = image->buffer->width * image->buffer->height; + row = dataView.Row (y); - if (color == 0 || color == 0xFFFFFFFF || (color & 0xFF == (color >> 8) & 0xFF && (color >> 8) & 0xFF == (color >> 16) & 0xFF && (color >> 16) & 0xFF == (color >> 24) & 0xFF)) { + for (int x = 0; x < dataView.width; x++) { - memset ((uint8_t*)data, color & 0xFF, length * 4); - - } else { - - for (int i = 0; i < length; i++) { - - data[i] = color; - - } - - } - - } else { - - int stride = image->buffer->width; - int offset; - - int rowStart = int (rect->y + image->offsetY); - int rowEnd = int (rect->y + rect->height + image->offsetY); - int columnStart = int (rect->x + image->offsetX); - int columnEnd = int (rect->x + rect->width + image->offsetX); - - for (int row = rowStart; row < rowEnd; row++) { - - for (int column = columnStart; column < columnEnd; column++) { - - offset = (row * stride) + (column); - data[offset] = color; - - } + fillColor.WriteUInt8 (data, row + (x * 4), format, premultiplied); } @@ -225,19 +268,22 @@ namespace lime { void ImageDataUtil::FloodFill (Image* image, int x, int y, int color) { uint8_t* data = (uint8_t*)image->buffer->data->Data (); + PixelFormat format = image->buffer->format; + bool premultiplied = image->buffer->premultiplied; - int offset = (((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4)); - uint8_t hitColorR = data[offset + 0]; - uint8_t hitColorG = data[offset + 1]; - uint8_t hitColorB = data[offset + 2]; - uint8_t hitColorA = image->transparent ? data[offset + 3] : 0xFF; + RGBA fillColor (color); - uint8_t r = (color >> 24) & 0xFF; - uint8_t g = (color >> 16) & 0xFF; - uint8_t b = (color >> 8) & 0xFF; - uint8_t a = image->transparent ? color & 0xFF : 0xFF; + RGBA hitColor; + hitColor.ReadUInt8 (data, ((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4), format, premultiplied); - if (hitColorR == r && hitColorG == g && hitColorB == b && hitColorA == a) return; + if (!image->transparent) { + + fillColor.a = 0xFF; + hitColor.a = 0xFF; + + } + + if (fillColor == hitColor) return; int dx[4] = { 0, -1, 1, 0 }; int dy[4] = { -1, 0, 0, 1 }; @@ -252,6 +298,7 @@ namespace lime { queue.push_back (y); int curPointX, curPointY, i, nextPointX, nextPointY, nextPointOffset; + RGBA readColor; while (queue.size () > 0) { @@ -270,13 +317,11 @@ namespace lime { } 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_back (nextPointX); queue.push_back (nextPointY); From fadc285209dabd0a5573b25fceb7e7d86c420fa8 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 10:38:29 -0700 Subject: [PATCH 55/76] Fixes --- lime/graphics/utils/ImageDataUtil.hx | 12 ++-- lime/math/color/RGBA.hx | 4 +- project/include/math/color/RGBA.h | 4 +- project/src/graphics/utils/ImageDataUtil.cpp | 62 +++++++------------- 4 files changed, 32 insertions(+), 50 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index df59562b3..d0b7d6562 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -655,6 +655,10 @@ class ImageDataUtil { var dataView = new ImageDataView (image, rect); var position, argb:ARGB, bgra:BGRA, pixel:RGBA; + #if !flash + var destPosition = 0; + #end + for (y in 0...dataView.height) { position = dataView.row (y); @@ -677,10 +681,10 @@ class ImageDataUtil { byteArray.writeByte (pixel.b); byteArray.writeByte (pixel.a); #else - byteArray.__set (position, pixel.r); - byteArray.__set (position + 1, pixel.g); - byteArray.__set (position + 2, pixel.b); - byteArray.__set (position + 3, pixel.a); + byteArray.__set (destPosition++, pixel.r); + byteArray.__set (destPosition++, pixel.g); + byteArray.__set (destPosition++, pixel.b); + byteArray.__set (destPosition++, pixel.a); #end position += 4; diff --git a/lime/math/color/RGBA.hx b/lime/math/color/RGBA.hx index e86f73b5a..6f6753dec 100644 --- a/lime/math/color/RGBA.hx +++ b/lime/math/color/RGBA.hx @@ -28,7 +28,7 @@ abstract RGBA(Int) from Int to Int { for (i in 0...256) { - __alpha16[i] = Math.floor (i * (1 << 16) / 255); + __alpha16[i] = Math.ceil ((i) * ((1 << 16) / 0xFF)); } @@ -124,7 +124,7 @@ abstract RGBA(Int) from Int to Int { if (a != 0 && a != 0xFF) { unmult = 255.0 / a; - set (__clamp[Math.floor (r * unmult)], __clamp[Math.floor (g * unmult)], __clamp[Math.floor (b * unmult)], a); + set (__clamp[Math.round (r * unmult)], __clamp[Math.round (g * unmult)], __clamp[Math.round (b * unmult)], a); } diff --git a/project/include/math/color/RGBA.h b/project/include/math/color/RGBA.h index 02a6f0f8e..b52830f8d 100644 --- a/project/include/math/color/RGBA.h +++ b/project/include/math/color/RGBA.h @@ -4,6 +4,7 @@ #include #include +#include namespace lime { @@ -18,8 +19,7 @@ namespace lime { for (int i = 0; i < 256; i++) { - // Seem to need +1 to get the same results as Haxe in multiplyAlpha - __alpha16[i] = (i + 1) * ((1 << 16) / 0xFF); + __alpha16[i] = ceil ((i + 1) * ((1 << 16) / 0xFF)); } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 50246c792..811014d6e 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -54,7 +54,8 @@ namespace lime { uint8_t* destData = (uint8_t*)image->buffer->data->Data (); ImageDataView srcView = ImageDataView (sourceImage, sourceRect); - ImageDataView destView = ImageDataView (image, &Rectangle (destPoint->x, destPoint->y, srcView.width, srcView.height)); + Rectangle destRect = Rectangle (destPoint->x, destPoint->y, srcView.width, srcView.height); + ImageDataView destView = ImageDataView (image, &destRect); PixelFormat srcFormat = sourceImage->buffer->format; PixelFormat destFormat = image->buffer->format; @@ -111,7 +112,8 @@ namespace lime { uint8_t* destData = (uint8_t*)image->buffer->data->Data (); ImageDataView sourceView = ImageDataView (sourceImage, sourceRect); - ImageDataView destView = ImageDataView (image, &Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height)); + Rectangle destRect = Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height); + ImageDataView destView = ImageDataView (image, &destRect); PixelFormat sourceFormat = sourceImage->buffer->format; PixelFormat destFormat = image->buffer->format; @@ -190,7 +192,8 @@ namespace lime { PixelFormat alphaFormat = alphaImage->buffer->format; bool alphaPremultiplied = alphaImage->buffer->premultiplied; - ImageDataView alphaView = ImageDataView (alphaImage, &Rectangle (alphaPoint->x, alphaPoint->y, destView.width, destView.height)); + Rectangle alphaRect = Rectangle (alphaPoint->x, alphaPoint->y, destView.width, destView.height); + ImageDataView alphaView = ImageDataView (alphaImage, &alphaRect); int alphaPosition; RGBA alphaPixel; @@ -340,52 +343,27 @@ namespace lime { int length = int (rect->width * rect->height); pixels->Resize (length * 4); - if (format == RGBA32 && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { - - memcpy (pixels->Data (), image->buffer->data->Data (), image->buffer->data->Length ()); - return; - - } + uint8_t* data = (uint8_t*)image->buffer->data->Data (); + uint8_t* destData = (uint8_t*)pixels->Data (); - uint8_t* data = (uint8_t*)pixels->Data (); - uint8_t* srcData = (uint8_t*)image->buffer->data->Data (); + PixelFormat sourceFormat = image->buffer->format; + bool premultiplied = image->buffer->premultiplied; - int srcStride = image->buffer->Stride (); - int srcPosition = int ((rect->x * 4) + (srcStride * rect->y)); - int srcRowOffset = srcStride - int (4 * rect->width); - int srcRowEnd = int (4 * (rect->x + rect->width)); + ImageDataView dataView = ImageDataView (image, rect); + int position, destPosition = 0; + RGBA pixel; - if (format == ARGB32) { + for (int y = 0; y < dataView.height; y++) { - for (int i = 0; i < length; i++) { - - data[i * 4 + 1] = srcData[srcPosition++]; - data[i * 4 + 2] = srcData[srcPosition++]; - data[i * 4 + 3] = srcData[srcPosition++]; - data[i * 4] = srcData[srcPosition++]; - - if ((srcPosition % srcStride) > srcRowEnd) { - - srcPosition += srcRowOffset; - - } - - } + position = dataView.Row (y); - } else { - - for (int i = 0; i < length; i++) { + for (int x = 0; x < dataView.width; x++) { - data[i * 4] = srcData[srcPosition++]; - data[i * 4 + 1] = srcData[srcPosition++]; - data[i * 4 + 2] = srcData[srcPosition++]; - data[i * 4 + 3] = srcData[srcPosition++]; + pixel.ReadUInt8 (data, position, sourceFormat, premultiplied); + pixel.WriteUInt8 (destData, destPosition, format, false); - if ((srcPosition % srcStride) > srcRowEnd) { - - srcPosition += srcRowOffset; - - } + position += 4; + destPosition += 4; } From 905e384ca234550169175ce0848e086fdd6ae0a0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 11:09:35 -0700 Subject: [PATCH 56/76] Finish implementating C++ Image operations --- lime/graphics/utils/ImageDataUtil.hx | 24 ++-- project/include/graphics/Image.h | 1 - project/src/graphics/Image.cpp | 4 - project/src/graphics/utils/ImageDataUtil.cpp | 141 +++++++------------ project/src/math/ColorMatrix.cpp | 2 +- 5 files changed, 66 insertions(+), 106 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index d0b7d6562..b4c9e5f2c 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -354,9 +354,9 @@ class ImageDataUtil { 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 - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_flood_fill (image, x, y, color); else + #end { var format = image.buffer.format; @@ -643,9 +643,9 @@ class ImageDataUtil { byteArray.position = 0; #end - //#if ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_get_pixels (image, rect, format, byteArray); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_get_pixels (image, rect, format, byteArray); else + #end { var data = image.buffer.data; @@ -705,9 +705,9 @@ class ImageDataUtil { if (image.buffer.data == null || sourceImage.buffer.data == null) return; - //#if ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_merge (image, sourceImage, sourceRect, destPoint, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier); else + #end { var sourceView = new ImageDataView (sourceImage, sourceRect); @@ -1012,9 +1012,9 @@ class ImageDataUtil { if (image.buffer.data == null) return; - //#if ((cpp || neko) && !disable_cffi) - //if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format); else - //#end + #if ((cpp || neko) && !disable_cffi) + if (!System.disableCFFI) lime_image_data_util_set_pixels (image, rect, byteArray, format); else + #end { var data = image.buffer.data; 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/src/graphics/Image.cpp b/project/src/graphics/Image.cpp index 3ad8692db..d7d3f318f 100644 --- a/project/src/graphics/Image.cpp +++ b/project/src/graphics/Image.cpp @@ -8,7 +8,6 @@ namespace lime { static int id_height; static int id_offsetX; static int id_offsetY; - static int id_transparent; static int id_width; static bool init = false; @@ -19,7 +18,6 @@ namespace lime { height = 0; offsetX = 0; offsetY = 0; - transparent = true; width = 0; } @@ -33,7 +31,6 @@ namespace lime { id_height = val_id ("height"); id_offsetX = val_id ("offsetX"); id_offsetY = val_id ("offsetY"); - id_transparent = val_id ("transparent"); id_width = val_id ("width"); init = true; @@ -44,7 +41,6 @@ namespace lime { buffer = new ImageBuffer (val_field (image, id_buffer)); offsetX = val_int (val_field (image, id_offsetX)); offsetY = val_int (val_field (image, id_offsetY)); - transparent = val_bool (val_field (image, id_transparent)); } diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 811014d6e..206620797 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -374,31 +374,39 @@ namespace lime { void ImageDataUtil::Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier) { - int rowOffset = int (destPoint->y + image->offsetY - sourceRect->y - sourceImage->offsetY); - int columnOffset = int (destPoint->x + image->offsetX - sourceRect->x - sourceImage->offsetY); + ImageDataView sourceView = ImageDataView (sourceImage, sourceRect); + Rectangle destRect = Rectangle (destPoint->x, destPoint->y, sourceView.width, sourceView.height); + ImageDataView destView = ImageDataView (image, &destRect); uint8_t* sourceData = (uint8_t*)sourceImage->buffer->data->Data (); - int sourceStride = sourceImage->buffer->Stride (); - int sourceOffset = 0; + uint8_t* destData = (uint8_t*)image->buffer->data->Data (); + PixelFormat sourceFormat = sourceImage->buffer->format; + PixelFormat destFormat = image->buffer->format; + bool sourcePremultiplied = sourceImage->buffer->premultiplied; + bool destPremultiplied = image->buffer->premultiplied; - uint8_t* data = (uint8_t*)image->buffer->data->Data (); - int stride = image->buffer->Stride (); - int offset = 0; + int sourcePosition, destPosition; + RGBA sourcePixel, destPixel; - int rowEnd = int (sourceRect->y + sourceRect->height + sourceImage->offsetY); - int columnEnd = int (sourceRect->x + sourceRect->width + sourceImage->offsetX); - - for (int row = int (sourceRect->y + sourceImage->offsetY); row < rowEnd; row++) { + for (int y = 0; y < destView.height; y++) { - for (int column = int (sourceRect->x + sourceImage->offsetX); column < columnEnd; column++) { + sourcePosition = sourceView.Row (y); + destPosition = destView.Row (y); + + for (int x = 0; x < destView.width; x++) { - 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] = int (((sourceData[offset] * redMultiplier) + (data[offset] * (256 - redMultiplier))) / 256); - data[offset + 1] = int (((sourceData[offset + 1] * greenMultiplier) + (data[offset + 1] * (256 - greenMultiplier))) / 256); - data[offset + 2] = int (((sourceData[offset + 2] * blueMultiplier) + (data[offset + 2] * (256 - blueMultiplier))) / 256); - data[offset + 3] = int (((sourceData[offset + 3] * alphaMultiplier) + (data[offset + 3] * (256 - alphaMultiplier))) / 256); + destPixel.r = int (((sourcePixel.r * redMultiplier) + (destPixel.r * (256 - redMultiplier))) / 256); + destPixel.g = int (((sourcePixel.g * greenMultiplier) + (destPixel.g * (256 - greenMultiplier))) / 256); + destPixel.b = int (((sourcePixel.b * blueMultiplier) + (destPixel.b * (256 - blueMultiplier))) / 256); + destPixel.a = int (((sourcePixel.a * alphaMultiplier) + (destPixel.a * (256 - alphaMultiplier))) / 256); + + destPixel.WriteUInt8 (destData, destPosition, destFormat, destPremultiplied); + + sourcePosition += 4; + destPosition += 4; } @@ -409,17 +417,15 @@ namespace lime { void ImageDataUtil::MultiplyAlpha (Image* image) { - int a16 = 0; - int length = image->buffer->data->Length () / 4; + PixelFormat format = image->buffer->format; uint8_t* data = (uint8_t*)image->buffer->data->Data (); + int length = int (image->buffer->data->Length () / 4); + RGBA pixel; for (int i = 0; i < length; i++) { - a16 = __alpha16[data[3]]; - data[0] = (data[0] * a16) >> 16; - data[1] = (data[1] * a16) >> 16; - data[2] = (data[2] * a16) >> 16; - data += 4; + pixel.ReadUInt8 (data, i * 4, format, false); + pixel.WriteUInt8 (data, i * 4, format, true); } @@ -569,61 +575,29 @@ namespace lime { void ImageDataUtil::SetPixels (Image* image, Rectangle* rect, Bytes* bytes, PixelFormat format) { - if (format == RGBA32 && rect->width == image->buffer->width && rect->height == image->buffer->height && rect->x == 0 && rect->y == 0) { - - memcpy (image->buffer->data->Data (), bytes->Data (), bytes->Length ()); - return; - - } + uint8_t* data = (uint8_t*)image->buffer->data->Data (); + PixelFormat sourceFormat = image->buffer->format; + bool premultiplied = image->buffer->premultiplied; + ImageDataView dataView = ImageDataView (image, rect); + int row; + RGBA pixel; - int offset = int (image->buffer->width * (rect->y + image->offsetX) + (rect->x + image->offsetY)); - int boundR = int ((rect->x + rect->width + image->offsetX)); - int width = image->buffer->width; - int color; + uint8_t* byteArray = (uint8_t*)bytes->Data (); + int srcPosition = 0; - if (format == ARGB32) { + bool transparent = image->buffer->transparent; + + for (int y = 0; y < dataView.height; y++) { - int pos = offset * 4; - int len = int (rect->width * rect->height * 4); - uint8_t* data = (uint8_t*)image->buffer->data->Data (); - uint8_t* byteArray = (uint8_t*)bytes->Data (); + row = dataView.Row (y); - for (int i = 0; i < len; i += 4) { + for (int x = 0; x < dataView.width; x++) { + pixel.ReadUInt8 (byteArray, srcPosition, format, false); + if (!transparent) pixel.a = 0xFF; + pixel.WriteUInt8 (data, row + (x * 4), sourceFormat, premultiplied); - if (((pos) % (width * 4)) >= boundR * 4) { - - pos += (width - boundR) * 4; - - } - - data[pos] = byteArray[i + 1]; - data[pos + 1] = byteArray[i + 2]; - data[pos + 2] = byteArray[i + 3]; - data[pos + 3] = byteArray[i]; - pos += 4; - - } - - } else { - - int pos = offset; - int len = int (rect->width * rect->height); - int* data = (int*)image->buffer->data->Data (); - int* byteArray = (int*)bytes->Data (); - - // TODO: memcpy rows at once - - for (int i = 0; i < len; i++) { - - if (((pos) % (width)) >= boundR) { - - pos += (width - boundR); - - } - - data[pos] = byteArray[i]; - pos++; + srcPosition += 4; } @@ -634,24 +608,15 @@ namespace lime { void ImageDataUtil::UnmultiplyAlpha (Image* image) { - int length = image->buffer->data->Length () / 4; + PixelFormat format = image->buffer->format; uint8_t* data = (uint8_t*)image->buffer->data->Data (); - - int unmultiply; - uint8_t a; + int length = int (image->buffer->data->Length () / 4); + RGBA pixel; for (int i = 0; i < length; i++) { - a = data[3]; - - if (a != 0) { - - unmultiply = 255.0 / a; - data[0] = __clamp[data[0] * unmultiply]; - data[1] = __clamp[data[1] * unmultiply]; - data[2] = __clamp[data[2] * unmultiply]; - - } + pixel.ReadUInt8 (data, i * 4, format, true); + pixel.WriteUInt8 (data, i * 4, format, false); } diff --git a/project/src/math/ColorMatrix.cpp b/project/src/math/ColorMatrix.cpp index 40b4a8725..57f5a1531 100644 --- a/project/src/math/ColorMatrix.cpp +++ b/project/src/math/ColorMatrix.cpp @@ -112,7 +112,7 @@ namespace lime { for (int i = 0; i < 256; i++) { - value = floor (i * multiplier + offset); + value = (int)(i * multiplier + offset); if (value > 0xFF) value = 0xFF; if (value < 0) value = 0; table[i] = value; From 491d49443752f3d377710c07f2f1355eaeaace41 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 11:14:01 -0700 Subject: [PATCH 57/76] Transparent fix --- project/src/graphics/utils/ImageDataUtil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 206620797..49482ef2b 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -123,7 +123,7 @@ namespace lime { int sourcePosition, destPosition; RGBA sourcePixel; - if (!mergeAlpha || !sourceImage->transparent) { + if (!mergeAlpha || !sourceImage->buffer->transparent) { for (int y = 0; y < destView.height; y++) { @@ -279,7 +279,7 @@ namespace lime { RGBA hitColor; hitColor.ReadUInt8 (data, ((y + image->offsetY) * (image->buffer->width * 4)) + ((x + image->offsetX) * 4), format, premultiplied); - if (!image->transparent) { + if (!image->buffer->transparent) { fillColor.a = 0xFF; hitColor.a = 0xFF; From d3dfe4e4f96f1559eac0ac3ad6171474bacfd861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Lemi=C3=A8re?= Date: Tue, 21 Jul 2015 21:41:47 +0200 Subject: [PATCH 58/76] Guard againsts canvas copyPixel outside of target --- lime/graphics/utils/ImageCanvasUtil.hx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index 8214068a8..adc6f03b0 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -88,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 >= sourceRect.width || destPoint.y >= sourceRect.height) { + + return; + + } + if (alphaImage != null && alphaImage.transparent) { if (alphaPoint == null) alphaPoint = new Vector2 (); @@ -355,4 +361,4 @@ class ImageCanvasUtil { } -} \ No newline at end of file +} From 0fa9e6e1bf58c3f98e1188267f887ee4f2fdaeb2 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 13:24:13 -0700 Subject: [PATCH 59/76] Update to 2.5.1 --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index b51512542..24077ebd3 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.5.0", - "releasenote": "Improvements to gamepad and Cairo support, stability updates", + "version": "2.5.1", + "releasenote": "Improved Image format support, library prefix support", "contributors": [ "singmajesty" ] } From 16617d7383df824dfea899e87cc8bb10f216eb3f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 13:24:21 -0700 Subject: [PATCH 60/76] Update CHANGELOG --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43be4c17a..a6280310f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +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 + + 2.5.0 (07/17/2015) ------------------ From 3283085fafe04d4da4ad2da1aaa6bbcef9bf80e7 Mon Sep 17 00:00:00 2001 From: Nilsen Filc Date: Tue, 21 Jul 2015 22:51:16 +0200 Subject: [PATCH 61/76] fix build --- project/include/math/color/RGBA.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/include/math/color/RGBA.h b/project/include/math/color/RGBA.h index b52830f8d..259126806 100644 --- a/project/include/math/color/RGBA.h +++ b/project/include/math/color/RGBA.h @@ -19,7 +19,7 @@ namespace lime { for (int i = 0; i < 256; i++) { - __alpha16[i] = ceil ((i + 1) * ((1 << 16) / 0xFF)); + __alpha16[i] = ceil ((float)(i + 1) * ((1 << 16) / 0xFF)); } @@ -208,4 +208,4 @@ namespace lime { } -#endif \ No newline at end of file +#endif From 668671b5cdc69feda2310da5336843b492b6e806 Mon Sep 17 00:00:00 2001 From: Nilsen Filc Date: Tue, 21 Jul 2015 23:05:30 +0200 Subject: [PATCH 62/76] fix audio offset fixes https://github.com/openfl/openfl/issues/746 --- lime/audio/AudioSource.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lime/audio/AudioSource.hx b/lime/audio/AudioSource.hx index 539c093d3..86112861f 100644 --- a/lime/audio/AudioSource.hx +++ b/lime/audio/AudioSource.hx @@ -299,8 +299,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); } @@ -386,4 +386,4 @@ class AudioSource { } -} \ No newline at end of file +} From aa3c385d51cfb57f763213821058d65c4a20ea1a Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Tue, 21 Jul 2015 14:25:42 -0700 Subject: [PATCH 63/76] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6280310f..713a49b8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * 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) From 0eb183fe599dcb8993eadec0344953f528657105 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 08:33:49 -0700 Subject: [PATCH 64/76] Fix Int32 typed array get/set on Neko --- lime/utils/ArrayBufferView.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lime/utils/ArrayBufferView.hx b/lime/utils/ArrayBufferView.hx index 9797f8d44..a660ac001 100644 --- a/lime/utils/ArrayBufferView.hx +++ b/lime/utils/ArrayBufferView.hx @@ -519,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 ); @@ -544,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) + buffer.setInt32(byteOffset,value); #else if (littleEndian) { setInt8(buffer, byteOffset , value ); From fbead4357012f5b2eb341310fd163d7906c98d2c Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 08:45:36 -0700 Subject: [PATCH 65/76] Patch Neko Int32 set for now --- lime/utils/ArrayBufferView.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lime/utils/ArrayBufferView.hx b/lime/utils/ArrayBufferView.hx index a660ac001..e0e7fa737 100644 --- a/lime/utils/ArrayBufferView.hx +++ b/lime/utils/ArrayBufferView.hx @@ -544,7 +544,7 @@ private abstract TypedArrayType(Int) from Int to Int { #if cpp untyped __global__.__hxcpp_memory_set_i32(buffer.getData(), byteOffset, value); #else - #if (haxe_ver >= 3.2) + #if ((haxe_ver >= 3.2) && !neko) // causes error on some int values? buffer.setInt32(byteOffset,value); #else if (littleEndian) { From 816166c44d51583b4c079bd7a549d45836f85bb1 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 10:30:41 -0700 Subject: [PATCH 66/76] Cleanup --- lime/text/TextLayout.hx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lime/text/TextLayout.hx b/lime/text/TextLayout.hx index 6fad73690..41794dc33 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; From c637863cb7d96acdfaefdff39f8a6f656b9c591f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 18:36:22 -0700 Subject: [PATCH 67/76] Improve Flash target color conversion (Image API) --- lime/graphics/Image.hx | 169 +++++++++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 48 deletions(-) diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index f085edb9a..ea9cf78cb 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; @@ -388,8 +391,16 @@ class Image { case FLASH: rect.offset (offsetX, offsetY); - if (format == null || format == RGBA32) 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: @@ -418,8 +429,15 @@ class Image { case FLASH: - if (format == null || format == RGBA32) 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: @@ -536,15 +554,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 == RGBA32) { + 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; } @@ -577,15 +593,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 == RGBA32) { + 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; } @@ -621,20 +635,38 @@ class Image { rect.offset (offsetX, offsetY); var byteArray = buffer.__srcBitmapData.getPixels (rect.__toFlashRectangle ()); - if (format == null || format == RGBA32) { + 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; } @@ -771,8 +803,15 @@ class Image { case FLASH: - if (format == null || format == RGBA32) 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: @@ -801,8 +840,15 @@ class Image { case FLASH: - if (format == null || format == RGBA32) 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: @@ -833,27 +879,54 @@ class Image { case FLASH: rect.offset (offsetX, offsetY); - if (format == null || format == RGBA32) { + + 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: From 7f6418d0e2741dfb48e2c83300c01af728c84bd1 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 18:36:58 -0700 Subject: [PATCH 68/76] Cleanup --- project/include/math/color/ARGB.h | 40 ------------------------------- project/include/math/color/BGRA.h | 40 ------------------------------- 2 files changed, 80 deletions(-) delete mode 100644 project/include/math/color/ARGB.h delete mode 100644 project/include/math/color/BGRA.h diff --git a/project/include/math/color/ARGB.h b/project/include/math/color/ARGB.h deleted file mode 100644 index 8d3b80fc8..000000000 --- a/project/include/math/color/ARGB.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef LIME_MATH_COLOR_MATRIX_H -#define LIME_MATH_COLOR_MATRIX_H - - -#include -#include - - -namespace lime { - - - class ColorMatrix { - - - public: - - ColorMatrix (); - ColorMatrix (value colorMatrix); - ~ColorMatrix (); - - float GetAlphaMultiplier (); - float GetAlphaOffset (); - float GetBlueMultiplier (); - float GetBlueOffset (); - int GetColor (); - float GetGreenMultiplier (); - float GetGreenOffset (); - float GetRedMultiplier (); - float GetRedOffset (); - - float data[20]; - - - }; - - -} - - -#endif \ No newline at end of file diff --git a/project/include/math/color/BGRA.h b/project/include/math/color/BGRA.h deleted file mode 100644 index 8d3b80fc8..000000000 --- a/project/include/math/color/BGRA.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef LIME_MATH_COLOR_MATRIX_H -#define LIME_MATH_COLOR_MATRIX_H - - -#include -#include - - -namespace lime { - - - class ColorMatrix { - - - public: - - ColorMatrix (); - ColorMatrix (value colorMatrix); - ~ColorMatrix (); - - float GetAlphaMultiplier (); - float GetAlphaOffset (); - float GetBlueMultiplier (); - float GetBlueOffset (); - int GetColor (); - float GetGreenMultiplier (); - float GetGreenOffset (); - float GetRedMultiplier (); - float GetRedOffset (); - - float data[20]; - - - }; - - -} - - -#endif \ No newline at end of file From 7b5d1a3c7af53fa4cc3bf9113ae272789293d6b0 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 18:37:10 -0700 Subject: [PATCH 69/76] Fix Image native fillRect and floodFill --- lime/graphics/utils/ImageDataUtil.hx | 8 ++++---- project/include/graphics/utils/ImageDataUtil.h | 5 +++-- project/src/ExternalInterface.cpp | 14 ++++++++------ project/src/graphics/utils/ImageDataUtil.cpp | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index b4c9e5f2c..da114a52e 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -318,7 +318,7 @@ class ImageDataUtil { if (data == null) return; #if ((cpp || neko) && !disable_cffi) - if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, fillColor); else + if (!System.disableCFFI) lime_image_data_util_fill_rect (image, rect, (fillColor >> 16) & 0xFFFF, (fillColor) & 0xFFFF); else // TODO: Better Int32 solution #end { @@ -355,7 +355,7 @@ class ImageDataUtil { 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 { @@ -1094,8 +1094,8 @@ class ImageDataUtil { 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", -1); - 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_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); diff --git a/project/include/graphics/utils/ImageDataUtil.h b/project/include/graphics/utils/ImageDataUtil.h index 21d72a786..b411e7992 100644 --- a/project/include/graphics/utils/ImageDataUtil.h +++ b/project/include/graphics/utils/ImageDataUtil.h @@ -10,6 +10,7 @@ #include #include #include +#include namespace lime { @@ -23,8 +24,8 @@ namespace lime { static void ColorTransform (Image* image, Rectangle* rect, ColorMatrix* ColorMatrix); static void CopyChannel (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int srcChannel, int destChannel); static void CopyPixels (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, Image* alphaImage, Vector2* alphaPoint, bool mergeAlpha); - static void FillRect (Image* image, Rectangle* rect, int color); - static void FloodFill (Image* image, int x, int y, int color); + static void FillRect (Image* image, Rectangle* rect, int32_t color); + static void FloodFill (Image* image, int x, int y, int32_t color); static void GetPixels (Image* image, Rectangle* rect, PixelFormat format, Bytes* pixels); static void Merge (Image* image, Image* sourceImage, Rectangle* sourceRect, Vector2* destPoint, int redMultiplier, int greenMultiplier, int blueMultiplier, int alphaMultiplier); static void MultiplyAlpha (Image* image); diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index d4dded491..007a7f5b5 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -559,20 +559,22 @@ namespace lime { } - value lime_image_data_util_fill_rect (value image, value rect, value color) { + value lime_image_data_util_fill_rect (value image, value rect, value rg, value ba) { Image _image = Image (image); Rectangle _rect = Rectangle (rect); - ImageDataUtil::FillRect (&_image, &_rect, val_number (color)); + int32_t color = (val_int (rg) << 16) | val_int (ba); + ImageDataUtil::FillRect (&_image, &_rect, color); return alloc_null (); } - value lime_image_data_util_flood_fill (value image, value x, value y, value color) { + value lime_image_data_util_flood_fill (value image, value x, value y, value rg, value ba) { Image _image = Image (image); - ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), val_number (color)); + int32_t color = (val_int (rg) << 16) | val_int (ba); + ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), color); return alloc_null (); } @@ -1169,8 +1171,8 @@ namespace lime { DEFINE_PRIM (lime_image_data_util_color_transform, 3); DEFINE_PRIM_MULT (lime_image_data_util_copy_channel); DEFINE_PRIM_MULT (lime_image_data_util_copy_pixels); - DEFINE_PRIM (lime_image_data_util_fill_rect, 3); - DEFINE_PRIM (lime_image_data_util_flood_fill, 4); + DEFINE_PRIM (lime_image_data_util_fill_rect, 4); + DEFINE_PRIM (lime_image_data_util_flood_fill, 5); DEFINE_PRIM (lime_image_data_util_get_pixels, 4); DEFINE_PRIM_MULT (lime_image_data_util_merge); DEFINE_PRIM (lime_image_data_util_multiply_alpha, 1); diff --git a/project/src/graphics/utils/ImageDataUtil.cpp b/project/src/graphics/utils/ImageDataUtil.cpp index 49482ef2b..7ea828f85 100644 --- a/project/src/graphics/utils/ImageDataUtil.cpp +++ b/project/src/graphics/utils/ImageDataUtil.cpp @@ -243,7 +243,7 @@ namespace lime { } - void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int color) { + void ImageDataUtil::FillRect (Image* image, Rectangle* rect, int32_t color) { uint8_t* data = (uint8_t*)image->buffer->data->Data (); PixelFormat format = image->buffer->format; @@ -268,7 +268,7 @@ namespace lime { } - void ImageDataUtil::FloodFill (Image* image, int x, int y, int color) { + void ImageDataUtil::FloodFill (Image* image, int x, int y, int32_t color) { uint8_t* data = (uint8_t*)image->buffer->data->Data (); PixelFormat format = image->buffer->format; From 4378412a5475ae85db648765275755b087bbcc84 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Wed, 22 Jul 2015 19:23:54 -0700 Subject: [PATCH 70/76] Update ImageCanvasUtil.hx --- lime/graphics/utils/ImageCanvasUtil.hx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lime/graphics/utils/ImageCanvasUtil.hx b/lime/graphics/utils/ImageCanvasUtil.hx index adc6f03b0..73e1f46df 100644 --- a/lime/graphics/utils/ImageCanvasUtil.hx +++ b/lime/graphics/utils/ImageCanvasUtil.hx @@ -88,12 +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 >= sourceRect.width || destPoint.y >= sourceRect.height) { - + if (destPoint.x >= image.width || destPoint.y >= image.height) { + return; - + } - + if (alphaImage != null && alphaImage.transparent) { if (alphaPoint == null) alphaPoint = new Vector2 (); From abc83da97b966ae1721688576d78d08e854cae7f Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 08:09:18 -0700 Subject: [PATCH 71/76] Improve getPixel/setPixel behavior --- lime/graphics/utils/ImageDataUtil.hx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lime/graphics/utils/ImageDataUtil.hx b/lime/graphics/utils/ImageDataUtil.hx index da114a52e..1d2de9616 100644 --- a/lime/graphics/utils/ImageDataUtil.hx +++ b/lime/graphics/utils/ImageDataUtil.hx @@ -605,7 +605,8 @@ class ImageDataUtil { switch (format) { - case ARGB32: return pixel >> 8 & 0xFFFFFF; + case ARGB32: return (pixel:ARGB); + case BGRA32: return (pixel:BGRA); default: return pixel; } @@ -976,11 +977,17 @@ class ImageDataUtil { public static function setPixel (image:Image, x:Int, y:Int, color:Int, format:PixelFormat):Void { - if (format == RGBA32) color = color >> 8; + var pixel:RGBA; + + switch (format) { + + case ARGB32: pixel = (color:ARGB); + case BGRA32: pixel = (color:BGRA); + default: pixel = color; + + } - var pixel:RGBA = 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; From 861c0fe63b4fc311551ecc0fd75f972f2ca2803d Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 08:09:30 -0700 Subject: [PATCH 72/76] Fallback to software if hardware is not available --- lime/_backend/native/NativeRenderer.hx | 28 +++++++++++++-------- project/include/graphics/Renderer.h | 1 + project/src/ExternalInterface.cpp | 9 +++++++ project/src/backend/sdl/SDLRenderer.cpp | 33 +++++++++++++++++++++++++ project/src/backend/sdl/SDLRenderer.h | 1 + 5 files changed, 62 insertions(+), 10 deletions(-) diff --git a/lime/_backend/native/NativeRenderer.hx b/lime/_backend/native/NativeRenderer.hx index 1447db885..6e17307be 100644 --- a/lime/_backend/native/NativeRenderer.hx +++ b/lime/_backend/native/NativeRenderer.hx @@ -40,23 +40,30 @@ 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": + + parent.context = OPENGL (new GLRenderContext ()); - } else { - - #if lime_cairo - render (); - parent.context = CAIRO (cairo); - #end + default: + + #if lime_cairo + render (); + parent.context = CAIRO (cairo); + #end } + #end } @@ -137,6 +144,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/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/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 007a7f5b5..64dbb50a9 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -868,6 +868,14 @@ namespace lime { } + value lime_renderer_get_type (value renderer) { + + Renderer* targetRenderer = (Renderer*)(intptr_t)val_float (renderer); + return alloc_string (targetRenderer->Type ()); + + } + + value lime_renderer_lock (value renderer) { return ((Renderer*)(intptr_t)val_float (renderer))->Lock (); @@ -1199,6 +1207,7 @@ namespace lime { DEFINE_PRIM (lime_png_decode_file, 2); DEFINE_PRIM (lime_renderer_create, 1); DEFINE_PRIM (lime_renderer_flip, 1); + DEFINE_PRIM (lime_renderer_get_type, 1); DEFINE_PRIM (lime_renderer_lock, 1); DEFINE_PRIM (lime_renderer_unlock, 1); DEFINE_PRIM (lime_render_event_manager_register, 2); diff --git a/project/src/backend/sdl/SDLRenderer.cpp b/project/src/backend/sdl/SDLRenderer.cpp index 659f13f87..b70085b5a 100644 --- a/project/src/backend/sdl/SDLRenderer.cpp +++ b/project/src/backend/sdl/SDLRenderer.cpp @@ -31,6 +31,15 @@ namespace lime { sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags); + if (!sdlRenderer && (sdlFlags & SDL_RENDERER_ACCELERATED)) { + + sdlFlags &= ~SDL_RENDERER_ACCELERATED; + sdlFlags |= SDL_RENDERER_SOFTWARE; + + sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags); + + } + if (!sdlRenderer) { printf ("Could not create SDL renderer: %s.\n", SDL_GetError ()); @@ -95,6 +104,30 @@ namespace lime { } + const char* SDLRenderer::Type () { + + if (sdlRenderer) { + + SDL_RendererInfo info; + SDL_GetRendererInfo (sdlRenderer, &info); + + if (info.flags & SDL_RENDERER_SOFTWARE) { + + return "software"; + + } else { + + return "opengl"; + + } + + } + + return "none"; + + } + + void SDLRenderer::Unlock () { if (sdlTexture) { diff --git a/project/src/backend/sdl/SDLRenderer.h b/project/src/backend/sdl/SDLRenderer.h index cc45e818d..f2c1d6c02 100644 --- a/project/src/backend/sdl/SDLRenderer.h +++ b/project/src/backend/sdl/SDLRenderer.h @@ -18,6 +18,7 @@ namespace lime { virtual void Flip (); virtual value Lock (); + virtual const char* Type (); virtual void Unlock (); SDL_Renderer* sdlRenderer; From f992251fd048b258602a2ce7245d3bcb27c976d5 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 09:03:58 -0700 Subject: [PATCH 73/76] Better render context lost/restored code --- lime/_backend/native/NativeApplication.hx | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index 69ef70bd5..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) @@ -236,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); } From 29724dc0fab07b20c1de6bab9bb6c172ed13f9f4 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 09:06:27 -0700 Subject: [PATCH 74/76] useHardware fix --- lime/_backend/native/NativeRenderer.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lime/_backend/native/NativeRenderer.hx b/lime/_backend/native/NativeRenderer.hx index 6e17307be..91b9234a3 100644 --- a/lime/_backend/native/NativeRenderer.hx +++ b/lime/_backend/native/NativeRenderer.hx @@ -53,10 +53,13 @@ class NativeRenderer { case "opengl": + useHardware = true; parent.context = OPENGL (new GLRenderContext ()); default: + useHardware = false; + #if lime_cairo render (); parent.context = CAIRO (cairo); From f7656f95920aebbb2422cc71dacb3c1e5c4211f3 Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 18:30:40 -0700 Subject: [PATCH 75/76] Update to 2.5.2 --- haxelib.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haxelib.json b/haxelib.json index 24077ebd3..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.5.1", - "releasenote": "Improved Image format support, library prefix support", + "version": "2.5.2", + "releasenote": "Software fallback support, image fixes", "contributors": [ "singmajesty" ] } From 1e8298260c0fb6c602bc4fb2d7552fbffb101cea Mon Sep 17 00:00:00 2001 From: Joshua Granick Date: Thu, 23 Jul 2015 18:30:53 -0700 Subject: [PATCH 76/76] Update CHANGELOG --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 713a49b8b..f4a3dd544 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +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) ------------------