diff --git a/lime/_backend/flash/FlashRenderer.hx b/lime/_backend/flash/FlashRenderer.hx index 2c390c1f0..2c37c381a 100644 --- a/lime/_backend/flash/FlashRenderer.hx +++ b/lime/_backend/flash/FlashRenderer.hx @@ -1,8 +1,12 @@ package lime._backend.flash; +import flash.display.BitmapData; +import flash.geom.Matrix; import flash.Lib; +import lime.graphics.Image; import lime.graphics.Renderer; +import lime.math.Rectangle; class FlashRenderer { @@ -33,6 +37,39 @@ class FlashRenderer { } + public function readPixels (rect:Rectangle):Image { + + if (rect == null) { + + rect = new Rectangle (0, 0, parent.window.stage.stageWidth, parent.window.stage.stageHeight); + + } else { + + rect.__contract (0, 0, parent.window.stage.stageWidth, parent.window.stage.stageHeight); + + } + + if (rect.width > 0 && rect.height > 0) { + + var bitmapData = new BitmapData (Std.int (rect.width), Std.int (rect.height)); + + var matrix = new Matrix (); + matrix.tx = -rect.x; + matrix.ty = -rect.y; + + bitmapData.draw (parent.window.stage, matrix); + + return Image.fromBitmapData (bitmapData); + + } else { + + return null; + + } + + } + + public function render ():Void { diff --git a/lime/_backend/flash/FlashWindow.hx b/lime/_backend/flash/FlashWindow.hx index 54c5fb567..4593376ed 100644 --- a/lime/_backend/flash/FlashWindow.hx +++ b/lime/_backend/flash/FlashWindow.hx @@ -48,6 +48,7 @@ class FlashWindow { Lib.current.stage.scaleMode = StageScaleMode.NO_SCALE; parent.id = 0; + parent.stage = Lib.current.stage; } diff --git a/lime/_backend/html5/HTML5Renderer.hx b/lime/_backend/html5/HTML5Renderer.hx index e25b1fe3c..1eb22a2fc 100644 --- a/lime/_backend/html5/HTML5Renderer.hx +++ b/lime/_backend/html5/HTML5Renderer.hx @@ -3,10 +3,14 @@ package lime._backend.html5; import haxe.macro.Compiler; import js.html.webgl.RenderingContext; +import js.html.CanvasElement; +import js.Browser; import lime.app.Application; +import lime.graphics.Image; import lime.graphics.opengl.GL; import lime.graphics.GLRenderContext; import lime.graphics.Renderer; +import lime.math.Rectangle; @:access(lime.app.Application) @:access(lime.graphics.opengl.GL) @@ -130,6 +134,42 @@ class HTML5Renderer { } + public function readPixels (rect:Rectangle):Image { + + // TODO: Handle DIV, improve 3D canvas support + + if (parent.window.backend.canvas != null) { + + if (rect == null) { + + rect = new Rectangle (0, 0, parent.window.backend.canvas.width, parent.window.backend.canvas.height); + + } else { + + rect.__contract (0, 0, parent.window.backend.canvas.width, parent.window.backend.canvas.height); + + } + + if (rect.width > 0 && rect.height > 0) { + + var canvas:CanvasElement = cast Browser.document.createElement ("canvas"); + canvas.width = Std.int (rect.width); + canvas.height = Std.int (rect.height); + + var context = canvas.getContext ("2d"); + context.drawImage (parent.window.backend.canvas, -rect.x, -rect.y); + + return Image.fromCanvas (canvas); + + } + + } + + return null; + + } + + public function render ():Void { diff --git a/lime/_backend/native/NativeRenderer.hx b/lime/_backend/native/NativeRenderer.hx index acd22c45c..d14a4eba3 100644 --- a/lime/_backend/native/NativeRenderer.hx +++ b/lime/_backend/native/NativeRenderer.hx @@ -1,6 +1,7 @@ package lime._backend.native; +import haxe.io.Bytes; import lime.graphics.cairo.Cairo; import lime.graphics.cairo.CairoFormat; import lime.graphics.cairo.CairoImageSurface; @@ -8,7 +9,11 @@ import lime.graphics.cairo.CairoSurface; import lime.graphics.CairoRenderContext; import lime.graphics.ConsoleRenderContext; import lime.graphics.GLRenderContext; +import lime.graphics.Image; +import lime.graphics.ImageBuffer; import lime.graphics.Renderer; +import lime.math.Rectangle; +import lime.utils.UInt8Array; #if !macro @:build(lime.system.CFFI.build()) @@ -112,6 +117,24 @@ class NativeRenderer { } + public function readPixels (rect:Rectangle):Image { + + var data:Dynamic = lime_renderer_read_pixels (handle, rect); + + if (data != null) { + + var buffer = new ImageBuffer (new UInt8Array (@:privateAccess new Bytes (data.data.length, data.data.b)), data.width, data.height, data.bitsPerPixel); + buffer.format = RGBA32; + + return new Image (buffer); + + } + + return null; + + } + + public function render ():Void { #if !macro @@ -164,6 +187,7 @@ class NativeRenderer { @:cffi private static function lime_renderer_get_type (handle:Dynamic):Dynamic; @:cffi private static function lime_renderer_lock (handle:Dynamic):Dynamic; @:cffi private static function lime_renderer_make_current (handle:Dynamic):Void; + @:cffi private static function lime_renderer_read_pixels (handle:Dynamic, rect:Dynamic):Dynamic; @:cffi private static function lime_renderer_unlock (handle:Dynamic):Void; #end diff --git a/lime/graphics/Image.hx b/lime/graphics/Image.hx index 0a30b668d..12f3080e2 100644 --- a/lime/graphics/Image.hx +++ b/lime/graphics/Image.hx @@ -459,7 +459,11 @@ class Image { } - public static function fromBitmapData (bitmapData:#if flash BitmapData #else Dynamic #end):Image { + #if flash + public static function fromBitmapData (bitmapData:BitmapData):Image { + #else + public static function fromBitmapData (bitmapData:Dynamic):Image { + #end if (bitmapData == null) return null; #if flash @@ -483,7 +487,11 @@ class Image { } - public static function fromCanvas (canvas:#if (js && html5) CanvasElement #else Dynamic #end):Image { + #if (js && html5) + public static function fromCanvas (canvas:CanvasElement):Image { + #else + public static function fromCanvas (canvas:Dynamic):Image { + #end if (canvas == null) return null; var buffer = new ImageBuffer (null, canvas.width, canvas.height); @@ -502,7 +510,11 @@ class Image { } - public static function fromImageElement (image:#if (js && html5) ImageElement #else Dynamic #end):Image { + #if (js && html5) + public static function fromImageElement (image:ImageElement):Image { + #else + public static function fromImageElement (image:Dynamic):Image { + #end if (image == null) return null; var buffer = new ImageBuffer (null, image.width, image.height); @@ -1563,7 +1575,6 @@ class Image { #if ((cpp || neko || nodejs) && !macro) - @:cffi private static function lime_image_encode (buffer:Dynamic, Type:Int, quality:Int):Dynamic; @:cffi private static function lime_image_load (data:Dynamic):Dynamic; #end diff --git a/lime/graphics/Renderer.hx b/lime/graphics/Renderer.hx index 0efbbdb27..6dab8cbc0 100644 --- a/lime/graphics/Renderer.hx +++ b/lime/graphics/Renderer.hx @@ -2,6 +2,7 @@ package lime.graphics; import lime.app.Event; +import lime.math.Rectangle; import lime.ui.Window; @@ -43,6 +44,13 @@ class Renderer { } + public function readPixels (rect:Rectangle = null):Image { + + return backend.readPixels (rect); + + } + + private function render ():Void { backend.render (); diff --git a/lime/tools/helpers/AssetHelper.hx b/lime/tools/helpers/AssetHelper.hx index 1d3300dfb..4b62d1f71 100644 --- a/lime/tools/helpers/AssetHelper.hx +++ b/lime/tools/helpers/AssetHelper.hx @@ -10,6 +10,7 @@ import lime.project.HXProject; import sys.io.File; import sys.FileSystem; + class AssetHelper { @@ -24,7 +25,7 @@ class AssetHelper { var data = { id : asset.id, path : asset.resourceName, - type : Std.string(asset.type) + type : Std.string (asset.type) } manifest.push (data); diff --git a/lime/ui/Window.hx b/lime/ui/Window.hx index fa1527021..e8832aab4 100644 --- a/lime/ui/Window.hx +++ b/lime/ui/Window.hx @@ -10,6 +10,8 @@ import lime.system.Display; #if openfl import openfl.display.Stage; +#elseif flash +import flash.display.Stage; #else typedef Stage = Dynamic; #end diff --git a/project/include/graphics/Renderer.h b/project/include/graphics/Renderer.h index daaeb4895..9c51e2de9 100644 --- a/project/include/graphics/Renderer.h +++ b/project/include/graphics/Renderer.h @@ -2,6 +2,8 @@ #define LIME_GRAPHICS_RENDERER_H +#include +#include #include #include @@ -19,6 +21,7 @@ namespace lime { virtual double GetScale () = 0; virtual value Lock () = 0; virtual void MakeCurrent () = 0; + virtual void ReadPixels (ImageBuffer *buffer, Rectangle *rect) = 0; virtual const char* Type () = 0; virtual void Unlock () = 0; diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 3e4bec674..4d47d12ef 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -1088,6 +1088,27 @@ namespace lime { } + value lime_renderer_read_pixels (value renderer, value rect) { + + Renderer* targetRenderer = (Renderer*)val_data (renderer); + ImageBuffer buffer; + + if (!val_is_null (rect)) { + + Rectangle _rect = Rectangle (rect); + targetRenderer->ReadPixels (&buffer, &_rect); + + } else { + + targetRenderer->ReadPixels (&buffer, NULL); + + } + + return buffer.Value (); + + } + + void lime_renderer_unlock (value renderer) { ((Renderer*)val_data (renderer))->Unlock (); @@ -1453,6 +1474,7 @@ namespace lime { DEFINE_PRIME1 (lime_renderer_get_type); DEFINE_PRIME1 (lime_renderer_lock); DEFINE_PRIME1v (lime_renderer_make_current); + DEFINE_PRIME2 (lime_renderer_read_pixels); DEFINE_PRIME1v (lime_renderer_unlock); DEFINE_PRIME2v (lime_render_event_manager_register); DEFINE_PRIME2v (lime_sensor_event_manager_register); diff --git a/project/src/backend/sdl/SDLRenderer.cpp b/project/src/backend/sdl/SDLRenderer.cpp index d64f03723..92c3ef7e0 100644 --- a/project/src/backend/sdl/SDLRenderer.cpp +++ b/project/src/backend/sdl/SDLRenderer.cpp @@ -194,6 +194,34 @@ namespace lime { } + void SDLRenderer::ReadPixels (ImageBuffer *buffer, Rectangle *rect) { + + if (sdlRenderer) { + + SDL_Rect bounds = { 0, 0, 0, 0 }; + + if (rect) { + + bounds.x = rect->x; + bounds.y = rect->y; + bounds.w = rect->width; + bounds.h = rect->height; + + } else { + + SDL_GetWindowSize (sdlWindow, &bounds.w, &bounds.h); + + } + + buffer->Resize (bounds.w, bounds.h, 32); + + SDL_RenderReadPixels (sdlRenderer, &bounds, SDL_PIXELFORMAT_ABGR8888, buffer->data->Data (), buffer->Stride ()); + + } + + } + + const char* SDLRenderer::Type () { if (sdlRenderer) { diff --git a/project/src/backend/sdl/SDLRenderer.h b/project/src/backend/sdl/SDLRenderer.h index 6b35ae222..735bdc916 100644 --- a/project/src/backend/sdl/SDLRenderer.h +++ b/project/src/backend/sdl/SDLRenderer.h @@ -21,6 +21,7 @@ namespace lime { virtual double GetScale (); virtual value Lock (); virtual void MakeCurrent (); + virtual void ReadPixels (ImageBuffer *buffer, Rectangle *rect); virtual const char* Type (); virtual void Unlock ();