static SKMatrix Multiply(SKMatrix first, SKMatrix second) { SKMatrix target = SKMatrix.CreateIdentity(); SKMatrix.Concat(ref target, first, second); return(target); }
/// <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; } }
/// <summary> /// Resets all zooming and dragging and makes the chart fit exactly it's /// bounds. /// </summary> /// <returns></returns> public SKMatrix FitScreen() { minScaleX = 1.0f; minScaleY = 1.0f; return(SKMatrix.CreateIdentity()); }
public static SKMatrix ToSkia(this Transform transform) { SKMatrix skMatrix = SKMatrix.CreateIdentity(); if (transform == null) { return(skMatrix); } Matrix matrix = transform.Value; skMatrix.Values = new float[] { (float)matrix.M11, (float)matrix.M21, Forms.ConvertToScaledPixel(matrix.OffsetX), (float)matrix.M12, (float)matrix.M22, Forms.ConvertToScaledPixel(matrix.OffsetY), 0, 0, 1 }; return(skMatrix); }
private void Manipulate() { TouchManipulationInfo[] infos = new TouchManipulationInfo[touchDictionary.Count]; touchDictionary.Values.CopyTo(infos, 0); SKMatrix touchMatrix = SKMatrix.CreateIdentity(); if (infos.Length == 1 && Type != BitmapType.Main) { SKPoint prevPoint = infos[0].PreviousPoint; SKPoint newPoint = infos[0].NewPoint; SKPoint pivotPoint = Matrix.MapPoint(Bitmap.Width / 2, Bitmap.Height / 2); touchMatrix = TouchManager.OneFingerManipulate(prevPoint, newPoint, pivotPoint); } else if (infos.Length >= 2) { int pivotIndex = infos[0].NewPoint == infos[0].PreviousPoint ? 0 : 1; SKPoint pivotPoint = infos[pivotIndex].NewPoint; SKPoint newPoint = infos[1 - pivotIndex].NewPoint; SKPoint prevPoint = infos[1 - pivotIndex].PreviousPoint; touchMatrix = TouchManager.TwoFingerManipulate(prevPoint, newPoint, pivotPoint); } SKMatrix matrix = Matrix; matrix.PostConcat(touchMatrix); Matrix = matrix; }
public void Reset() { _rotatedDegrees = 0; Matrix = SKMatrix.CreateIdentity(); CanvasView?.InvalidateSurface(); }
public DesignCanvasView() { InitializeComponent(); Matrix = SKMatrix.CreateIdentity(); Touches = new Dictionary <long, SKPoint>(); CanvasView.PaintSurface += OnCanvasViewPaintSurface; }
internal TouchManipulationBitmap(SKBitmap bitmap, BitmapType type, string text, SKColor color = default) { Matrix = SKMatrix.CreateIdentity(); Bitmap = bitmap; Type = type; Color = color; Text = text; }
public TouchManipulationBitmap(SKBitmap bitmap) { this.bitmap = bitmap; Matrix = SKMatrix.CreateIdentity(); TouchManager = new TouchManipulationManager { Mode = TouchManipulationMode.ScaleRotate }; }
public static SKMatrix RadianToMatrix(double radian) { SKMatrix newMatrix = SKMatrix.CreateIdentity(); newMatrix.ScaleX = (float)Math.Cos(radian); newMatrix.ScaleY = newMatrix.ScaleX; newMatrix.SkewY = (float)Math.Sin(radian); newMatrix.SkewX = -newMatrix.SkewY; return(newMatrix); }
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); }
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args) { base.OnPaintSurface(args); SKImageInfo info = args.Info; SKSurface surface = skSurface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(SKColors.Gray); // Calculate rectangle for displaying bitmap float scale = Math.Min((float)info.Width / bitmap.Width, (float)info.Height / bitmap.Height); float x = (info.Width - scale * bitmap.Width) / 2; float y = (info.Height - scale * bitmap.Height) / 2; SKRect bitmapRect = new SKRect(x, y, x + scale * bitmap.Width, y + scale * bitmap.Height); canvas.DrawBitmap(bitmap, bitmapRect); // Calculate a matrix transform for displaying the cropping rectangle SKMatrix bitmapScaleMatrix = SKMatrix.CreateIdentity(); bitmapScaleMatrix.SetScaleTranslate(scale, scale, x, y); // Display rectangle SKRect scaledCropRect = bitmapScaleMatrix.MapRect(croppingRect.Rect); canvas.DrawRect(scaledCropRect, edgeStroke); // Display heavier corners using (SKPath path = new SKPath()) { path.MoveTo(scaledCropRect.Left, scaledCropRect.Top + CORNER); path.LineTo(scaledCropRect.Left, scaledCropRect.Top); path.LineTo(scaledCropRect.Left + CORNER, scaledCropRect.Top); path.MoveTo(scaledCropRect.Right - CORNER, scaledCropRect.Top); path.LineTo(scaledCropRect.Right, scaledCropRect.Top); path.LineTo(scaledCropRect.Right, scaledCropRect.Top + CORNER); path.MoveTo(scaledCropRect.Right, scaledCropRect.Bottom - CORNER); path.LineTo(scaledCropRect.Right, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Right - CORNER, scaledCropRect.Bottom); path.MoveTo(scaledCropRect.Left + CORNER, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Left, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Left, scaledCropRect.Bottom - CORNER); canvas.DrawPath(path, cornerStroke); } // Invert the transform for touch tracking bitmapScaleMatrix.TryInvert(out inverseBitmapMatrix); }
private SKMatrix ComputeMatrix(SKSize size, SKPoint ptUL, SKPoint ptUR, SKPoint ptLL, SKPoint?ptLR = null) { // Scale transform SKMatrix S = SKMatrix.CreateScale(1 / size.Width, 1 / size.Height); // Affine transform SKMatrix A = new SKMatrix { ScaleX = ptUR.X - ptUL.X, SkewY = ptUR.Y - ptUL.Y, SkewX = ptLL.X - ptUL.X, ScaleY = ptLL.Y - ptUL.Y, TransX = ptUL.X, TransY = ptUL.Y, Persp2 = 1 }; // Non-Affine transform SKMatrix N = SKMatrix.CreateIdentity(); if (ptLR.HasValue) { SKMatrix inverseA; A.TryInvert(out inverseA); SKPoint abPoint = inverseA.MapPoint(ptLR.Value); float a = abPoint.X; float b = abPoint.Y; float scaleX = a / (a + b - 1); float scaleY = b / (a + b - 1); N = new SKMatrix { ScaleX = scaleX, ScaleY = scaleY, Persp0 = scaleX - 1, Persp1 = scaleY - 1, Persp2 = 1 }; } // Multiply S * N * A SKMatrix result = SKMatrix.CreateIdentity(); SKMatrix.PostConcat(ref result, S); SKMatrix.PostConcat(ref result, N); SKMatrix.PostConcat(ref result, A); return(result); }
private SKMatrix GetScaleMatrix(SKPoint center, float radiusX, float radiusY) { if (radiusX > radiusY) { return(SKMatrix.CreateScale(radiusX / radiusY, 1f, center.X, center.Y)); } if (radiusY > radiusX) { return(SKMatrix.CreateScale(1f, radiusY / radiusX, center.X, center.Y)); } return(SKMatrix.CreateIdentity()); }
/// <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); }
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> /// 2本指での操作 /// </summary> /// <param name="prevPoint"></param> /// <param name="newPoint"></param> /// <param name="pivotPoint"></param> /// <returns></returns> public SKMatrix TwoFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint) { SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = newPoint - pivotPoint; if (Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { // Find angles from pivot point to touch points float oldAngle = (float)Math.Atan2(oldVector.Y, oldVector.X); float newAngle = (float)Math.Atan2(newVector.Y, newVector.X); // Calculate rotation matrix float angle = newAngle - oldAngle; 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; } float scaleX = 1; float scaleY = 1; if (Mode == TouchManipulationMode.AnisotropicScale) { scaleX = newVector.X / oldVector.X; scaleY = newVector.Y / oldVector.Y; } else if (Mode == TouchManipulationMode.IsotropicScale || Mode == TouchManipulationMode.ScaleRotate || Mode == TouchManipulationMode.ScaleDualRotate) { scaleX = scaleY = Magnitude(newVector) / Magnitude(oldVector); } if (!float.IsNaN(scaleX) && !float.IsInfinity(scaleX) && !float.IsNaN(scaleY) && !float.IsInfinity(scaleY)) { //SKMatrix.PostConcat(ref touchMatrix, // SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); touchMatrix = touchMatrix.PostConcat(SKMatrix.CreateScale(scaleX, scaleY, pivotPoint.X, pivotPoint.Y)); } return(touchMatrix); }
void DrawRotatedWithMatrices(SKCanvas canvas, SKPath path, SKPaint fill, SKPaint outline, ChartData item, float degrees, int cx, int cy) { var identity = SKMatrix.CreateIdentity(); var translate = SKMatrix.CreateTranslation(-cx, -cy); var rotate = SKMatrix.CreateRotationDegrees(degrees); //angleBox.Text = degrees.ToString(); var translate2 = SKMatrix.CreateTranslation(cx, cy); SKMatrix.PostConcat(ref identity, translate); SKMatrix.PostConcat(ref identity, rotate); SKMatrix.PostConcat(ref identity, translate2); path.Transform(identity); canvas.DrawPath(path, fill); canvas.DrawPath(path, outline); }
public static SKMatrix CaculateOneFingerDraggedMatrix(SKPoint prevPoint, SKPoint curPoint, SKPoint pivotPoint, TouchManipulationMode mode) { if (mode == TouchManipulationMode.None) { return(SKMatrix.CreateIdentity()); } SKMatrix touchMatrix = SKMatrix.CreateIdentity(); SKPoint delta = curPoint - prevPoint; if (mode == TouchManipulationMode.ScaleDualRotate) // One-finger rotation { SKPoint oldVector = prevPoint - pivotPoint; SKPoint newVector = curPoint - pivotPoint; // Avoid rotation if fingers are too close to center if (Magnitude(newVector) > 25 && Magnitude(oldVector) > 25) { 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; } } // Multiply the rotation matrix by a translation matrix touchMatrix = touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y)); return(touchMatrix); }
private void PanGestureRecognizer_PanUpdated(object sender, PanUpdatedEventArgs e) { Debug.WriteLine($"e.PanUpdate = {e.TotalX} - {e.TotalY}"); switch (e.StatusType) { case GestureStatus.Started: isMoving = true; startMatrix = currentmatrix; scaleMatrix = SKMatrix.CreateIdentity(); break; case GestureStatus.Running: translationMatrix = SKMatrix.CreateTranslation((float)e.TotalX * translationSpeedUp, (float)e.TotalY * translationSpeedUp); canvasView.InvalidateSurface(); break; case GestureStatus.Canceled: case GestureStatus.Completed: isMoving = false; break; } }
private void Load(Stream stream) { var matrix = SKMatrix.CreateIdentity(); Dictionary <int, SKMatrix> stack = new Dictionary <int, SKMatrix>(); using (var reader = XmlReader.Create(stream)) { while (reader.Read()) { if (reader.NodeType == XmlNodeType.EndElement) { if (stack.TryGetValue(reader.Depth, out var stackMatrix)) { stack.Remove(reader.Depth); matrix = stackMatrix; } } else if (reader.NodeType == XmlNodeType.Element) { if (string.Equals(reader.Name, "svg", StringComparison.Ordinal)) { var preserveAspectRatio = reader["preserveAspectRatio"]; // get the SVG dimensions var viewBoxA = reader["viewBox"] ?? reader["viewPort"]; if (viewBoxA != null) { ViewBox = ReadRectangle(viewBoxA); } var widthA = reader["width"]; var heightA = reader["height"]; var width = ReadNumber(widthA); var height = ReadNumber(heightA); var size = new SKSize(width, height); if (widthA == null) { size.Width = ViewBox.Width; } else if (widthA.IndexOf('%') > -1) { size.Width *= ViewBox.Width; } if (heightA == null) { size.Height = ViewBox.Height; } else if (heightA != null && heightA.IndexOf('%') > -1) { size.Height *= ViewBox.Height; } CanvasSize = size; if (!ViewBox.IsEmpty && (ViewBox.Width != CanvasSize.Width || ViewBox.Height != CanvasSize.Height)) { if (preserveAspectRatio == "none") { matrix = matrix.PostConcat(SKMatrix.CreateScale(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height)); } else { // TODO: just center scale for now var scale = Math.Min(CanvasSize.Width / ViewBox.Width, CanvasSize.Height / ViewBox.Height); var centered = SKRect.Create(CanvasSize).AspectFit(ViewBox.Size); matrix = matrix.PostConcat(SKMatrix.CreateTranslation(centered.Left, centered.Top)) .PostConcat(SKMatrix.CreateScale(scale, scale)); } } // translate the canvas by the viewBox origin matrix = matrix.PostConcat(SKMatrix.CreateTranslation(-ViewBox.Left, -ViewBox.Top)); } else { var transform = reader["transform"]; if (transform != null) { stack[reader.Depth] = matrix; var trMatrix = ReadTransform(transform); matrix = matrix.PostConcat(trMatrix); } if (string.Equals(reader.Name, "path", StringComparison.Ordinal)) { var pathData = reader["d"]; using (var path = SKPath.ParseSvgPathData(pathData)) Path.AddPath(path, ref matrix); } else if (string.Equals(reader.Name, "polyline", StringComparison.Ordinal)) { var pathData = "M" + reader["points"]; using (var path = SKPath.ParseSvgPathData(pathData)) Path.AddPath(path, ref matrix); } else if (string.Equals(reader.Name, "polygon", StringComparison.Ordinal)) { var pathData = "M" + reader["points"] + " Z"; using (var path = SKPath.ParseSvgPathData(pathData)) Path.AddPath(path, ref matrix); } else if (string.Equals(reader.Name, "line", StringComparison.Ordinal)) { var x1 = ReadNumber(reader["x1"]); var x2 = ReadNumber(reader["x2"]); var y1 = ReadNumber(reader["y1"]); var y2 = ReadNumber(reader["y2"]); using (var path = new SKPath()) { path.MoveTo(x1, y1); path.LineTo(x2, y2); Path.AddPath(path, ref matrix); } } else if (string.Equals(reader.Name, "circle", StringComparison.Ordinal)) { var cx = ReadNumber(reader["cx"]); var cy = ReadNumber(reader["cy"]); var rr = ReadNumber(reader["r"]); using (var path = new SKPath()) { path.AddCircle(cx, cy, rr); Path.AddPath(path, ref matrix); } } else if (string.Equals(reader.Name, "ellipse", StringComparison.Ordinal)) { var cx = ReadNumber(reader["cx"]); var cy = ReadNumber(reader["cy"]); var rx = ReadNumber(reader["rx"]); var ry = ReadNumber(reader["ry"]); using (var path = new SKPath()) { path.AddOval(new SKRect(cx, cy, rx, ry)); Path.AddPath(path, ref matrix); } } else if (string.Equals(reader.Name, "rect", StringComparison.Ordinal)) { var x = ReadNumber(reader["x"]); var y = ReadNumber(reader["y"]); var width = ReadNumber(reader["width"]); var height = ReadNumber(reader["height"]); var rx = ReadOptionalNumber(reader["rx"]); var ry = ReadOptionalNumber(reader["ry"]); var rect = SKRect.Create(x, y, width, height); using (var path = new SKPath()) { if (rx != null) { path.AddRoundRect(rect, rx ?? 0, ry ?? 0); } else { path.AddRect(rect); } Path.AddPath(path, ref matrix); } } } } } } }
protected override void OnPaintSurface(SKPaintSurfaceEventArgs args) { base.OnPaintSurface(args); SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(SkiaHelper.backgroundColor); // 计算显示位图的矩形 var rect = SkiaHelper.CalculateRectangle(new SKRect(0, 0, info.Width, info.Height), bitmap); canvas.DrawBitmap(bitmap, rect.rect); // 计算用于显示裁剪矩形的矩阵变换 SKMatrix bitmapScaleMatrix = SKMatrix.CreateIdentity(); SKMatrix.CreateScaleTranslation(rect.scaleX, rect.scaleX, rect.rect.Left, rect.rect.Top); // 显示矩形 SKRect scaledCropRect = bitmapScaleMatrix.MapRect(croppingRect.Rect); using (SKPaint edgeStroke = new SKPaint()) { edgeStroke.Style = SKPaintStyle.Stroke; edgeStroke.Color = SKColors.White; edgeStroke.StrokeWidth = 3; edgeStroke.IsAntialias = true; canvas.DrawRect(scaledCropRect, edgeStroke); } canvas.DrawSurrounding(rect.rect, scaledCropRect, SKColors.Gray.WithAlpha(190)); // Display heavier corners using (SKPaint cornerStroke = new SKPaint()) using (SKPath path = new SKPath()) { cornerStroke.Style = SKPaintStyle.Stroke; cornerStroke.Color = SKColors.White; cornerStroke.StrokeWidth = 7; path.MoveTo(scaledCropRect.Left, scaledCropRect.Top + corner); path.LineTo(scaledCropRect.Left, scaledCropRect.Top); path.LineTo(scaledCropRect.Left + corner, scaledCropRect.Top); path.MoveTo(scaledCropRect.Right - corner, scaledCropRect.Top); path.LineTo(scaledCropRect.Right, scaledCropRect.Top); path.LineTo(scaledCropRect.Right, scaledCropRect.Top + corner); path.MoveTo(scaledCropRect.Right, scaledCropRect.Bottom - corner); path.LineTo(scaledCropRect.Right, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Right - corner, scaledCropRect.Bottom); path.MoveTo(scaledCropRect.Left + corner, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Left, scaledCropRect.Bottom); path.LineTo(scaledCropRect.Left, scaledCropRect.Bottom - corner); canvas.DrawPath(path, cornerStroke); } // 反转变换以进行触摸跟踪 bitmapScaleMatrix.TryInvert(out inverseBitmapMatrix); }