From e7b72c7c1aae600123ee340eacf8ea3c81948a4c Mon Sep 17 00:00:00 2001
From: "Adam D. Ruppe" <destructionator@gmail.com>
Date: Fri, 24 Sep 2021 08:52:16 -0400
Subject: [PATCH] arc windows fix

---
 simpledisplay.d | 80 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 66 insertions(+), 14 deletions(-)

diff --git a/simpledisplay.d b/simpledisplay.d
index 6d4b479..90cd8ce 100644
--- a/simpledisplay.d
+++ b/simpledisplay.d
@@ -1504,11 +1504,42 @@ float[2] getDpi() {
 	return dpi;
 }
 
-TrueColorImage trueColorImageFromNativeHandle(NativeWindowHandle handle, int width, int height) {
+/++
+	Implementation used by [SimpleWindow.takeScreenshot].
+
+	Params:
+		handle = the native window handle. If `NativeWindowHandle.init`, it will attempt to get the whole screen.
+		width = the width of the image you wish to capture. If 0, it will attempt to capture the full width of the target.
+		height = the height of the image you wish to capture. If 0, it will attempt to capture the full height of the target.
+		x = the x-offset of the image to capture, from the left.
+		y = the y-offset of the image to capture, from the top.
+
+	History:
+		Added on March 14, 2021
+
+		Documented public on September 23, 2021 with full support for null params (dub 10.3)
+		
++/
+TrueColorImage trueColorImageFromNativeHandle(NativeWindowHandle handle, int width = 0, int height = 0, int x = 0, int y = 0) {
 	TrueColorImage got;
 	version(X11) {
 		auto display = XDisplayConnection.get;
-		auto image = XGetImage(display, handle, 0, 0, width, height, (cast(c_ulong) ~0) /*AllPlanes*/, ImageFormat.ZPixmap);
+		if(handle == 0)
+			handle = RootWindow(display, DefaultScreen(display));
+
+		if(width == 0 || height == 0) {
+			Window root;
+			int xpos, ypos;
+			uint widthret, heightret, borderret, depthret;
+			XGetGeometry(display, handle, &root, &xpos, &ypos, &widthret, &heightret, &borderret, &depthret);
+
+			if(width == 0)
+				width = widthret;
+			if(height == 0)
+				height = heightret;
+		}
+
+		auto image = XGetImage(display, handle, x, y, width, height, (cast(c_ulong) ~0) /*AllPlanes*/, ImageFormat.ZPixmap);
 
 		// https://github.com/adamdruppe/arsd/issues/98
 
@@ -1517,14 +1548,23 @@ TrueColorImage trueColorImageFromNativeHandle(NativeWindowHandle handle, int wid
 
 		XDestroyImage(image);
 	} else version(Windows) {
-		// I just need to BitBlt that shit... BUT WAIT IT IS ALREADY IN A DIB!!!!!!!
-
 		auto hdc = GetDC(handle);
 		scope(exit) ReleaseDC(handle, hdc);
+
+		if(width == 0 || height == 0) {
+			BITMAP bmHeader;
+			auto bm  = GetCurrentObject(hdc, OBJ_BITMAP);
+			GetObject(bm, BITMAP.sizeof, &bmHeader);
+			if(width == 0)
+				width = bmHeader.bmWidth;
+			if(height == 0)
+				height = bmHeader.bmHeight;
+		}
+
 		auto i = new Image(width, height);
 		HDC hdcMem = CreateCompatibleDC(hdc);
 		HBITMAP hbmOld = SelectObject(hdcMem, i.handle);
-		BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
+		BitBlt(hdcMem, x, y, width, height, hdc, 0, 0, SRCCOPY);
 		SelectObject(hdcMem, hbmOld);
 		DeleteDC(hdcMem);
 
@@ -2469,6 +2509,7 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
 	/// Draws an image on the window. This is meant to provide quick look
 	/// of a static image generated elsewhere.
 	@property void image(Image i) {
+	/+
 		version(Windows) {
 			BITMAP bm;
 			HDC hdc = GetDC(hwnd);
@@ -2502,6 +2543,9 @@ class SimpleWindow : CapableOfHandlingNativeEvent, CapableOfBeingDrawnUpon {
 			draw().drawImage(Point(0, 0), i);
 			setNeedsDisplay(view, true);
 		} else static assert(0);
+	+/
+		auto painter = this.draw;
+		painter.drawImage(Point(0, 0), i);
 	}
 
 	/++
@@ -10158,14 +10202,20 @@ version(Windows) {
 				drawEllipse(x1, y1, x1 + width, y1 + height);
 			else {
 				import core.stdc.math;
-				float startAngle = start * 64 * 180 / 3.14159265;
-				float endAngle = finish * 64 * 180 / 3.14159265;
-				Arc(hdc, x1, y1, x1 + width, y1 + height,
-					cast(int)(cos(startAngle) * width / 2 + x1),
-					cast(int)(sin(startAngle) * height / 2 + y1),
-					cast(int)(cos(endAngle) * width / 2 + x1),
-					cast(int)(sin(endAngle) * height / 2 + y1),
-				);
+				float startAngle = cast(float) start / 64.0 / 180.0 * 3.14159265358979323;
+				float endAngle = cast(float) finish / 64.0 / 180.0 * 3.14159265358979323;
+
+				auto c1 = cast(int)(cos(startAngle) * width / 2 + x1 + width / 2);
+				auto c2 = cast(int)(-sin(startAngle) * height / 2 + y1 + height / 2);
+				auto c3 = cast(int)(cos(endAngle) * width / 2 + x1 + width / 2);
+				auto c4 = cast(int)(-sin(endAngle) * height / 2 + y1 + height / 2);
+				import std.stdio; writeln(c1, " ", c2, " ", c3, " ", c4);
+
+
+				if(_activePen.color.a)
+					Arc(hdc, x1, y1, x1 + width + 1, y1 + height + 1, c1, c2, c3, c4);
+				if(_fillColor.a)
+					Pie(hdc, x1, y1, x1 + width + 1, y1 + height + 1, c1, c2, c3, c4);
 			}
 		}
 
@@ -11536,8 +11586,10 @@ version(X11) {
 				XFillArc(display, d, gc, x1, y1, width, height, start, finish);
 				swapColors();
 			}
-			if(foregroundIsNotTransparent)
+			if(foregroundIsNotTransparent) {
 				XDrawArc(display, d, gc, x1, y1, width, height, start, finish);
+				// Windows draws the straight lines on the edges too so FIXME sort of
+			}
 		}
 
 		void drawPolygon(Point[] vertexes) {