protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 266.75f, Position.Y - 272.15f); var scale = Size.Width / 200.0f; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var red = SKPath.ParseSvgPathData("M272.1 107.7c38.8-.6 76.3 14 104.4 40.8l77.7-77.7C405 24.6 339.7-.8 272.1 0 169.2 0 75.1 58 28.9 150l90.4 70.1c21.5-64.5 81.8-112.4 152.8-112.4z"); red.Transform(transformationMatrix); var green = SKPath.ParseSvgPathData("M272.1 544.3c73.4 0 135.3-24.1 180.4-65.7l-87.7-68c-24.4 16.6-55.9 26-92.6 26-71 0-131.2-47.9-152.8-112.3H28.9v70.1c46.2 91.9 140.3 149.9 243.2 149.9z"); green.Transform(transformationMatrix); var blue = SKPath.ParseSvgPathData("M533.5 278.4c0-18.5-1.5-37.1-4.7-55.3H272.1v104.8h147c-6.1 33.8-25.7 63.7-54.4 82.7v68h87.7c51.5-47.4 81.1-117.4 81.1-200.2z"); blue.Transform(transformationMatrix); var yellow = SKPath.ParseSvgPathData("M119.3 324.3c-11.4-33.8-11.4-70.4 0-104.2V150H28.9c-38.6 76.9-38.6 167.5 0 244.4l90.4-70.1z"); yellow.Transform(transformationMatrix); canvas.DrawPath(red, _r); canvas.DrawPath(green, _g); canvas.DrawPath(blue, _b); canvas.DrawPath(yellow, _y); }
public void TranslationToMatrixIsCorrect() { var m = SKMatrix.CreateTranslation(5, 7); var rsm = SKRotationScaleMatrix.CreateTranslation(5, 7).ToMatrix(); Assert.Equal(m.Values, rsm.Values); }
/// <inheritdoc /> public override void Render(SKCanvas canvas, SKRect bounds, SKPaint paint) { _lastBounds = bounds; // For brevity's sake ColorGradient gradient = Properties.Colors.BaseValue; SKMatrix matrix = SKMatrix.Concat( SKMatrix.CreateRotationDegrees(Properties.Rotation, bounds.MidX, bounds.MidY), SKMatrix.CreateTranslation(_scrollX, _scrollY) ); // LinearGradientRepeatMode.Mirror is currently the only setting that requires a different tile mode SKShaderTileMode tileMode = Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.Mirror ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; // Render gradient paint.Shader = SKShader.CreateLinearGradient( new SKPoint(bounds.Left, bounds.Top), new SKPoint( (Properties.Orientation == LinearGradientOrientationMode.Horizontal ? bounds.Right : bounds.Left) * Properties.WaveSize / 100, (Properties.Orientation == LinearGradientOrientationMode.Horizontal ? bounds.Top : bounds.Bottom) * Properties.WaveSize / 100 ), gradient.GetColorsArray(0, Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.RepeatSeamless), gradient.GetPositionsArray(0, Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.RepeatSeamless), tileMode, matrix ); canvas.DrawRect(bounds, paint); paint.Shader?.Dispose(); paint.Shader = null; }
public void MatrixCanInvert() { var m = SKMatrix.CreateTranslation(10, 20); Assert.True(m.TryInvert(out var inverse)); Assert.Equal(SKMatrix.CreateTranslation(-10, -20).Values, inverse.Values); }
internal override void Render(SKSurface surface) { foreach (var shape in Shapes) { surface.Canvas.Save(); var visualMatrix = surface.Canvas.TotalMatrix; visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(shape.Offset.X, shape.Offset.Y)); if (shape.Scale != new Vector2(1, 1)) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateScale(shape.Scale.X, shape.Scale.Y)); } if (shape.RotationAngleInDegrees != 0) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(shape.RotationAngleInDegrees, shape.CenterPoint.X, shape.CenterPoint.Y)); } if (shape.TransformMatrix != Matrix3x2.Identity) { visualMatrix = visualMatrix.PreConcat(shape.TransformMatrix.ToSKMatrix44().Matrix); } surface.Canvas.SetMatrix(visualMatrix); shape.Render(surface); surface.Canvas.Restore(); } }
public void MatrixMapsPoint() { var matrix = SKMatrix.CreateTranslation(2, 4); var expectedResult = matrix.MapPoint(3, 6); Assert.Equal(new SKPoint(5, 10), expectedResult); }
public void MatrixMapsPoints() { var source = new[] { new SKPoint(0, 0), new SKPoint(-10, -10), new SKPoint(-10, 10), new SKPoint(10, -10), new SKPoint(10, 10), new SKPoint(-5, -5), new SKPoint(-5, 5), new SKPoint(5, -5), new SKPoint(5, 5), }; var expectedResult = new[] { new SKPoint(10, 10), new SKPoint(0, 0), new SKPoint(0, 20), new SKPoint(20, 0), new SKPoint(20, 20), new SKPoint(5, 5), new SKPoint(5, 15), new SKPoint(15, 5), new SKPoint(15, 15), }; var matrix = SKMatrix.CreateTranslation(10, 10); matrix.MapPoints(source, source); Assert.Equal(expectedResult, source); }
/// <summary> /// Centers the viewport around the specified position(x-index and y-value) /// in the chart.Centering the viewport outside the bounds of the chart is /// not possible. Makes most sense in combination with the /// setScaleMinima(...) method. /// </summary> /// <param name="transformedPts">the position to center view viewport to</param> /// <param name="view"></param> public void CenterViewPort(SKPoint transformedPts, IChartBase view) { float x = transformedPts.X - OffsetLeft; float y = transformedPts.Y - OffsetTop; Refresh(touchMatrix.PostConcat(SKMatrix.CreateTranslation(-x, -y)), view, true); }
protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 11.5f, Position.Y - 11.5f); var scale = 6.0f / Size.Width; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var backgroundPath = SKPath.ParseSvgPathData("M0 0h23v23H0z"); backgroundPath.Transform(transformationMatrix); var redSquarePath = SKPath.ParseSvgPathData("M1 1h10v10H1z"); redSquarePath.Transform(transformationMatrix); var greenSquarePath = SKPath.ParseSvgPathData("M12 1h10v10H12z"); greenSquarePath.Transform(transformationMatrix); var blueSquarePath = SKPath.ParseSvgPathData("M1 12h10v10H1z"); blueSquarePath.Transform(transformationMatrix); var yellowSquarePath = SKPath.ParseSvgPathData("M12 12h10v10H12z"); yellowSquarePath.Transform(transformationMatrix); canvas.DrawPath(backgroundPath, _background); canvas.DrawPath(redSquarePath, _r); canvas.DrawPath(greenSquarePath, _g); canvas.DrawPath(blueSquarePath, _b); canvas.DrawPath(yellowSquarePath, _y); }
/// <summary> /// Configure paint wrapper for using tile brush. /// </summary> /// <param name="paintWrapper">Paint wrapper.</param> /// <param name="targetSize">Target size.</param> /// <param name="tileBrush">Tile brush to use.</param> /// <param name="tileBrushImage">Tile brush image.</param> private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage) { var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize); var intermediate = CreateRenderTarget(calc.IntermediateSize); paintWrapper.AddDisposable(intermediate); using (var context = intermediate.CreateDrawingContext(null)) { var sourceRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(96)); var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_dpi)); context.Clear(Colors.Transparent); context.PushClip(calc.IntermediateClip); context.Transform = calc.IntermediateTransform; context.DrawBitmap( RefCountable.CreateUnownedNotClonable(tileBrushImage), 1, sourceRect, targetRect, tileBrush.BitmapInterpolationMode); context.PopClip(); } var tileTransform = tileBrush.TileMode != TileMode.None ? SKMatrix.CreateTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y) : SKMatrix.CreateIdentity(); SKShaderTileMode tileX = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; SKShaderTileMode tileY = tileBrush.TileMode == TileMode.None ? SKShaderTileMode.Clamp : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY ? SKShaderTileMode.Mirror : SKShaderTileMode.Repeat; var image = intermediate.SnapshotImage(); paintWrapper.AddDisposable(image); var paintTransform = default(SKMatrix); SKMatrix.Concat( ref paintTransform, tileTransform, SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y))); using (var shader = image.ToShader(tileX, tileY, paintTransform)) { paintWrapper.Paint.Shader = shader; } }
public void Pinch(GestureState state, float scale, SKPoint origin) { switch (state) { case GestureState.Started: startPinchMatrix = Matrix; startPinchOrigin = origin; totalPinchScale = 1f; break; case GestureState.Running: totalPinchScale *= scale; var pinchTranslation = origin - startPinchOrigin; var canvasTranslation = SKMatrix.CreateTranslation(pinchTranslation.X, pinchTranslation.Y); var canvasScaling = SKMatrix.CreateScale(totalPinchScale, totalPinchScale, origin.X, origin.Y); var canvasCombined = SKMatrix.Identity; SKMatrix.Concat(ref canvasCombined, ref canvasScaling, ref canvasTranslation); SKMatrix.Concat(ref Matrix, ref canvasCombined, ref startPinchMatrix); break; default: startPinchMatrix = SKMatrix.Identity; startPinchOrigin = SKPoint.Empty; totalPinchScale = 1f; break; } }
private static SKMatrix CreateRotationMatrix(IReadOnlyViewport viewport, MRect rect, SKMatrix priorMatrix) { // The front-end sets up the canvas with a matrix based on screen scaling (e.g. retina). // We need to retain that effect by combining our matrix with the incoming matrix. // We'll create four matrices in addition to the incoming matrix. They perform the // zoom scale, focal point offset, user rotation and finally, centering in the screen. var userRotation = SKMatrix.CreateRotationDegrees((float)viewport.Rotation); var focalPointOffset = SKMatrix.CreateTranslation( (float)(rect.Left - viewport.Center.X), (float)(viewport.Center.Y - rect.Top)); var zoomScale = SKMatrix.CreateScale((float)(1.0 / viewport.Resolution), (float)(1.0 / viewport.Resolution)); var centerInScreen = SKMatrix.CreateTranslation((float)(viewport.Width / 2.0), (float)(viewport.Height / 2.0)); // We'll concatenate them like so: incomingMatrix * centerInScreen * userRotation * zoomScale * focalPointOffset var matrix = SKMatrix.Concat(zoomScale, focalPointOffset); matrix = SKMatrix.Concat(userRotation, matrix); matrix = SKMatrix.Concat(centerInScreen, matrix); matrix = SKMatrix.Concat(priorMatrix, matrix); return(matrix); }
public static void Save(Dictionary <int, ushort> characterToGlyphMap, SKTypeface typeface, float textSize, string fill, string outputDirectory, ZipArchive?zipArchive) { var skColor = new SKColor(0x00, 0x00, 0x00); using var skTextPaint = new SKPaint { IsAntialias = true, Color = skColor, Typeface = typeface, TextEncoding = SKTextEncoding.Utf32, TextSize = textSize, TextAlign = SKTextAlign.Center, LcdRenderText = true, SubpixelText = true }; var metrics = skTextPaint.FontMetrics; var mAscent = metrics.Ascent; var mDescent = metrics.Descent; foreach (var kvp in characterToGlyphMap) { var charCode = kvp.Key; var utf32 = Char.ConvertFromUtf32((int)charCode); float x = 0; float y = (mAscent / 2.0f) - mDescent / 2.0f; using var outlinePath = skTextPaint.GetTextPath(utf32, x, y); using var fillPath = skTextPaint.GetFillPath(outlinePath); fillPath.Transform(SKMatrix.CreateTranslation(-fillPath.Bounds.Left, -fillPath.Bounds.Top)); var bounds = fillPath.Bounds; var svgPathData = fillPath.ToSvgPathData(); var sb = new StringBuilder(); sb.AppendLine($"<svg viewBox=\"{bounds.Left} {bounds.Top} {bounds.Width} {bounds.Height}\" xmlns=\"http://www.w3.org/2000/svg\">"); // width=\"{bounds.Width}\" height=\"{bounds.Height}\" sb.AppendLine($" <path fill=\"{fill}\" d=\"{svgPathData}\"/>"); sb.AppendLine($"</svg>"); var svg = sb.ToString(); var outputPath = Path.Combine(outputDirectory, $"{charCode.ToString("X2").PadLeft(5, '0')}_{typeface.FamilyName}.svg"); if (zipArchive != null) { var zipArchiveEntry = zipArchive.CreateEntry(outputPath); using var streamWriter = new StreamWriter(zipArchiveEntry.Open()); streamWriter.Write(svg); } else { using var streamWriter = File.CreateText(outputPath); streamWriter.Write(svg); } } }
/// <summary> /// Opens the render context using the dimensions of the provided path /// </summary> public void Open(SKPath path, Folder?parent) { if (_disposed) { throw new ObjectDisposedException("Renderer"); } if (IsOpen) { throw new ArtemisCoreException("Cannot open render context because it is already open"); } if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds) || _lastGraphicsContext != Constants.ManagedGraphicsContext?.GraphicsContext) { Invalidate(); } if (!_valid || Surface == null) { SKRect pathBounds = path.Bounds; int width = (int)pathBounds.Width; int height = (int)pathBounds.Height; SKImageInfo imageInfo = new(width, height); if (Constants.ManagedGraphicsContext?.GraphicsContext == null) { Surface = SKSurface.Create(imageInfo); } else { Surface = SKSurface.Create(Constants.ManagedGraphicsContext.GraphicsContext, true, imageInfo); } Path = new SKPath(path); Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1)); TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y); if (parent != null) { TargetLocation -= parent.Bounds.Location; } Surface.Canvas.ClipPath(Path); _lastParentBounds = parent?.Bounds ?? new SKRect(); _lastBounds = path.Bounds; _lastGraphicsContext = Constants.ManagedGraphicsContext?.GraphicsContext; _valid = true; } Paint = new SKPaint(); Surface.Canvas.Clear(); Surface.Canvas.Save(); IsOpen = true; }
public void MatrixCanPostConcat() { var a = SKMatrix.CreateTranslation(10, 20); var b = SKMatrix.CreateTranslation(5, 7); var c = a.PostConcat(b); Assert.Equal(SKMatrix.CreateTranslation(15, 27).Values, c.Values); }
public void MapRectCreatesModifiedRect() { var rect = SKRect.Create(2, 4, 6, 8); var matrix = SKMatrix.CreateTranslation(10, 12); var mapped = matrix.MapRect(rect); Assert.Equal(SKRect.Create(12, 16, 6, 8), mapped); }
/// <summary> /// Updates the particle's position and orientation based on the given time /// </summary> /// <para>Call this method first and then <see cref="Paint"/></para> /// <para>This method doesn't need to be called on the UI/Main thread</para> /// <param name="absoluteElapsedMillis"></param> public virtual void Update(long absoluteElapsedMillis, SKSize scale) { // Determine elapsed time since this particles was created var elapsedMillis = absoluteElapsedMillis - _absoluteElapsedMillisPrevious; if (_absoluteElapsedMillisPrevious == 0) { _absoluteElapsedMillisPrevious = absoluteElapsedMillis; return; } _internalAbsoluteMillis += elapsedMillis; _absoluteElapsedMillisPrevious = absoluteElapsedMillis; // Traversed distance = speed x time var dist = TranslationSpeed * _internalAbsoluteMillis * 0.001; // New position var deg2radFactor = 0.0174533; var angle = Direction * deg2radFactor; Position = InitialPosition + new SKPoint { X = (float)(dist * Math.Cos(angle)), Y = (float)(dist * Math.Sin(angle)) }; TransformationMatrix = SKMatrix.CreateTranslation(-Position.X, -Position.Y); // New Scale TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateScale(scale.Width, scale.Height)); // New Orientation Orientation = InitialOrientation + new SKPoint3 { X = _internalAbsoluteMillis * 0.001f * RotationSpeed.X, Y = _internalAbsoluteMillis * 0.001f * RotationSpeed.Y, Z = _internalAbsoluteMillis * 0.001f * RotationSpeed.Z }; _totalRotationMatrix.SetIdentity(); _xAxisRotationMatrix.SetRotationAboutDegrees(1, 0, 0, Orientation.X); _totalRotationMatrix.PostConcat(_xAxisRotationMatrix); _yAxisRotationMatrix.SetRotationAboutDegrees(0, 1, 0, Orientation.Y); _totalRotationMatrix.PostConcat(_yAxisRotationMatrix); _zAxisRotationMatrix.SetRotationAboutDegrees(0, 0, 1, Orientation.Z); _totalRotationMatrix.PostConcat(_zAxisRotationMatrix); TransformationMatrix = TransformationMatrix.PostConcat(_totalRotationMatrix.Matrix); // Translate back TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateTranslation(Position.X, Position.Y)); }
public static void PerformMirrorOperation(DrawItem tmpItem, float canvasWidth) { float midPoint = canvasWidth / 2.0f; float drawMidXPoint = tmpItem.Path.Bounds.MidX; float x = (midPoint - drawMidXPoint) * 2; SKMatrix translateXaxis = SKMatrix.CreateTranslation(x, 0); tmpItem.Path.Transform(translateXaxis); }
private static void RenderVisual(SKSurface surface, SKImageInfo info, Visual visual) { if (visual.Opacity != 0) { surface.Canvas.Save(); var visualMatrix = surface.Canvas.TotalMatrix; visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.Offset.X, visual.Offset.Y)); if (visual.RotationAngleInDegrees != 0) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(visual.RotationAngleInDegrees, visual.CenterPoint.X, visual.CenterPoint.Y)); } if (visual.TransformMatrix != Matrix4x4.Identity) { visualMatrix = visualMatrix.PreConcat(visual.TransformMatrix.ToSKMatrix44().Matrix); } surface.Canvas.SetMatrix(visualMatrix); if (visual.Clip is InsetClip insetClip) { surface.Canvas.ClipRect(new SKRect { Top = insetClip.TopInset, Bottom = insetClip.BottomInset, Left = insetClip.LeftInset, Right = insetClip.RightInset }); } visual.Render(surface, info); switch (visual) { case SpriteVisual spriteVisual: foreach (var inner in spriteVisual.Children) { RenderVisual(surface, info, inner); } break; case ContainerVisual containerVisual: foreach (var inner in containerVisual.Children) { RenderVisual(surface, info, inner); } break; } surface.Canvas.Restore(); } }
public virtual void Update(SKCanvas canvas, long absoluteElapsedMillis) { var elapsedMillis = absoluteElapsedMillis - _absoluteElapsedMillisPrevious; if (_absoluteElapsedMillisPrevious == 0) { _absoluteElapsedMillisPrevious = absoluteElapsedMillis; return; } _internalAbsoluteMillis += elapsedMillis; _absoluteElapsedMillisPrevious = absoluteElapsedMillis; canvas.Save(); // Traversed distance = speed x time var dist = TranslationSpeed * _internalAbsoluteMillis * 0.001; // New position var deg2radFactor = 0.0174533; var angle = Direction * deg2radFactor; Position = InitialPosition + new SKPoint { X = (float)(dist * Math.Cos(angle)), Y = (float)(dist * Math.Sin(angle)) }; var matrix = SKMatrix.CreateTranslation(-Position.X, -Position.Y); // New Orientation Orientation = InitialOrientation + new SKPoint3 { X = _internalAbsoluteMillis * 0.001f * RotationSpeed.X, Y = _internalAbsoluteMillis * 0.001f * RotationSpeed.Y, Z = _internalAbsoluteMillis * 0.001f * RotationSpeed.Z }; var matrix44 = SKMatrix44.CreateIdentity(); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, Orientation.X)); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, Orientation.Y)); matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, Orientation.Z)); // Apply transforms matrix = matrix.PostConcat(matrix44.Matrix); matrix = matrix.PostConcat(SKMatrix.CreateTranslation(Position.X, Position.Y)); canvas.SetMatrix(matrix); Draw(canvas); canvas.Restore(); }
SKMatrix CreateMatrix() { SKMatrix matrix = SKMatrix.CreateIdentity(); SKRect drawableBounds = _drawableBounds; float halfStrokeWidth = _skPaint.StrokeWidth / 2; drawableBounds.Left += halfStrokeWidth; drawableBounds.Top += halfStrokeWidth; drawableBounds.Right -= halfStrokeWidth; drawableBounds.Bottom -= halfStrokeWidth; float widthScale = drawableBounds.Width / _pathFillBounds.Width; float heightScale = drawableBounds.Height / _pathFillBounds.Height; switch (_stretch) { case Stretch.None: drawableBounds = _drawableBounds; float adjustX = Math.Min(0, _pathStrokeBounds.Left); float adjustY = Math.Min(0, _pathStrokeBounds.Top); if (adjustX < 0 || adjustY < 0) { matrix = SKMatrix.CreateTranslation(-adjustX, -adjustY); } break; case Stretch.Fill: matrix = SKMatrix.CreateScale(widthScale, heightScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - widthScale * _pathFillBounds.Left, drawableBounds.Top - heightScale * _pathFillBounds.Top)); break; case Stretch.Uniform: float minScale = Math.Min(widthScale, heightScale); matrix = SKMatrix.CreateScale(minScale, minScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - (minScale * _pathFillBounds.Left) + (drawableBounds.Width - (minScale * _pathFillBounds.Width)) / 2, drawableBounds.Top - (minScale * _pathFillBounds.Top) + (drawableBounds.Height - (minScale * _pathFillBounds.Height)) / 2)); break; case Stretch.UniformToFill: float maxScale = Math.Max(widthScale, heightScale); matrix = SKMatrix.CreateScale(maxScale, maxScale); matrix = matrix.PostConcat( SKMatrix.CreateTranslation(drawableBounds.Left - (maxScale * _pathFillBounds.Left), drawableBounds.Top - (maxScale * _pathFillBounds.Top))); break; } return(matrix); }
/** * <summary>Expands the size of this quad stretching around its center.</summary> * <param name="valueX">Expansion's horizontal extent.</param> * <param name="valueY">Expansion's vertical extent.</param> * <returns>This quad.</returns> */ public Quad Inflate(float valueX, float valueY) { SKRect oldBounds = GetBounds(); var matrix = SKMatrix.CreateTranslation(oldBounds.MidX, oldBounds.MidY); matrix = matrix.PreConcat(SKMatrix.CreateScale(1 + valueX * 2 / oldBounds.Width, 1 + valueY * 2 / oldBounds.Height)); matrix = matrix.PreConcat(SKMatrix.CreateTranslation(-(oldBounds.MidX), -(oldBounds.MidY))); pointTopLeft = matrix.MapPoint(pointTopLeft); pointTopRight = matrix.MapPoint(pointTopRight); pointBottomRight = matrix.MapPoint(pointBottomRight); pointBottomLeft = matrix.MapPoint(pointBottomLeft); return(this); }
private protected SKMatrix CreateTransformMatrix(SKRect bounds) { var transform = SKMatrix.Identity; // Translate to origin if (CenterPoint != Vector2.Zero) { transform = SKMatrix.CreateTranslation(-CenterPoint.X, -CenterPoint.Y); } // Scaling if (Scale != Vector2.One) { transform = transform.PostConcat(SKMatrix.CreateScale(Scale.X, Scale.Y)); } // Rotating if (RotationAngle != 0) { transform = transform.PostConcat(SKMatrix.CreateRotation(RotationAngle)); } // Translating if (Offset != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(Offset.X, Offset.Y)); } // Translate back if (CenterPoint != Vector2.Zero) { transform = transform.PostConcat(SKMatrix.CreateTranslation(CenterPoint.X, CenterPoint.Y)); } if (!TransformMatrix.IsIdentity) { transform = transform.PostConcat(TransformMatrix.ToSKMatrix()); } var relativeTransform = RelativeTransformMatrix.IsIdentity ? SKMatrix.Identity : RelativeTransformMatrix.ToSKMatrix(); if (!relativeTransform.IsIdentity) { relativeTransform.TransX *= bounds.Width; relativeTransform.TransY *= bounds.Height; transform = transform.PostConcat(relativeTransform); } return(transform); }
protected override void Draw(SKCanvas canvas) { var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 8.0f, Position.Y - 8.0f); var scale = 6.0f / Size.Width; transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y)); var backgroundPath = SKPath.ParseSvgPathData( "M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z"); backgroundPath.Transform(transformationMatrix); canvas.DrawPath(backgroundPath, _paint); }
public override void PrepareMatrixOffset(bool inverted) { if (!inverted) { MatrixOffset = SKMatrix.Identity.PostConcat(SKMatrix.CreateTranslation(ViewPortHandler.OffsetLeft, ViewPortHandler.ChartHeight - ViewPortHandler.OffsetBottom)); } else { MatrixOffset = SKMatrix .CreateTranslation(ViewPortHandler.OffsetRight - ViewPortHandler.ChartWidth, ViewPortHandler.ChartHeight - ViewPortHandler.OffsetTop) .PostConcat(SKMatrix.CreateScale(-1f, 1f)); } }
/// <summary> /// 单指操纵 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { if (Mode == TouchManipulationMode.None) { return(SKMatrix.CreateIdentity()); } SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint delta = newPoint - prevPoint; if (Mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation { SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; float scale = Magnitude(newVector) / Magnitude(oldVector); // Avoid rotation if fingers are too close to center if (Magnitude(newVector) > 30 && Magnitude(oldVector) > 30) { float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - prevAngle; touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y); // Effectively rotate the old vector float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector); oldVector.X = magnitudeRatio * newVector.X; oldVector.Y = magnitudeRatio * newVector.Y; // Recalculate delta delta = newVector - oldVector; } if (!float.IsNaN(scale) && !float.IsInfinity(scale)) { var tm = SKMatrix.CreateScale(scale, scale, pivotPoint.X, pivotPoint.Y); touchMatrix.PostConcat(tm); } } // Multiply the rotation matrix by a translation matrix touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y)); return(touchMatrix); }
private void RenderVisual(SKSurface surface, SKImageInfo info, Visual visual) { if (visual.Opacity != 0 && visual.IsVisible) { surface.Canvas.Save(); var visualMatrix = surface.Canvas.TotalMatrix; visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.Offset.X, visual.Offset.Y)); visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.AnchorPoint.X, visual.AnchorPoint.Y)); if (visual.RotationAngleInDegrees != 0) { visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(visual.RotationAngleInDegrees, visual.CenterPoint.X, visual.CenterPoint.Y)); } if (visual.TransformMatrix != Matrix4x4.Identity) { visualMatrix = visualMatrix.PreConcat(visual.TransformMatrix.ToSKMatrix44().Matrix); } surface.Canvas.SetMatrix(visualMatrix); ApplyClip(surface, visual); using var opacityDisposable = PushOpacity(visual.Opacity); visual.Render(surface, info); switch (visual) { case SpriteVisual spriteVisual: foreach (var inner in spriteVisual.Children) { RenderVisual(surface, info, inner); } break; case ContainerVisual containerVisual: foreach (var inner in containerVisual.Children) { RenderVisual(surface, info, inner); } break; } surface.Canvas.Restore(); } }
public void CanTransform() { var radii = new[] { new SKPoint(5, 5), new SKPoint(5, 5), new SKPoint(5, 5), new SKPoint(5, 5) }; var rect = SKRect.Create(10, 10, 100, 100); var offset = rect; offset.Offset(2, 2); var rrect = new SKRoundRect(rect, 5, 5); var transformed = rrect.Transform(SKMatrix.CreateTranslation(2, 2)); Assert.Equal(offset, transformed.Rect); Assert.Equal(radii, transformed.Radii); }
public static MaskDrawable Create(SvgMask svgMask, SKRect skViewport, DrawableBase?parent, IAssetLoader assetLoader, HashSet <Uri>?references, DrawAttributes ignoreAttributes = DrawAttributes.None) { var drawable = new MaskDrawable(assetLoader, references) { Element = svgMask, Parent = parent, IgnoreAttributes = ignoreAttributes, IsDrawable = true }; if (!drawable.IsDrawable) { return(drawable); } var maskUnits = svgMask.MaskUnits; var maskContentUnits = svgMask.MaskContentUnits; var xUnit = svgMask.X; var yUnit = svgMask.Y; var widthUnit = svgMask.Width; var heightUnit = svgMask.Height; // TODO: Pass correct skViewport var skRectTransformed = SvgExtensions.CalculateRect(xUnit, yUnit, widthUnit, heightUnit, maskUnits, skViewport, skViewport, svgMask); if (skRectTransformed is null) { drawable.IsDrawable = false; return(drawable); } var skMatrix = SKMatrix.CreateIdentity(); if (maskContentUnits == SvgCoordinateUnits.ObjectBoundingBox) { var skBoundsTranslateTransform = SKMatrix.CreateTranslation(skViewport.Left, skViewport.Top); skMatrix = skMatrix.PreConcat(skBoundsTranslateTransform); var skBoundsScaleTransform = SKMatrix.CreateScale(skViewport.Width, skViewport.Height); skMatrix = skMatrix.PreConcat(skBoundsScaleTransform); } drawable.CreateChildren(svgMask, skViewport, drawable, assetLoader, references, ignoreAttributes); drawable.Initialize(skRectTransformed.Value, skMatrix); return(drawable); }
/// <summary> /// Opens the render context using the dimensions of the provided path /// </summary> public void Open(SKPath path, Folder?parent) { if (_disposed) { throw new ObjectDisposedException("Renderer"); } if (IsOpen) { throw new ArtemisCoreException("Cannot open render context because it is already open"); } if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds)) { Invalidate(); } if (!_valid || Canvas == null) { SKRect pathBounds = path.Bounds; int width = (int)pathBounds.Width; int height = (int)pathBounds.Height; Bitmap = new SKBitmap(width, height); Path = new SKPath(path); Canvas = new SKCanvas(Bitmap); Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1)); TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y); if (parent != null) { TargetLocation -= parent.Bounds.Location; } Canvas.ClipPath(Path); _lastParentBounds = parent?.Bounds ?? new SKRect(); _lastBounds = path.Bounds; _valid = true; } Paint = new SKPaint(); Canvas.Clear(); Canvas.Save(); IsOpen = true; }