From a80e3778fdf6b1c03a20c5889e969dda7d8119ff Mon Sep 17 00:00:00 2001 From: Thomas Friedel Date: Tue, 11 Feb 2020 11:28:18 +0100 Subject: [PATCH] changed the way window scaling is done to support high DPI scaling, use the FramebufferSize functions in glfwcanvas and sdlcanvas to determine the canvas size --- examples/drawing/drawing.go | 14 +++++++++++++ glfwcanvas/glfwcanvas.go | 26 ++++++++--------------- sdlcanvas/sdlcanvas.go | 41 ++++++++++--------------------------- 3 files changed, 34 insertions(+), 47 deletions(-) diff --git a/examples/drawing/drawing.go b/examples/drawing/drawing.go index cef7337..bee02d4 100644 --- a/examples/drawing/drawing.go +++ b/examples/drawing/drawing.go @@ -33,6 +33,20 @@ func main() { cv.SetFillStyle("#000") cv.FillRect(0, 0, w, h) + // Estimated size used for scaling + const ( + contentWidth = 1000 + contentHeight = 350 + ) + + // Calculate scaling + sx := w / contentWidth + sy := h / contentHeight + scale := math.Min(sx, sy) + cv.Save() + defer cv.Restore() + cv.Scale(scale, scale) + // Draw lines with different colors and line thickness for x := 1.0; x < 10.5; x += 1.0 { cv.SetStrokeStyle(int(x*25), 255, 255) diff --git a/glfwcanvas/glfwcanvas.go b/glfwcanvas/glfwcanvas.go index ae11d25..07c73c2 100644 --- a/glfwcanvas/glfwcanvas.go +++ b/glfwcanvas/glfwcanvas.go @@ -33,8 +33,6 @@ type Window struct { KeyUp func(scancode int, rn rune, name string) KeyChar func(rn rune) SizeChange func(w, h int) - scalex float64 - scaley float64 } // CreateWindow creates a window using SDL and initializes the OpenGL context @@ -79,8 +77,6 @@ func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { wnd := &Window{ Window: window, canvas: cv, - scalex: float64(fbw) / float64(w), - scaley: float64(fbh) / float64(h), } var mx, my int @@ -93,7 +89,7 @@ func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { } }) window.SetCursorPosCallback(func(w *glfw.Window, xpos, ypos float64) { - mx, my = int(math.Round(xpos*wnd.scalex)), int(math.Round(ypos*wnd.scaley)) + mx, my = int(math.Round(xpos)), int(math.Round(ypos)) if wnd.MouseMove != nil { wnd.MouseMove(mx, my) } @@ -116,12 +112,10 @@ func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { } }) window.SetSizeCallback(func(w *glfw.Window, width, height int) { - fbw, fbh := window.GetFramebufferSize() - wnd.scalex = float64(fbw) / float64(width) - wnd.scaley = float64(fbh) / float64(height) if wnd.SizeChange != nil { wnd.SizeChange(width, height) } else { + fbw, fbh := window.GetFramebufferSize() backend.SetBounds(0, 0, fbw, fbh) } }) @@ -168,25 +162,23 @@ func (wnd *Window) FinishFrame() { func (wnd *Window) MainLoop(run func()) { for !wnd.close { wnd.StartFrame() - if wnd.scalex != 1 || wnd.scaley != 1 { - wnd.canvas.Save() - wnd.canvas.Scale(wnd.scalex, wnd.scaley) - } run() - if wnd.scalex != 1 || wnd.scaley != 1 { - wnd.canvas.Restore() - } wnd.FinishFrame() } } -// Size returns the current width and height of the window +// Size returns the current width and height of the window. +// Note that this size may not be the same as the size of the +// framebuffer, since some operating systems scale the window. +// Use the Width/Height/Size function on Canvas to determine +// the drawing size func (wnd *Window) Size() (int, int) { return wnd.Window.GetSize() } // FramebufferSize returns the current width and height of -// the framebuffer +// the framebuffer, which is also the internal size of the +// canvas func (wnd *Window) FramebufferSize() (int, int) { return wnd.Window.GetFramebufferSize() } diff --git a/sdlcanvas/sdlcanvas.go b/sdlcanvas/sdlcanvas.go index 4ceabe7..d67d26e 100644 --- a/sdlcanvas/sdlcanvas.go +++ b/sdlcanvas/sdlcanvas.go @@ -5,7 +5,6 @@ import ( _ "image/gif" // Imported here so that applications based on this package support these formats by default _ "image/jpeg" _ "image/png" - "math" "runtime" "time" "unicode/utf8" @@ -39,8 +38,6 @@ type Window struct { KeyUp func(scancode int, rn rune, name string) KeyChar func(rn rune) SizeChange func(w, h int) - scalex float64 - scaley float64 } // CreateWindow creates a window using SDL and initializes the OpenGL context @@ -108,8 +105,6 @@ func CreateWindow(w, h int, title string) (*Window, *canvas.Canvas, error) { Backend: backend, canvas: cv, events: make([]sdl.Event, 0, 100), - scalex: float64(fbw) / float64(w), - scaley: float64(fbh) / float64(h), } return wnd, cv, nil @@ -150,27 +145,23 @@ func (wnd *Window) StartFrame() error { case *sdl.MouseButtonEvent: if e.Type == sdl.MOUSEBUTTONDOWN { if wnd.MouseDown != nil { - mx, my := wnd.mpos(e.X, e.Y) - wnd.MouseDown(int(e.Button), mx, my) + wnd.MouseDown(int(e.Button), int(e.X), int(e.Y)) handled = true } } else if e.Type == sdl.MOUSEBUTTONUP { if wnd.MouseUp != nil { - mx, my := wnd.mpos(e.X, e.Y) - wnd.MouseUp(int(e.Button), mx, my) + wnd.MouseUp(int(e.Button), int(e.X), int(e.Y)) handled = true } } case *sdl.MouseMotionEvent: if wnd.MouseMove != nil { - mx, my := wnd.mpos(e.X, e.Y) - wnd.MouseMove(mx, my) + wnd.MouseMove(int(e.X), int(e.Y)) handled = true } case *sdl.MouseWheelEvent: if wnd.MouseWheel != nil { - mx, my := wnd.mpos(e.X, e.Y) - wnd.MouseWheel(mx, my) + wnd.MouseWheel(int(e.X), int(e.Y)) handled = true } case *sdl.KeyboardEvent: @@ -195,8 +186,6 @@ func (wnd *Window) StartFrame() error { if e.WindowID == wnd.WindowID { if e.Event == sdl.WINDOWEVENT_SIZE_CHANGED { fbw, fbh := wnd.Window.GLGetDrawableSize() - wnd.scalex = float64(fbw) / float64(e.Data1) - wnd.scaley = float64(fbh) / float64(e.Data2) if wnd.SizeChange != nil { wnd.SizeChange(int(e.Data1), int(e.Data2)) handled = true @@ -220,12 +209,6 @@ func (wnd *Window) StartFrame() error { return nil } -func (wnd *Window) mpos(x, y int32) (int, int) { - mx := int(math.Round(float64(x) * wnd.scalex)) - my := int(math.Round(float64(y) * wnd.scaley)) - return mx, my -} - // FinishFrame updates the FPS count and displays the frame func (wnd *Window) FinishFrame() { now := time.Now() @@ -267,27 +250,25 @@ func (wnd *Window) MainLoop(run func()) { } } - if wnd.scalex != 1 || wnd.scaley != 1 { - wnd.canvas.Save() - wnd.canvas.Scale(wnd.scalex, wnd.scaley) - } run() - if wnd.scalex != 1 || wnd.scaley != 1 { - wnd.canvas.Restore() - } wnd.FinishFrame() } } -// Size returns the current width and height of the window +// Size returns the current width and height of the window. +// Note that this size may not be the same as the size of the +// framebuffer, since some operating systems scale the window. +// Use the Width/Height/Size function on Canvas to determine +// the drawing size func (wnd *Window) Size() (int, int) { w, h := wnd.Window.GetSize() return int(w), int(h) } // FramebufferSize returns the current width and height of -// the framebuffer +// the framebuffer, which is also the internal size of the +// canvas func (wnd *Window) FramebufferSize() (int, int) { w, h := wnd.Window.GLGetDrawableSize() return int(w), int(h)