Browse Source

Merge branch 'master' into master

Dmitry Arndt 8 years ago
parent
commit
539a209639

+ 1 - 1
appveyor.yml

@@ -37,4 +37,4 @@ artifacts:
   - path: artifacts\inspectcode.xml
 cache:
   - gtk-sharp-2.12.26.msi
-  - dotnet-1.0.1.exe
+  - dotnet-2.0.0.exe

+ 10 - 10
build.cake

@@ -2,16 +2,15 @@
 // ADDINS
 ///////////////////////////////////////////////////////////////////////////////
 
-#addin "nuget:?package=Polly&version=4.2.0"
-#addin "nuget:?package=NuGet.Core&version=2.12.0"
-#tool "nuget:?package=xunit.runner.console&version=2.2.0"
-#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
+#addin "nuget:?package=Polly&version=5.3.1"
+#addin "nuget:?package=NuGet.Core&version=2.14.0"
+#tool "nuget:?package=NuGet.CommandLine&version=4.3.0"
 #tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2017.1.20170613.162720"
 ///////////////////////////////////////////////////////////////////////////////
 // TOOLS
 ///////////////////////////////////////////////////////////////////////////////
 
-#tool "nuget:?package=xunit.runner.console&version=2.2.0"
+#tool "nuget:?package=xunit.runner.console&version=2.3.0-beta5-build3769"
 
 ///////////////////////////////////////////////////////////////////////////////
 // USINGS
@@ -213,8 +212,8 @@ Task("Run-Unit-Tests")
         .ToList();
 
     var toolPath = (parameters.IsPlatformAnyCPU || parameters.IsPlatformX86) ? 
-        "./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
-        "./tools/xunit.runner.console/tools/xunit.console.exe";
+        Context.Tools.Resolve("xunit.console.x86.exe") :
+        Context.Tools.Resolve("xunit.console.exe");
 
     var xUnitSettings = new XUnit2Settings 
     { 
@@ -353,10 +352,12 @@ Task("Run-Leak-Tests")
         var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml";
         if(System.IO.File.Exists(report))
             System.IO.File.Delete(report);
+
+        var toolXunitConsoleX86 = Context.Tools.Resolve("xunit.console.x86.exe").FullPath;
         var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
         {
             FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe",
-            Arguments="-targetExecutable=\"tools\\xunit.runner.console\\tools\\xunit.console.x86.exe\" -returnTargetExitCode  -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
+            Arguments="-targetExecutable=\"" + toolXunitConsoleX86 + "\" -returnTargetExitCode  -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
             UseShellExecute = false,
         });
         var st = System.Diagnostics.Stopwatch.StartNew();
@@ -392,8 +393,7 @@ Task("Inspect")
             "src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
         Information("Running code inspections");
         
-        
-        StartProcess("tools\\JetBrains.ReSharper.CommandLineTools\\tools\\inspectcode.exe",
+        StartProcess(Context.Tools.Resolve("inspectcode.exe"),
             new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" });
         Information("Analyzing report");
         var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));

+ 62 - 1
src/Avalonia.Visuals/Media/PathMarkupParser.cs

@@ -21,7 +21,10 @@ namespace Avalonia.Media
             { 'L', Command.Line },
             { 'H', Command.HorizontalLine },
             { 'V', Command.VerticalLine },
+            { 'Q', Command.QuadraticBezierCurve },
+            { 'T', Command.SmoothQuadraticBezierCurve },
             { 'C', Command.CubicBezierCurve },
+            { 'S', Command.SmoothCubicBezierCurve },
             { 'A', Command.Arc },
             { 'Z', Command.Close },
         };
@@ -55,6 +58,9 @@ namespace Avalonia.Media
             HorizontalLine,
             VerticalLine,
             CubicBezierCurve,
+            QuadraticBezierCurve,
+            SmoothCubicBezierCurve,
+            SmoothQuadraticBezierCurve,
             Arc,
             Close,
         }
