Maelstrom: Added the concept of logical scale separate from logical size - useful for retina displays

https://github.com/libsdl-org/Maelstrom/commit/4f6aa2e7fcb9f75905d750c690fdfc71f0520442

From 4f6aa2e7fcb9f75905d750c690fdfc71f0520442 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 12 Oct 2012 00:52:56 -0700
Subject: [PATCH] Added the concept of logical scale separate from logical size
 - useful for retina displays

---
 screenlib/SDL_FrameBuf.cpp | 50 +++++++++++++++++++++++++++++++++++---
 screenlib/SDL_FrameBuf.h   | 15 +++++++-----
 2 files changed, 55 insertions(+), 10 deletions(-)

diff --git a/screenlib/SDL_FrameBuf.cpp b/screenlib/SDL_FrameBuf.cpp
index af2c28e4..5a5d6ee8 100644
--- a/screenlib/SDL_FrameBuf.cpp
+++ b/screenlib/SDL_FrameBuf.cpp
@@ -39,6 +39,7 @@ FrameBuf:: FrameBuf() : ErrorBase()
 	renderer = NULL;
 	faded = 0;
 	resizable = false;
+	logicalScale = 0.0f;
 }
 
 int
@@ -109,7 +110,13 @@ FrameBuf::ProcessEvent(SDL_Event *event)
 				SDL_GetWindowSize(window, &w, &h);
 				SDL_RenderSetViewport(renderer, NULL);
 			}
-			UpdateWindowSize(w, h);
+			if (logicalScale > 0.0f) {
+				w = (int)(w/logicalScale);
+				h = (int)(h/logicalScale);
+				SetLogicalSize(w, h);
+			} else {
+				UpdateWindowSize(w, h);
+			}
 		}
 		break;
 	}
@@ -143,6 +150,20 @@ extern "C" {
 }
 #endif
 
+void
+FrameBuf:: GetCursorPosition(int *x, int *y)
+{
+	float scale_x, scale_y;
+
+	SDL_GetMouseState(x, y);
+	SDL_RenderGetScale(renderer, &scale_x, &scale_y);
+
+	*x = (int)(*x/scale_x) - output.x;
+	*y = (int)(*y/scale_y) - output.y;
+	*x = (*x * rect.w) / output.w;
+	*y = (*y * rect.h) / output.h;
+}
+
 void
 FrameBuf::EnableTextInput()
 {
@@ -164,7 +185,7 @@ FrameBuf::DisableTextInput()
 }
 
 void
-FrameBuf:: GetDesktopSize(int &w, int &h)
+FrameBuf:: GetDesktopSize(int &w, int &h) const
 {
 	SDL_DisplayMode mode;
 
@@ -178,13 +199,13 @@ FrameBuf:: GetDesktopSize(int &w, int &h)
 }
 
 void
-FrameBuf:: GetDisplaySize(int &w, int &h)
+FrameBuf:: GetDisplaySize(int &w, int &h) const
 {
 	SDL_GetWindowSize(window, &w, &h);
 }
 
 void
-FrameBuf:: GetLogicalSize(int &w, int &h)
+FrameBuf:: GetLogicalSize(int &w, int &h) const
 {
 	SDL_RenderGetLogicalSize(renderer, &w, &h);
 	if (!w || !h) {
@@ -200,6 +221,27 @@ FrameBuf:: SetLogicalSize(int w, int h)
 	UpdateWindowSize(w, h);
 }
 
+void
+FrameBuf:: SetLogicalScale(float scale)
+{
+	logicalScale = scale;
+
+	int w, h;
+	if (Resizable()) {
+		SDL_GetWindowSize(window, &w, &h);
+	} else {
+		w = Width();
+		h = Height();
+	}
+	if (logicalScale > 0.0f) {
+		w = (int)(w/logicalScale);
+		h = (int)(h/logicalScale);
+		SetLogicalSize(w, h);
+	} else {
+		UpdateWindowSize(w, h);
+	}
+}
+
 void
 FrameBuf:: QueueBlit(SDL_Texture *src,
 			int srcx, int srcy, int srcw, int srch,
diff --git a/screenlib/SDL_FrameBuf.h b/screenlib/SDL_FrameBuf.h
index c529fed5..cd77aee0 100644
--- a/screenlib/SDL_FrameBuf.h
+++ b/screenlib/SDL_FrameBuf.h
@@ -107,10 +107,14 @@ class FrameBuf : public ErrorBase {
 	bool Resizable() const {
 		return resizable;
 	}
-	void GetDesktopSize(int &w, int &h);
-	void GetDisplaySize(int &w, int &h);
-	void GetLogicalSize(int &w, int &h);
+	void GetDesktopSize(int &w, int &h) const;
+	void GetDisplaySize(int &w, int &h) const;
+	void GetLogicalSize(int &w, int &h) const;
 	void SetLogicalSize(int w, int h);
+	float GetLogicalScale() const {
+		return logicalScale;
+	}
+	void SetLogicalScale(float scale);
 
 	/* Blit and update routines */
 	void QueueBlit(SDL_Texture *src,
@@ -210,9 +214,7 @@ class FrameBuf : public ErrorBase {
 	void HideCursor(void) {
 		SDL_ShowCursor(0);
 	}
-	void GetCursorPosition(int *x, int *y) {
-		SDL_GetMouseState(x, y);
-	}
+	void GetCursorPosition(int *x, int *y);
 	void SetCaption(const char *caption, const char *icon = NULL) {
 		SDL_SetWindowTitle(window, caption);
 	}
@@ -226,6 +228,7 @@ class FrameBuf : public ErrorBase {
 	SDL_Rect clip;
 	SDL_Rect output;
 	bool resizable;
+	float logicalScale;
 
 	void UpdateWindowSize(int width, int height) {
 		clip.x = rect.x = 0;