Pārlūkot izejas kodu

Switched cairo to use xplat Visual/ImageBrush code

Nikita Tsukanov 10 gadi atpakaļ
vecāks
revīzija
23b5706a21

+ 2 - 1
Perspex.sln

@@ -108,10 +108,11 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared
 EndProject
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
+		src\Shared\RenderHelpers\RenderHelpers.projitems*{fb05ac90-89ba-4f2f-a924-f37875fb547c}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{db070a10-bf39-4752-8456-86e9d5928478}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{54f237d5-a70a-4752-9656-0c70b1a7b047}*SharedItemsImports = 4
-		Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
+		src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4
 	EndGlobalSection

+ 1 - 1
src/Gtk/Perspex.Cairo/Media/ImageBrushImpl.cs

@@ -7,7 +7,7 @@ namespace Perspex.Cairo.Media
 	{
 		public ImageBrushImpl(Perspex.Media.ImageBrush brush, Size destinationSize)
 		{
-			this.PlatformBrush = TileBrushes.CreateImageBrush(brush, destinationSize);
+			this.PlatformBrush = TileBrushes.CreateTileBrush(brush, destinationSize);
 		}
 	}
 }

+ 8 - 178
src/Gtk/Perspex.Cairo/Media/TileBrushes.cs

@@ -8,115 +8,22 @@ using Perspex.Layout;
 using Perspex.Media;
 using Perspex.Platform;
 using Perspex.Rendering;
+using Perspex.RenderHelpers;
 
 namespace Perspex.Cairo.Media
 {
     internal static class TileBrushes
     {
-        public static SurfacePattern CreateImageBrush(ImageBrush brush, Size targetSize)
+        public static SurfacePattern CreateTileBrush(TileBrush brush, Size targetSize)
         {
-            if (brush.Source == null)
-            {
+            var helper = new TileBrushImplHelper(brush, targetSize);
+            if (!helper.IsValid)
                 return null;
-            }
-
-            // TODO: This is directly ported from Direct2D and could probably be made more
-            // efficient on cairo by taking advantage of the fact that cairo has Extend.None.
-            var image = ((BitmapImpl)brush.Source.PlatformImpl).Surface;
-            var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight);
-            var tileMode = brush.TileMode;
-            var sourceRect = brush.SourceRect.ToPixels(imageSize);
-            var destinationRect = brush.DestinationRect.ToPixels(targetSize);
-            var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
-            var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
-            var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
-
-			var intermediate = new ImageSurface (Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height);
-            using (var context = new Context(intermediate))
-            {
-                Rect drawRect;
-                var transform = CalculateIntermediateTransform(
-                    tileMode,
-                    sourceRect,
-                    destinationRect,
-                    scale,
-                    translate,
-                    out drawRect);
-                context.Rectangle(drawRect.ToCairo());
-                context.Clip();
-                context.Transform(transform.ToCairo());
-                Gdk.CairoHelper.SetSourcePixbuf(context, image, 0, 0);
-                context.Rectangle(0, 0, imageSize.Width, imageSize.Height);
-                context.Fill();
-
-                var result = new SurfacePattern(intermediate);
-
-                if ((brush.TileMode & TileMode.FlipXY) != 0)
-                {
-                    // TODO: Currently always FlipXY as that's all cairo supports natively. 
-                    // Support separate FlipX and FlipY by drawing flipped images to intermediate
-                    // surface.
-                    result.Extend = Extend.Reflect;
-                }
-                else
-                {
-                    result.Extend = Extend.Repeat;
-                }
-
-                if (brush.TileMode != TileMode.None)
-                {
-                    var matrix = result.Matrix;
-                    matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
-                    result.Matrix = matrix;
-                }
-
-                return result;
-            }
-        }
-
-        public static SurfacePattern CreateVisualBrush(VisualBrush brush, Size targetSize)
-        {
-            var visual = brush.Visual;
-
-            if (visual == null)
-            {
-                return null;
-            }
-
-            var layoutable = visual as ILayoutable;
-
-            if (layoutable?.IsArrangeValid == false)
-            {
-                layoutable.Measure(Size.Infinity);
-                layoutable.Arrange(new Rect(layoutable.DesiredSize));
-            }
-
-            // TODO: This is directly ported from Direct2D and could probably be made more
-            // efficient on cairo by taking advantage of the fact that cairo has Extend.None.
-            var tileMode = brush.TileMode;
-            var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size);
-            var destinationRect = brush.DestinationRect.ToPixels(targetSize);
-            var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
-            var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
-            var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
             
-			using (var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height))
+			using (var intermediate = new ImageSurface(Format.ARGB32, (int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height))
             using (var ctx = new RenderTarget(intermediate).CreateDrawingContext())
             {
-                Rect drawRect;
-                var transform = CalculateIntermediateTransform(
-                    tileMode,
-                    sourceRect,
-                    destinationRect,
-                    scale,
-                    translate,
-                    out drawRect);
-
-                using (ctx.PushClip(drawRect))
-                using (ctx.PushPostTransform(transform))
-                {
-                    ctx.Render(visual);
-                }
+                helper.DrawIntermediate(ctx);
 
                 var result = new SurfacePattern(intermediate);
 
@@ -135,7 +42,7 @@ namespace Perspex.Cairo.Media
                 if (brush.TileMode != TileMode.None)
                 {
                     var matrix = result.Matrix;
-                    matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
+                    matrix.InitTranslate(-helper.DestinationRect.X, -helper.DestinationRect.Y);
                     result.Matrix = matrix;
                 }
 
@@ -143,83 +50,6 @@ namespace Perspex.Cairo.Media
             }
         }
 