@@ -71,7 +77,8 @@ namespace Avalonia.Media
             {
                 Command command = Command.None;
                 Point point = new Point();
-                bool relative = false;
+                bool relative = false;        
+                Point? previousControlPoint = null;
 
                 while (ReadCommand(reader, ref command, ref relative))
                 {
@@ -79,6 +86,7 @@ namespace Avalonia.Media
                     {
                         case Command.FillRule:
                             _context.SetFillRule(ReadFillRule(reader));
+                            previousControlPoint = null;
                             break;
 
                         case Command.Move:
@@ -90,11 +98,13 @@ namespace Avalonia.Media
                             point = ReadPoint(reader, point, relative);
                             _context.BeginFigure(point, true);
                             openFigure = true;
+                            previousControlPoint = null;
                             break;
 
                         case Command.Line:
                             point = ReadPoint(reader, point, relative);
                             _context.LineTo(point);
+                            previousControlPoint = null;
                             break;
 
                         case Command.HorizontalLine:
@@ -108,6 +118,7 @@ namespace Avalonia.Media
                             }
 
                             _context.LineTo(point);
+                            previousControlPoint = null;
                             break;
 
                         case Command.VerticalLine:
@@ -121,18 +132,57 @@ namespace Avalonia.Media
                             }
 
                             _context.LineTo(point);
+                            previousControlPoint = null;
                             break;
 
+                        case Command.QuadraticBezierCurve:
+                            {
+                                Point handle = ReadPoint(reader, point, relative);
+                                previousControlPoint = handle;
+                                ReadSeparator(reader);
+                                point = ReadPoint(reader, point, relative);
+                                _context.QuadraticBezierTo(handle, point);
+                                break;
+                            }
+
+                        case Command.SmoothQuadraticBezierCurve:
+                            {
+                                Point end = ReadPoint(reader, point, relative);
+                                
+                                if(previousControlPoint != null)
+                                    previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point);
+                                
+                                _context.QuadraticBezierTo(previousControlPoint ?? point, end);
+                                point = end;
+                                break;
+                            }
+
                         case Command.CubicBezierCurve:
                             {
                                 Point point1 = ReadPoint(reader, point, relative);
                                 ReadSeparator(reader);
                                 Point point2 = ReadPoint(reader, point, relative);
+                                previousControlPoint = point2;
                                 ReadSeparator(reader);
                                 point = ReadPoint(reader, point, relative);
                                 _context.CubicBezierTo(point1, point2, point);
                                 break;
                             }
+                            
+                        case Command.SmoothCubicBezierCurve:
+                            {
+                                Point point2 = ReadPoint(reader, point, relative);
+                                ReadSeparator(reader);
+                                Point end = ReadPoint(reader, point, relative);
+                                
+                                if(previousControlPoint != null)
+                                    previousControlPoint = MirrorControlPoint((Point)previousControlPoint, point);
+                                
+                                _context.CubicBezierTo(previousControlPoint ?? point, point2, end);
+                                previousControlPoint = point2;
+                                point = end;
+                                break;
+                            }
 
                         case Command.Arc:
                             {
@@ -147,12 +197,14 @@ namespace Avalonia.Media
                                 point = ReadPoint(reader, point, relative);
 
                                 _context.ArcTo(point, size, rotationAngle, isLargeArc, sweepDirection);
+                                previousControlPoint = null;
                                 break;
                             }
 
                         case Command.Close:
                             _context.EndFigure(true);
                             openFigure = false;
+                            previousControlPoint = null;
                             break;
 
                         default:
@@ -167,6 +219,12 @@ namespace Avalonia.Media
             }
         }
 
