Jelajahi Sumber

Merge pull request #361 from PixiEditor/even-more-fixes

More fixes
Krzysztof Krysiński 3 tahun lalu
induk
melakukan
a15b5bce6e

+ 27 - 0
PixiEditor/Helpers/Converters/WidthToBitmapScalingModeConverter.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Media;
+
+namespace PixiEditor.Helpers.Converters
+{
+    internal class WidthToBitmapScalingModeConverter : SingleInstanceMultiValueConverter<WidthToBitmapScalingModeConverter>
+    {
+        public override object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+        {
+            int? pixelWidth = values[0] as int?;
+            double? actualWidth = values[1] as double?;
+            if (pixelWidth == null || actualWidth == null)
+                return DependencyProperty.UnsetValue;
+            double zoomLevel = actualWidth.Value / pixelWidth.Value;
+            if (zoomLevel < 1)
+                return BitmapScalingMode.HighQuality;
+            return BitmapScalingMode.NearestNeighbor;
+        }
+
+        public override object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 22 - 0
PixiEditor/Helpers/Converters/ZoomLevelToBitmapScalingModeConverter.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Globalization;
+using System.Windows.Media;
+
+namespace PixiEditor.Helpers.Converters
+{
+    internal class ZoomLevelToBitmapScalingModeConverter : SingleInstanceConverter<ZoomLevelToBitmapScalingModeConverter>
+    {
+        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            double zoomLevel = (double)value;
+            if (zoomLevel < 1)
+                return BitmapScalingMode.HighQuality;
+            return BitmapScalingMode.NearestNeighbor;
+        }
+
+        public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 2 - 2
PixiEditor/Models/Constants.cs

@@ -3,8 +3,8 @@
     internal class Constants
     {
         public const int DefaultCanvasSize = 64;
-        public const int MaxPreviewWidth = 2048;
-        public const int MaxPreviewHeight = 2048;
+        public const int MaxPreviewWidth = 128;
+        public const int MaxPreviewHeight = 128;
 
         public const int MaxCanvasSize = 9999;
 

+ 3 - 1
PixiEditor/Models/Controllers/SurfaceRenderer.cs

@@ -12,6 +12,7 @@ namespace PixiEditor.Models.Controllers
         public SKSurface BackingSurface { get; private set; }
         public WriteableBitmap FinalBitmap { get; private set; }
         private SKPaint BlendingPaint { get; } = new SKPaint() { BlendMode = SKBlendMode.SrcOver };
+        private SKPaint HighQualityResizePaint { get; } = new SKPaint() { FilterQuality = SKFilterQuality.High };
         public SurfaceRenderer(int width, int height)
         {
             FinalBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Pbgra32, null);
@@ -23,6 +24,7 @@ namespace PixiEditor.Models.Controllers
         {
             BackingSurface.Dispose();
             BlendingPaint.Dispose();
+            HighQualityResizePaint.Dispose();
         }
 
         public void Draw(Surface otherSurface, byte opacity)
@@ -31,7 +33,7 @@ namespace PixiEditor.Models.Controllers
             FinalBitmap.Lock();
             BlendingPaint.Color = new SKColor(255, 255, 255, opacity);
             using (var snapshot = otherSurface.SkiaSurface.Snapshot())
-                BackingSurface.Canvas.DrawImage(snapshot, new SKRect(0, 0, FinalBitmap.PixelWidth, FinalBitmap.PixelHeight));
+                BackingSurface.Canvas.DrawImage(snapshot, new SKRect(0, 0, FinalBitmap.PixelWidth, FinalBitmap.PixelHeight), HighQualityResizePaint);
             FinalBitmap.AddDirtyRect(new Int32Rect(0, 0, FinalBitmap.PixelWidth, FinalBitmap.PixelHeight));
             FinalBitmap.Unlock();
         }

+ 10 - 3
PixiEditor/Models/DataHolders/Document/Document.Operations.cs

@@ -7,7 +7,6 @@ using SkiaSharp;
 using System;
 using System.Linq;
 using System.Windows;
-using Windows.Graphics;
 
 namespace PixiEditor.Models.DataHolders
 {
@@ -231,9 +230,19 @@ namespace PixiEditor.Models.DataHolders
             for (int i = 0; i < Layers.Count; i++)
             {
                 Layer layer = Layers[i];
+                Layers[i].MaxWidth = newWidth;
+                Layers[i].MaxHeight = newHeight;
+                if (layer.IsReset)
+                    continue;
+
                 Thickness newOffset = offset[i];
                 Int32Rect newRect = new((int)newOffset.Left, (int)newOffset.Top, layer.Width, layer.Height);
                 Int32Rect newLayerRect = newRect.Intersect(newCanvasRect);
+                if (!newLayerRect.HasArea)
+                {
+                    layer.Reset();
+                    continue;
+                }
                 Surface newBitmap = new(newLayerRect.Width, newLayerRect.Height);
                 var oldBitmap = layer.LayerBitmap;
                 using var snapshot = oldBitmap.SkiaSurface.Snapshot();
@@ -243,8 +252,6 @@ namespace PixiEditor.Models.DataHolders
                 oldBitmap.Dispose();
 
                 Layers[i].Offset = new Thickness(newLayerRect.X, newLayerRect.Y, 0, 0);
-                Layers[i].MaxWidth = newWidth;
-                Layers[i].MaxHeight = newHeight;
             }
 
             Width = newWidth;

+ 68 - 20
PixiEditor/Models/DataHolders/Document/Document.cs

@@ -114,16 +114,19 @@ namespace PixiEditor.Models.DataHolders
         /// </summary>
         public void ClipCanvas()
         {
-            DoubleCoords points = GetEdgePoints(Layers);
-            int smallestX = points.Coords1.X;
-            int smallestY = points.Coords1.Y;
-            int biggestX = points.Coords2.X;
-            int biggestY = points.Coords2.Y;
+            DoubleCoords? maybePoints = GetEdgePoints(Layers);
 
-            if (smallestX == 0 && smallestY == 0 && biggestX == 0 && biggestY == 0)
+            if (maybePoints == null)
             {
+                //all layers are empty
                 return;
             }
+            DoubleCoords points = maybePoints.Value;
+
+            int smallestX = points.Coords1.X;
+            int smallestY = points.Coords1.Y;
+            int biggestX = points.Coords2.X;
+            int biggestY = points.Coords2.Y;
 
             int width = biggestX - smallestX;
             int height = biggestY - smallestY;
@@ -133,15 +136,15 @@ namespace PixiEditor.Models.DataHolders
             int oldWidth = Width;
             int oldHeight = Height;
 
-            MoveOffsets(Layers, moveVector);
+            StorageBasedChange change = new StorageBasedChange(this, Layers);
 
-            object[] reverseArguments = { oldOffsets, oldWidth, oldHeight };
-            object[] processArguments = { Layers.Select(x => x.Offset).ToArray(), width, height };
+            object[] reverseArguments = { oldWidth, oldHeight };
+            object[] processArguments = { Layers.Select(x => new Thickness(x.OffsetX - smallestX, x.OffsetY - smallestY, 0, 0)).ToArray(), width, height };
 
             ResizeCanvasProcess(processArguments);
 
-            UndoManager.AddUndoChange(new Change(
-                ResizeCanvasProcess,
+            UndoManager.AddUndoChange(change.ToChange(
+                RestoreDocumentLayersProcess,
                 reverseArguments,
                 ResizeCanvasProcess,
                 processArguments,
@@ -155,22 +158,18 @@ namespace PixiEditor.Models.DataHolders
         {
             var layersToCenter = Layers.Where(x => x.IsActive && LayerStructureUtils.GetFinalLayerIsVisible(x, LayerStructure));
             if (!layersToCenter.Any())
-            {
                 return;
-            }
 
-            DoubleCoords points = GetEdgePoints(layersToCenter);
+            DoubleCoords? maybePoints = ClipLayersAndGetEdgePoints(layersToCenter);
+            if (maybePoints == null)
+                return;
+            DoubleCoords points = maybePoints.Value;
 
             int smallestX = points.Coords1.X;
             int smallestY = points.Coords1.Y;
             int biggestX = points.Coords2.X;
             int biggestY = points.Coords2.Y;
 
-            if (smallestX == 0 && smallestY == 0 && biggestX == 0 && biggestY == 0)
-            {
-                return;
-            }
-
             Coordinates contentCenter = CoordinatesCalculator.GetCenterPoint(points.Coords1, points.Coords2);
             Coordinates documentCenter = CoordinatesCalculator.GetCenterPoint(
                 new Coordinates(0, 0),
@@ -241,7 +240,47 @@ namespace PixiEditor.Models.DataHolders
             return 0;
         }
 
-        private DoubleCoords GetEdgePoints(IEnumerable<Layer> layers)
+        private DoubleCoords? GetEdgePoints(IEnumerable<Layer> layers)
+        {
+            if (Layers.Count == 0)
+                throw new ArgumentException("Not enough layers");
+
+            int smallestX = int.MaxValue;
+            int smallestY = int.MaxValue;
+            int biggestX = int.MinValue;
+            int biggestY = int.MinValue;
+
+            bool allLayersSkipped = true;
+
+            foreach (Layer layer in layers)
+            {
+                Int32Rect bounds = layer.TightBounds;
+                if (layer.IsReset || !bounds.HasArea)
+                    continue;
+                allLayersSkipped = false;
+
+                if (layer.OffsetX + bounds.X < smallestX)
+                    smallestX = layer.OffsetX + bounds.X;
+
+                if (layer.OffsetX + bounds.X + bounds.Width > biggestX)
+                    biggestX = layer.OffsetX + bounds.X + bounds.Width;
+
+                if (layer.OffsetY + bounds.Y < smallestY)
+                    smallestY = layer.OffsetY + bounds.Y;
+
+                if (layer.OffsetY + bounds.Y + bounds.Height > biggestY)
+                    biggestY = layer.OffsetY + bounds.Y + bounds.Height;
+            }
+
+            if (allLayersSkipped)
+                return null;
+
+            return new DoubleCoords(
+                new Coordinates(smallestX, smallestY),
+                new Coordinates(biggestX, biggestY));
+        }
+
+        private DoubleCoords? ClipLayersAndGetEdgePoints(IEnumerable<Layer> layers)
         {
             if (Layers.Count == 0)
             {
@@ -253,9 +292,15 @@ namespace PixiEditor.Models.DataHolders
             int biggestX = int.MinValue;
             int biggestY = int.MinValue;
 
+            bool allLayersSkipped = true;
+
             foreach (Layer layer in layers)
             {
                 layer.ClipCanvas();
+                if (layer.IsReset)
+                    continue;
+                allLayersSkipped = false;
+
                 if (layer.OffsetX < smallestX)
                 {
                     smallestX = layer.OffsetX;
@@ -277,6 +322,9 @@ namespace PixiEditor.Models.DataHolders
                 }
             }
 
+            if (allLayersSkipped)
+                return null;
+
             return new DoubleCoords(
                 new Coordinates(smallestX, smallestY),
                 new Coordinates(biggestX, biggestY));

+ 14 - 14
PixiEditor/Models/DataHolders/RecentlyOpenedDocument.cs

@@ -3,6 +3,7 @@ using PixiEditor.Models.IO;
 using PixiEditor.Models.Position;
 using PixiEditor.Parser;
 using PixiEditor.Parser.Skia;
+using System;
 using System.Diagnostics;
 using System.IO;
 using System.Linq;
@@ -88,7 +89,7 @@ namespace PixiEditor.Models.DataHolders
                               .Where(x => x.Opacity > 0.8)
                               .Select(x => (x.ToSKImage(), new Coordinates(x.OffsetX, x.OffsetY))));
 
-                return surface.ToWriteableBitmap();
+                return DownscaleToMaxSize(surface.ToWriteableBitmap());
             }
             else if (SupportedFilesHelper.IsExtensionSupported(FileExtension))
             {
@@ -103,25 +104,24 @@ namespace PixiEditor.Models.DataHolders
                     corrupt = true;
                     return null;
                 }
-                
-                if (bitmap == null)//prevent crash
-                    return null;
-
-                ImageFileMaxSizeChecker imageFileMaxSizeChecker = new ImageFileMaxSizeChecker()
-                {
-                    MaxAllowedWidthInPixels = Constants.MaxPreviewWidth,
-                    MaxAllowedHeightInPixels = Constants.MaxPreviewHeight,
-                };
 
-                if (bitmap == null)
+                if (bitmap == null) //prevent crash
                     return null;
 
-                return imageFileMaxSizeChecker.IsFileUnderMaxSize(bitmap) ?
-                    bitmap
-                    : bitmap.Resize(width: Constants.MaxPreviewWidth, height: Constants.MaxPreviewHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
+                return DownscaleToMaxSize(bitmap);
             }
 
             return null;
         }
+
+        private WriteableBitmap DownscaleToMaxSize(WriteableBitmap bitmap)
+        {
+            if (bitmap.PixelWidth > Constants.MaxPreviewWidth || bitmap.PixelHeight > Constants.MaxPreviewHeight)
+            {
+                double factor = Math.Min(Constants.MaxPreviewWidth / (double)bitmap.PixelWidth, Constants.MaxPreviewHeight / (double)bitmap.PixelHeight);
+                return bitmap.Resize((int)(bitmap.PixelWidth * factor), (int)(bitmap.PixelHeight * factor), WriteableBitmapExtensions.Interpolation.Bilinear);
+            }
+            return bitmap;
+        }
     }
 }

+ 0 - 20
PixiEditor/Models/IO/ImageFileMaxSizeChecker.cs

@@ -1,20 +0,0 @@
-using System.Windows.Media.Imaging;
-
-namespace PixiEditor.Models.IO
-{
-    internal class ImageFileMaxSizeChecker
-    {
-        public int MaxAllowedWidthInPixels { get; init; } = Constants.MaxPreviewWidth;
-        public int MaxAllowedHeightInPixels { get; init; } = Constants.MaxPreviewHeight;
-
-        public ImageFileMaxSizeChecker()
-        {
-        }
-
-        public bool IsFileUnderMaxSize(WriteableBitmap fileToCheck)
-        {
-            return fileToCheck.PixelWidth <= MaxAllowedWidthInPixels
-                && fileToCheck.PixelHeight <= MaxAllowedHeightInPixels;
-        }
-    }
-}

+ 0 - 22
PixiEditor/Models/IO/PixiFileMaxSizeChecker.cs

@@ -1,22 +0,0 @@
-using PixiEditor.Parser;
-
-namespace PixiEditor.Models.IO
-{
-    internal class PixiFileMaxSizeChecker
-    {
-        public int MaxAllowedWidthInPixels { get; init; } = 1080;
-        public int MaxAllowedHeightInPixels { get; init; } = 1080;
-        public int MaxAllowedLayerCount { get; init; } = 5;
-
-        public PixiFileMaxSizeChecker()
-        {
-        }
-
-        public bool IsFileUnderMaxSize(SerializableDocument fileToCheck)
-        {
-            return fileToCheck.Width <= MaxAllowedWidthInPixels
-                && fileToCheck.Height <= MaxAllowedHeightInPixels
-                && fileToCheck.Layers.Count <= MaxAllowedLayerCount;
-        }
-    }
-}

+ 5 - 2
PixiEditor/Models/Layers/Layer.cs

@@ -9,7 +9,6 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 using System.Windows;
-using Windows.Graphics;
 
 namespace PixiEditor.Models.Layers
 {
@@ -491,7 +490,11 @@ namespace PixiEditor.Models.Layers
         public void ClipCanvas()
         {
             var dimensions = GetContentDimensions();
-            if (dimensions == Int32Rect.Empty) return;
+            if (dimensions == Int32Rect.Empty)
+            {
+                Reset();
+                return;
+            }
 
             ResizeCanvas(0, 0, dimensions.X, dimensions.Y, dimensions.Width, dimensions.Height);
             Offset = new Thickness(OffsetX + dimensions.X, OffsetY + dimensions.Y, 0, 0);

+ 8 - 1
PixiEditor/Views/Dialogs/HelloTherePopup.xaml

@@ -119,7 +119,14 @@
                                                 Style="{StaticResource DarkRoundButton}"
                                                 x:Name="fileButton">
                                             <Grid Width="100" Height="100">
-                                                <Image Source="{Binding PreviewBitmap}" RenderOptions.BitmapScalingMode="NearestNeighbor" Margin="20"/>
+                                                <Image Source="{Binding PreviewBitmap}" x:Name="image" Margin="20">
+                                                    <RenderOptions.BitmapScalingMode>
+                                                        <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
+                                                            <Binding Path="PreviewBitmap.PixelWidth"/>
+                                                            <Binding ElementName="image" Path="ActualWidth"/>
+                                                        </MultiBinding>
+                                                    </RenderOptions.BitmapScalingMode>
+                                                </Image>
                                                 <Border Grid.Row="1" Height="8" Width="8" x:Name="extensionBorder" Margin="5"
                                                         Background="{Binding FileExtension, Converter={converters:FileExtensionToColorConverter}}" 
                                                         VerticalAlignment="Bottom" HorizontalAlignment="Right">

+ 0 - 13
PixiEditor/Views/MainWindow.xaml.cs

@@ -4,7 +4,6 @@ using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.ViewModels;
-using PixiEditor.Views.Dialogs;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -48,7 +47,6 @@ namespace PixiEditor
 
             UpdateWindowChromeBorderThickness();
             StateChanged += MainWindow_StateChanged;
-            Activated += MainWindow_Activated;
 
             DataContext.CloseAction = Close;
             Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
@@ -97,12 +95,6 @@ namespace PixiEditor
             ((HwndSource)PresentationSource.FromVisual(this)).AddHook(Helpers.WindowSizeHelper.SetMaxSizeHook);
         }
 
-        [Conditional("RELEASE")]
-        private static void CloseHelloThereIfRelease()
-        {
-            Application.Current.Windows.OfType<HelloTherePopup>().ToList().ForEach(x => { if (!x.IsClosing) x.Close(); });
-        }
-
         [Conditional("RELEASE")]
         private void OnReleaseBuild()
         {
@@ -158,11 +150,6 @@ namespace PixiEditor
             SystemCommands.CloseWindow(this);
         }
 
-        private void MainWindow_Activated(object sender, EventArgs e)
-        {
-            CloseHelloThereIfRelease();
-        }
-
         private void UpdateWindowChromeBorderThickness()
         {
             if (WindowState == WindowState.Maximized)

+ 5 - 2
PixiEditor/Views/UserControls/DrawingViewPort.xaml

@@ -82,11 +82,14 @@
                                           RenderOptions.BitmapScalingMode="NearestNeighbor"/>
 
                 <Image Source="{Binding PreviewLayerRenderer.FinalBitmap}" Panel.ZIndex="2"
-                       RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
+                       RenderOptions.BitmapScalingMode="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Zoombox}}, Path=Zoom, Converter={converters:ZoomLevelToBitmapScalingModeConverter}}" 
+                       Stretch="Uniform"
                        Width="{Binding Width}" Height="{Binding Height}"/>
 
+
                 <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Renderer.FinalBitmap}"
-                       RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform" 
+                       RenderOptions.BitmapScalingMode="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Zoombox}}, Path=Zoom, Converter={converters:ZoomLevelToBitmapScalingModeConverter}}" 
+                       Stretch="Uniform" 
                        Visibility="{Binding XamlAccesibleViewModel.BitmapManager.OnlyReferenceLayer, Converter={InverseBoolToVisibilityConverter}}"/>
 
                 <local:PlainLayerView TargetLayer="{Binding ActiveSelection.SelectionLayer}"

+ 8 - 2
PixiEditor/Views/UserControls/Layers/LayerGroupControl.xaml

@@ -36,8 +36,14 @@
                     <StackPanel Grid.Row="1" Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left">
                         <Border Width="30" Height="30" BorderThickness="1" BorderBrush="Black" Background="{StaticResource MainColor}"
                            Margin="5, 0, 10, 0">
-                            <Image Source="{Binding PreviewImage, ElementName=groupControl}" Stretch="Uniform" Width="20" Height="20" 
-                       RenderOptions.BitmapScalingMode="NearestNeighbor"/>
+                            <Image Source="{Binding PreviewImage, ElementName=groupControl}" Stretch="Uniform" Width="20" Height="20">
+                                <RenderOptions.BitmapScalingMode>
+                                    <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
+                                        <Binding Path="PreviewImage.PixelWidth" ElementName="groupControl"/>
+                                        <Binding RelativeSource="{RelativeSource Mode=Self}" Path="ActualWidth"/>
+                                    </MultiBinding>
+                                </RenderOptions.BitmapScalingMode>
+                            </Image>
                         </Border>
                         <userControls:EditableTextBlock
                     FontSize="16"

+ 9 - 1
PixiEditor/Views/UserControls/PlainLayerView.xaml

@@ -4,9 +4,17 @@
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
              xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d" 
              x:Name="uc"
              d:DesignHeight="450" d:DesignWidth="800">
     <Image x:Name="image" Width="{Binding Width, ElementName=uc}" Height="{Binding Height, ElementName=uc}" 
-           RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"/>
+           Stretch="Uniform">
+        <RenderOptions.BitmapScalingMode>
+            <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
+                <Binding RelativeSource="{RelativeSource Mode=Self}" Path="Source.PixelWidth"/>
+                <Binding RelativeSource="{RelativeSource Mode=Self}" Path="ActualWidth"/>
+            </MultiBinding>
+        </RenderOptions.BitmapScalingMode>
+    </Image>
 </UserControl>

+ 8 - 2
PixiEditor/Views/UserControls/PreviewWindow.xaml

@@ -34,8 +34,14 @@
                         </MultiBinding>
                     </Grid.LayoutTransform>
                 </Grid>
-                <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Document.Renderer.FinalBitmap, ElementName=uc}"
-                                               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform" />
+                <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Document.Renderer.FinalBitmap, ElementName=uc}" Stretch="Uniform">
+                    <RenderOptions.BitmapScalingMode>
+                        <MultiBinding Converter="{converters:WidthToBitmapScalingModeConverter}">
+                            <Binding ElementName="uc" Path="Document.Renderer.FinalBitmap.PixelWidth"/>
+                            <Binding ElementName="previewWindowViewbox" Path="ActualWidth"/>
+                        </MultiBinding>
+                    </RenderOptions.BitmapScalingMode>
+                </Image>
                 <Border x:Name="colorCursor" Width="1" Height="1"
                     Margin="{Binding ColorCursorPosition, ElementName=uc}"
                     HorizontalAlignment="Left" VerticalAlignment="Top"

+ 1 - 1
PixiEditor/Views/UserControls/Zoombox.xaml.cs

@@ -105,7 +105,7 @@ namespace PixiEditor.Views.UserControls
         public static readonly DependencyProperty UseTouchGesturesProperty =
             DependencyProperty.Register(nameof(UseTouchGestures), typeof(bool), typeof(Zoombox));
 
-        private const double zoomFactor = 1.1;
+        private const double zoomFactor = 1.09050773267; //2^(1/8)
         private const double maxZoom = 50;
         private double minZoom = -28;
         public object AdditionalContent