-        /// <summary>
-        /// Calculates a translate based on a <see cref="TileBrush"/>, a source and destination
-        /// rectangle and a scale.
-        /// </summary>
-        /// <param name="brush">The brush.</param>
-        /// <param name="sourceRect">The source rectangle.</param>
-        /// <param name="destinationRect">The destination rectangle.</param>
-        /// <param name="scale">The scale factor.</param>
-        /// <returns>A vector with the X and Y translate.</returns>
-        private static Vector CalculateTranslate(
-            TileBrush brush,
-            Rect sourceRect,
-            Rect destinationRect,
-            Vector scale)
-        {
-            var x = 0.0;
-            var y = 0.0;
-            var size = sourceRect.Size * scale;
-
-            switch (brush.AlignmentX)
-            {
-                case AlignmentX.Center:
-                    x += (destinationRect.Width - size.Width) / 2;
-                    break;
-                case AlignmentX.Right:
-                    x += destinationRect.Width - size.Width;
-                    break;
-            }
-
-            switch (brush.AlignmentY)
-            {
-                case AlignmentY.Center:
-                    y += (destinationRect.Height - size.Height) / 2;
-                    break;
-                case AlignmentY.Bottom:
-                    y += destinationRect.Height - size.Height;
-                    break;
-            }
-
-            return new Vector(x, y);
-        }
-
-        private static Size CalculateIntermediateSize(
-            TileMode tileMode,
-            Size targetSize,
-            Size destinationSize)
-        {
-            var result = tileMode == TileMode.None ? targetSize : destinationSize;
-            return result;
-        }
-
-        private static Matrix CalculateIntermediateTransform(
-            TileMode tileMode,
-            Rect sourceRect,
-            Rect destinationRect,
-            Vector scale,
-            Vector translate,
-            out Rect drawRect)
-        {
-            var transform = Matrix.CreateTranslation(-sourceRect.Position) *
-                Matrix.CreateScale(scale) *
-                Matrix.CreateTranslation(translate);
-            Rect dr;
-
-            if (tileMode == TileMode.None)
-            {
-                dr = destinationRect;
-                transform *= Matrix.CreateTranslation(destinationRect.Position);
-            }
-            else
-            {
-                dr = new Rect(destinationRect.Size);
-            }
-
-            drawRect = dr;
-
-            return transform;
-        }
+      
     }
 }

+ 1 - 1
src/Gtk/Perspex.Cairo/Media/VisualBrushImpl.cs

@@ -7,7 +7,7 @@ namespace Perspex.Cairo.Media
 	{
 		public VisualBrushImpl(Perspex.Media.VisualBrush brush, Size destinationSize)
 		{
-			this.PlatformBrush = TileBrushes.CreateVisualBrush(brush, destinationSize);
+			this.PlatformBrush = TileBrushes.CreateTileBrush(brush, destinationSize);
 		}
 	}
 }

+ 1 - 0
src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj

@@ -93,6 +93,7 @@
     <None Include="app.config" />
     <None Include="packages.config" />
   </ItemGroup>
+  <Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
        Other similar extension points exist, see Microsoft.Common.targets.