+        private Point MirrorControlPoint(Point controlPoint, Point center)
+        {
+            Point dir = (controlPoint - center);
+            return center + -dir;
+        }
+
         private static bool ReadCommand(
             StringReader reader,
             ref Command command,
@@ -243,6 +301,9 @@ namespace Avalonia.Media
                     (c == 'E' && !readExponent) ||
                     char.IsDigit(c))
                 {
+                    if (b.Length != 0 && !readExponent && c == '-')
+                        break;
+                    
                     b.Append(c);
                     reader.Read();
 

+ 1 - 1
src/Skia/Avalonia.Skia/BitmapImpl.cs

@@ -48,7 +48,7 @@ namespace Avalonia.Skia
             public BitmapDrawingContext(SKBitmap bitmap, Vector dpi, IVisualBrushRenderer visualBrushRenderer)
                 : this(CreateSurface(bitmap), dpi, visualBrushRenderer)
             {
-
+                CanUseLcdRendering = false;
             }
 
             private static SKSurface CreateSurface(SKBitmap bitmap)

+ 2 - 2
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -16,7 +16,7 @@ namespace Avalonia.Skia
         private readonly IDisposable[] _disposables;
         private readonly IVisualBrushRenderer _visualBrushRenderer;
         private Stack<PaintWrapper> maskStack = new Stack<PaintWrapper>();
-        
+        protected bool CanUseLcdRendering = true;
         public SKCanvas Canvas { get; private set; }
 
         public DrawingContextImpl(
@@ -345,7 +345,7 @@ namespace Avalonia.Skia
             using (var paint = CreatePaint(foreground, text.Size))
             {
                 var textImpl = (FormattedTextImpl)text;
-                textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint);
+                textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint, CanUseLcdRendering);
             }
         }
 

+ 8 - 5
src/Skia/Avalonia.Skia/FormattedTextImpl.cs

