From 088fc6fc565471ab57889fd81d10e574b90e2f39 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 3 Oct 2017 13:09:29 +0300 Subject: [PATCH] [GTK3] Fixed DPI support for DeferredRenderer --- src/Gtk/Avalonia.Gtk3/FramebufferManager.cs | 2 +- .../Avalonia.Gtk3/ImageSurfaceFramebuffer.cs | 26 ++++++++----------- src/Gtk/Avalonia.Gtk3/Interop/Native.cs | 6 ++++- src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs | 3 ++- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs index 00d1ec05f3..b0cc668569 100644 --- a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs +++ b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs @@ -27,7 +27,7 @@ namespace Avalonia.Gtk3 var s = _window.ClientSize; var width = (int) s.Width; var height = (int) s.Height; - return new ImageSurfaceFramebuffer(_window, width, height); + return new ImageSurfaceFramebuffer(_window, width, height, _window.LastKnownScaleFactor); } } } diff --git a/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs index 34a95df47e..53771dd369 100644 --- a/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs +++ b/src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs @@ -19,11 +19,11 @@ namespace Avalonia.Gtk3 private CairoSurface _surface; private int _factor; private object _lock = new object(); - public ImageSurfaceFramebuffer(WindowBaseImpl impl, int width, int height) + public ImageSurfaceFramebuffer(WindowBaseImpl impl, int width, int height, int factor) { _impl = impl; _widget = impl.GtkWidget; - _factor = (int)(Native.GtkWidgetGetScaleFactor?.Invoke(_widget) ?? 1u); + _factor = factor; width *= _factor; height *= _factor; _surface = Native.CairoImageSurfaceCreate(1, width, height); @@ -32,23 +32,21 @@ namespace Avalonia.Gtk3 Height = height; Address = Native.CairoImageSurfaceGetData(_surface); RowBytes = Native.CairoImageSurfaceGetStride(_surface); + Native.CairoSurfaceSetDeviceScale(_surface, factor, factor); Native.CairoSurfaceFlush(_surface); } - static void Draw(IntPtr context, CairoSurface surface, double factor) + static void Draw(IntPtr context, CairoSurface surface) { - Native.CairoSurfaceMarkDirty(surface); - Native.CairoScale(context, 1d / factor, 1d / factor); Native.CairoSetSourceSurface(context, surface, 0, 0); Native.CairoPaint(context); - } /* static Stopwatch St =Stopwatch.StartNew(); private static int _frames; private static int _fps;*/ - static void DrawToWidget(GtkWidget widget, CairoSurface surface, int width, int height, double factor) + static void DrawToWidget(GtkWidget widget, CairoSurface surface, int width, int height) { if(surface == null || widget.IsClosed) return; @@ -58,7 +56,7 @@ namespace Avalonia.Gtk3 var rc = new GdkRectangle {Width = width, Height = height}; Native.GdkWindowBeginPaintRect(window, ref rc); var context = Native.GdkCairoCreate(window); - Draw(context, surface, factor); + Draw(context, surface); /* _frames++; var el = St.Elapsed; @@ -84,15 +82,13 @@ namespace Avalonia.Gtk3 { private readonly GtkWidget _widget; private CairoSurface _surface; - private readonly double _factor; private readonly int _width; private readonly int _height; - public RenderOp(GtkWidget widget, CairoSurface _surface, double factor, int width, int height) + public RenderOp(GtkWidget widget, CairoSurface _surface, int width, int height) { _widget = widget; this._surface = _surface; - _factor = factor; _width = width; _height = height; } @@ -105,7 +101,7 @@ namespace Avalonia.Gtk3 public void RenderNow() { - DrawToWidget(_widget, _surface, _width, _height, _factor); + DrawToWidget(_widget, _surface, _width, _height); } } @@ -116,13 +112,13 @@ namespace Avalonia.Gtk3 if (Dispatcher.UIThread.CheckAccess()) { if (_impl.CurrentCairoContext != IntPtr.Zero) - Draw(_impl.CurrentCairoContext, _surface, _factor); + Draw(_impl.CurrentCairoContext, _surface); else - DrawToWidget(_widget, _surface, Width, Height, _factor); + DrawToWidget(_widget, _surface, Width, Height); _surface.Dispose(); } else - _impl.SetNextRenderOperation(new RenderOp(_widget, _surface, _factor, Width, Height)); + _impl.SetNextRenderOperation(new RenderOp(_widget, _surface, Width, Height)); _surface = null; } } diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs index a6a08c3614..3c6c60ba10 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs @@ -178,7 +178,10 @@ namespace Avalonia.Gtk3.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_surface_destroy(IntPtr surface); - + + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] + public delegate void cairo_surface_set_device_scale(CairoSurface surface, double sx, double sy); + [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)] public delegate void cairo_set_source_surface(IntPtr cr, CairoSurface surface, double x, double y); @@ -465,6 +468,7 @@ namespace Avalonia.Gtk3.Interop public static D.cairo_surface_write_to_png CairoSurfaceWriteToPng; public static D.cairo_surface_flush CairoSurfaceFlush; public static D.cairo_surface_destroy CairoSurfaceDestroy; + public static D.cairo_surface_set_device_scale CairoSurfaceSetDeviceScale; public static D.cairo_set_source_surface CairoSetSourceSurface; public static D.cairo_set_source_rgba CairoSetSourceRgba; public static D.cairo_scale CairoScale; diff --git a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs index 009ef6763c..bfec3db756 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs @@ -306,7 +306,7 @@ namespace Avalonia.Gtk3 public IMouseDevice MouseDevice => Gtk3Platform.Mouse; - public double Scaling => (double) 1 / (Native.GtkWidgetGetScaleFactor?.Invoke(GtkWidget) ?? 1); + public double Scaling => LastKnownScaleFactor = (int) (Native.GtkWidgetGetScaleFactor?.Invoke(GtkWidget) ?? 1); public IPlatformHandle Handle => this; @@ -387,6 +387,7 @@ namespace Avalonia.Gtk3 public Size ClientSize { get; private set; } + public int LastKnownScaleFactor { get; private set; } public void Resize(Size value) {