From 84832e6f8622cd1e873bbfaed74b667d476d4c13 Mon Sep 17 00:00:00 2001
From: "Adam D. Ruppe" <destructionator@gmail.com>
Date: Sun, 9 Jun 2013 09:19:36 -0400
Subject: [PATCH] experimental direct image access

---
 simpledisplay.d | 49 +++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/simpledisplay.d b/simpledisplay.d
index 9b73cfe..c7e6b02 100644
--- a/simpledisplay.d
+++ b/simpledisplay.d
@@ -112,7 +112,7 @@ struct Pen {
 }
 
 
-class Image {
+final class Image {
 	this(int width, int height) {
 		this.width = width;
 		this.height = height;
@@ -128,7 +128,7 @@ class Image {
 		impl.dispose();
 	}
 
-	void putPixel(int x, int y, Color c) {
+	final void putPixel(int x, int y, Color c) {
 		if(x < 0 || x >= width)
 			return;
 		if(y < 0 || y >= height)
@@ -137,7 +137,7 @@ class Image {
 		impl.setPixel(x, y, c);
 	}
 
-	void opIndexAssign(Color c, int x, int y) {
+	final void opIndexAssign(Color c, int x, int y) {
 		putPixel(x, y, c);
 	}
 
@@ -150,6 +150,39 @@ class Image {
 		return where;
 	}
 
+	// FIXME: make properly cross platform by getting rgba right
+
+	/// warning: this is not portable across platforms because the data format can change
+	ubyte* getDataPointer() {
+		return impl.rawData;
+	}
+
+	/// for use with getDataPointer
+	final int bytesPerLine() const pure @safe nothrow {
+		version(Windows)
+			return ((cast(int) width * 3 + 3) / 4) * 4;
+		else version(X11)
+			return 4 * width;
+		else version(OSXCocoa)
+			return 4 * width;
+		else version(html5)
+			return 4 * width;
+		else static assert(0);
+	}
+
+	/// for use with getDataPointer
+	final int bytesPerPixel() const pure @safe nothrow {
+		version(Windows)
+			return 3;
+		else version(X11)
+			return 4;
+		else version(OSXCocoa)
+			return 4;
+		else version(html5)
+			return 4;
+		else static assert(0);
+	}
+
 	immutable int width;
 	immutable int height;
     private:
@@ -320,7 +353,7 @@ class Sprite {
 			infoheader.bmiHeader.biBitCount = 24;
 			infoheader.bmiHeader.biCompression = BI_RGB;
 
-			byte* rawData;
+			ubyte* rawData;
 
 			// FIXME: this should prolly be a device dependent bitmap...
 			handle = enforce(CreateDIBSection(
@@ -937,7 +970,7 @@ version(Windows) {
 
 	mixin template NativeImageImplementation() {
 		HBITMAP handle;
-		byte* rawData;
+		ubyte* rawData;
 
 		void setPixel(int x, int y, Color c) {
 			auto itemsPerLine = ((cast(int) width * 3 + 3) / 4) * 4;
@@ -1198,14 +1231,14 @@ version(X11) {
 
 	mixin template NativeImageImplementation() {
 		XImage* handle;
-		byte* rawData;
+		ubyte* rawData;
 
 		void createImage(int width, int height) {
 			auto display = XDisplayConnection.get();
 			auto screen = DefaultScreen(display);
 
 			// This actually needs to be malloc to avoid a double free error when XDestroyImage is called
-			rawData = cast(byte*) malloc(width * height * 4);
+			rawData = cast(ubyte*) malloc(width * height * 4);
 
 			handle = XCreateImage(
 				display,
@@ -1807,7 +1840,7 @@ XImage *XCreateImage(
     uint	/* depth */,
     int			/* format */,
     int			/* offset */,
-    byte*		/* data */,
+    ubyte*		/* data */,
     uint	/* width */,
     uint	/* height */,
     int			/* bitmap_pad */,