@@ -171,8 +171,10 @@ namespace Avalonia.Skia
         }
 
         internal void Draw(DrawingContextImpl context,
-                           SKCanvas canvas, SKPoint origin,
-                           DrawingContextImpl.PaintWrapper foreground)
+            SKCanvas canvas,
+            SKPoint origin,
+            DrawingContextImpl.PaintWrapper foreground,
+            bool canUseLcdRendering)
         {
             /* TODO: This originated from Native code, it might be useful for debugging character positions as
              * we improve the FormattedText support. Will need to port this to C# obviously. Rmove when
@@ -206,7 +208,7 @@ namespace Avalonia.Skia
                 SKPaint currentPaint = null;
                 try
                 {
-                    ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint);
+                    ApplyWrapperTo(ref currentPaint, foreground, ref currd, paint, canUseLcdRendering);
                     bool hasCusomFGBrushes = _foregroundBrushes.Any();
 
                     for (int c = 0; c < _skiaLines.Count; c++)
@@ -243,7 +245,7 @@ namespace Avalonia.Skia
 
                                 subStr = Text.Substring(i, len);
 
-                                ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint);
+                                ApplyWrapperTo(ref currentPaint, currentWrapper, ref currd, paint, canUseLcdRendering);
                                 
                                 canvas.DrawText(subStr, currX, origin.Y + line.Top + _lineOffset, paint);
 
@@ -277,12 +279,13 @@ namespace Avalonia.Skia
         private List<AvaloniaFormattedTextLine> _skiaLines;
 
         private static void ApplyWrapperTo(ref SKPaint current, DrawingContextImpl.PaintWrapper wrapper,
-                                                ref IDisposable curr, SKPaint paint)
+                                                ref IDisposable curr, SKPaint paint, bool canUseLcdRendering)
         {
             if (current == wrapper.Paint)
                 return;
             curr?.Dispose();
             curr = wrapper.ApplyTo(paint);
+            paint.LcdRenderText = canUseLcdRendering;
         }
 
         private static bool IsBreakChar(char c)

+ 1 - 0
tests/Avalonia.RenderTests/Avalonia.RenderTests.projitems

@@ -14,6 +14,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Media\RadialGradientBrushTests.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Media\BitmapTests.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)OpacityMaskTests.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)SVGPathTests.cs" />
     <Compile Include="Media\FormattedTextImplTests.cs" />
     <Compile Include="Controls\ImageTests.cs" />
     <Compile Include="Controls\BorderTests.cs" />

+ 53 - 0
tests/Avalonia.RenderTests/SVGPathTests.cs

@@ -0,0 +1,53 @@
+using Avalonia.Controls;
+using Avalonia.Controls.Shapes;
+using Avalonia.Media;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Xunit;
+using System.Threading.Tasks;
+
+#if AVALONIA_CAIRO
+namespace Avalonia.Cairo.RenderTests
+#elif AVALONIA_SKIA
+namespace Avalonia.Skia.RenderTests
+#else
+namespace Avalonia.Direct2D1.RenderTests
+#endif
+{
+    public class SVGPathTests : TestBase
+    {
+        public SVGPathTests()
+            :base("SVGPath")
+        {
+        }
+
+        [Fact]
+        public async Task SVGPath()
+        {
+            var target = new Canvas
+            {
+                Background = Brushes.Yellow,
+                Width = 76,
+                Height = 76,
+                Children = new Avalonia.Controls.Controls
+                {
+                    new Path
+                    {
+                        Width = 32,
+                        Height = 40,
+                        [Canvas.LeftProperty] = 23,
+                        [Canvas.TopProperty] = 18,
+                        Stretch = Stretch.Fill,
+                        Fill = Brushes.Black,
+                        //Coffee Maker by Becris from the Noun Project
+                        Data = StreamGeometry.Parse("M5,51v4c0,1.654,1.346,3,3,3h7v3c0,0.552,0.447,1,1,1h8c0.553,0,1-0.448,1-1v-3h18v3c0,0.552,0.447,1,1,1h8  c0.553,0,1-0.448,1-1v-3c2.757,0,5-2.243,5-5V13V7c0-2.757-2.243-5-5-5H11C8.243,2,6,4.243,6,7v2c0,2.757,2.243,5,5,5h1.743  l-2.717,11.775c-0.068,0.297,0.002,0.609,0.192,0.848C10.407,26.861,10.695,27,11,27h4c0.431,0,0.812-0.275,0.948-0.684L18.721,18  h1.499l1.811,7.243C22.142,25.688,22.541,26,23,26h12c0.459,0,0.858-0.312,0.97-0.757L37.78,18h6.658l-3.235,29.11  C41.147,47.618,40.72,48,40.21,48h-4.167c0.873-1.159,1.203-2.622,0.897-4.047L35,34.895v-2.481l2.707-2.707  c0.286-0.286,0.372-0.716,0.217-1.09C37.77,28.244,37.404,28,37,28H22c-0.553,0-1,0.448-1,1v0.719l-2.758-0.689  c-0.443-0.111-0.906,0.094-1.123,0.496l-7,13l1.762,0.948l6.631-12.315L21,31.781v3.115l-1.94,9.057  c-0.306,1.426,0.025,2.889,0.897,4.048H8C6.346,48,5,49.346,5,51z M23,60h-6v-2h6V60z M51,60h-6v-2h6V60z M8,9V7  c0-1.654,1.346-3,3-3h42c1.654,0,3,1.346,3,3v5H46H14h-3C9.346,12,8,10.654,8,9z M34.219,24H23.781l-1.5-6h13.438L34.219,24z   M44.66,16H37H21h-3c-0.431,0-0.812,0.275-0.948,0.684L14.279,25h-2.022l2.539-11h30.087l-0.185,1.662L44.66,16z M43.191,47.331  L46.896,14H56v39c0,1.654-1.346,3-3,3h-1h-8H24h-8H8c-0.552,0-1-0.449-1-1v-4c0-0.551,0.448-1,1-1h15.948h8.104h8.158  C41.741,50,43.022,48.853,43.191,47.331z M23,30h11.586l-1.293,1.293C33.105,31.48,33,31.735,33,32v2H23V30z M21.614,46.886  c-0.571-0.708-0.79-1.624-0.6-2.514L22.809,36h10.383l1.794,8.372c0.19,0.89-0.028,1.806-0.6,2.514  C33.813,47.594,32.963,48,32.052,48h-8.104C23.037,48,22.187,47.594,21.614,46.886z")
+                    }
+                }
+            };
+
+            await RenderToFile(target);
+            CompareImages();
+        }
+    }
+}

BIN
tests/TestFiles/Cairo/SVGPath/SVGPath.expected.png


BIN
tests/TestFiles/Direct2D1/SVGPath/SVGPath.expected.png


BIN
tests/TestFiles/Skia/SVGPath/SVGPath.expected.png


+ 1 - 1
tools/packages.config

@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-    <package id="Cake" version="0.18.0" />
+    <package id="Cake" version="0.22.2" />
 </packages>