public static SKMatrix BuildTransformMatrix(string Transform) { var Output = SKMatrix.MakeIdentity(); char[] delim = { ',', ' ', '(', ')' }; var v_s = Transform.Split(delim, StringSplitOptions.RemoveEmptyEntries); if (v_s.Length == 0) { throw (new Exception("Malformed transform.")); } //Get the name of the transform type int i = 0; var Type = v_s[i++].ToLower(); //Switch to correct transform type switch (Type) { case "matrix": var a = float.Parse(v_s[i++]); var b = float.Parse(v_s[i++]); var c = float.Parse(v_s[i++]); var d = float.Parse(v_s[i++]); var e = float.Parse(v_s[i++]); var f = float.Parse(v_s[i++]); Output.ScaleX = a; Output.ScaleY = d; Output.SkewX = c; Output.SkewY = b; Output.TransX = e; Output.TransY = f; break; case "translate": var tx = float.Parse(v_s[i++]); var ty = 0.0f; if (i < v_s.Length) { ty = float.Parse(v_s[i++]); } // Output = SKMatrix.MakeTranslation(tx, ty); break; case "scale": var sx = float.Parse(v_s[i++]); var sy = 0.0f; if (i < v_s.Length) { sy = float.Parse(v_s[i++]); } // Output = SKMatrix.MakeScale(sx, sy); break; case "rotate": // var angle = float.Parse(v_s[i++]); // var cx = 0.0f; if (i < v_s.Length) { cx = float.Parse(v_s[i++]); } // var cy = 0.0f; if (i < v_s.Length) { cy = float.Parse(v_s[i++]); } // Output = SKMatrix.MakeRotationDegrees(angle, cx, cy); break; case "skewX": var sk_x_angle = float.Parse(v_s[i++]); var anglx_radians = ((float)Math.PI / 180.0f) * sk_x_angle; Output = SKMatrix.MakeSkew((float)Math.Tan(anglx_radians), 0); break; case "skewY": var sk_y_angle = float.Parse(v_s[i++]); var angly_radians = ((float)Math.PI / 180.0f) * sk_y_angle; Output = SKMatrix.MakeSkew(0, (float)Math.Tan(angly_radians)); break; } ; // SVG always have these settings Output.Persp0 = 0; Output.Persp1 = 0; Output.Persp2 = 1; return(Output); }
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args) { SKImageInfo info = args.Info; SKSurface surface = args.Surface; SKCanvas canvas = surface.Canvas; canvas.Clear(); float xCenter = info.Width / 2; float yCenter = info.Height / 2; float radius = 0.24f * Math.Min(info.Width, info.Height); using (SKRegion wholeScreenRegion = new SKRegion()) { wholeScreenRegion.SetRect(new SKRectI(0, 0, info.Width, info.Height)); using (SKRegion leftRegion = new SKRegion(wholeScreenRegion)) using (SKRegion rightRegion = new SKRegion(wholeScreenRegion)) using (SKRegion topRegion = new SKRegion(wholeScreenRegion)) using (SKRegion bottomRegion = new SKRegion(wholeScreenRegion)) { using (SKPath circlePath = new SKPath()) { // Make basic circle path circlePath.AddCircle(xCenter, yCenter, radius); // Left leaf circlePath.Transform(SKMatrix.MakeTranslation(-radius, 0)); leftRegion.SetPath(circlePath); // Right leaf circlePath.Transform(SKMatrix.MakeTranslation(2 * radius, 0)); rightRegion.SetPath(circlePath); // Make union of right with left leftRegion.Op(rightRegion, SKRegionOperation.Union); // Top leaf circlePath.Transform(SKMatrix.MakeTranslation(-radius, -radius)); topRegion.SetPath(circlePath); // Combine with bottom leaf circlePath.Transform(SKMatrix.MakeTranslation(0, 2 * radius)); bottomRegion.SetPath(circlePath); // Make union of top with bottom bottomRegion.Op(topRegion, SKRegionOperation.Union); // Exclusive-OR left and right with top and bottom leftRegion.Op(bottomRegion, SKRegionOperation.XOR); // Set that as clip region canvas.ClipRegion(leftRegion); // Set transform for drawing lines from center canvas.Translate(xCenter, yCenter); // Draw 360 lines for (double angle = 0; angle < 360; angle++) { float x = 2 * radius * (float)Math.Cos(Math.PI * angle / 180); float y = 2 * radius * (float)Math.Sin(Math.PI * angle / 180); using (SKPaint strokePaint = new SKPaint()) { strokePaint.Color = SKColors.Green; strokePaint.StrokeWidth = 2; canvas.DrawLine(0, 0, x, y, strokePaint); } } } } } }
/// <summary> /// Get arrow path for the specified annotation position /// </summary> /// <param name="graphics"></param> /// <param name="position"></param> /// <returns></returns> private SKPath GetArrowPath( ChartGraphics graphics, SKRect position) { // Get absolute position SKRect positionAbs = graphics.GetAbsoluteRectangle(position); SKPoint firstPoint = positionAbs.Location; SKPoint secondPoint = new(positionAbs.Right, positionAbs.Bottom); // Calculate arrow length float deltaX = secondPoint.X - firstPoint.X; float deltaY = secondPoint.Y - firstPoint.Y; float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY); // Create unrotated graphics path for the arrow started at the annotation location // and going to the right for the length of the rotated arrow. SKPath path = new(); float pointerRatio = 2.1f; SKPoint[] points; if (ArrowStyle == ArrowStyle.Simple) { points = new SKPoint[] { firstPoint, new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize), new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize), new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio) }; } else if (ArrowStyle == ArrowStyle.DoubleArrow) { points = new SKPoint[] { firstPoint, new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize), new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize), new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio), new SKPoint(firstPoint.X + arrowLength, firstPoint.Y), new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio), new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio) }; } else if (ArrowStyle == ArrowStyle.Tailed) { float tailRatio = 2.1f; points = new SKPoint[] { firstPoint, new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize), new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize * tailRatio), new SKPoint(firstPoint.X + arrowLength - ArrowSize * tailRatio, firstPoint.Y), new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize * tailRatio), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize), new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio) }; } else { throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown)); } path.AddLines(points); path.Close(); // Calculate arrow angle float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI); if (deltaX < 0) { angle += 180f; } // Rotate arrow path around the first point SKMatrix matrix = SKMatrix.CreateRotationDegrees(angle, firstPoint.X, firstPoint.Y); path.Transform(matrix); return(path); }
public static SKMatrix Invert(this SKMatrix m) { m.TryInvert(out var m2); return(m2); }
public void UpdateTransform(SKMatrix transform) { UpdateShapeTransform(transform); }
// Every 1/60th second, update bitmap with user drawings bool OnTimerTick() { if (bitmap == null) { return(true); } // Determine the current color. float tColor = stopwatch.ElapsedMilliseconds % 10000 / 10000f; fingerPaint.Color = SKColor.FromHsl(360 * tColor, 100, 50); titleLabel.TextColor = fingerPaint.Color.ToFormsColor(); // Determine the rotation angle. float tAngle = stopwatch.ElapsedMilliseconds % 5000 / 5000f; angle = 360 * tAngle; SKMatrix matrix = SKMatrix.MakeRotationDegrees(-angle, bitmap.Width / 2, bitmap.Height / 2); // Loop trough the fingers touching the screen. foreach (long id in idDictionary.Keys) { FingerInfo fingerInfo = idDictionary[id]; // Get the canvas size in pixels. It's square so it's only one number. float canvasSize = 0; if (canvasView is SKCanvasView) { canvasSize = (canvasView as SKCanvasView).CanvasSize.Width; } else { canvasSize = (canvasView as SKGLView).CanvasSize.Width; } // Convert Xamarin.Forms coordinates to pixels for drawing on the bitmap. // Also, make an offset factor if there's been resizing and the bitmap // is now larger than the canvas. (It's never smaller.) float factor = canvasSize / (float)canvasView.Width; // scaling factor float offset = (bitmapSize - canvasSize) / 2; // bitmap always >= canvas SKPoint convertedPoint = new SKPoint(factor * (float)fingerInfo.ThisPosition.X + offset, factor * (float)fingerInfo.ThisPosition.Y + offset); // Now rotate the point based on the rotation angle SKPoint pt0 = matrix.MapPoint(convertedPoint); if (!float.IsPositiveInfinity(fingerInfo.LastPosition.X)) { // Draw four lines in four quadrants. SKPoint pt1 = fingerInfo.LastPosition; bitmapCanvas.DrawLine(pt0.X, pt0.Y, pt1.X, pt1.Y, fingerPaint); float x0Flip = bitmap.Width - pt0.X; float y0Flip = bitmap.Height - pt0.Y; float x1Flip = bitmap.Width - pt1.X; float y1Flip = bitmap.Height - pt1.Y; bitmapCanvas.DrawLine(x0Flip, pt0.Y, x1Flip, pt1.Y, fingerPaint); bitmapCanvas.DrawLine(pt0.X, y0Flip, pt1.X, y1Flip, fingerPaint); bitmapCanvas.DrawLine(x0Flip, y0Flip, x1Flip, y1Flip, fingerPaint); } // Save the current point for next time through. fingerInfo.LastPosition = pt0; } // Redraw the canvas. if (canvasView is SKCanvasView) { (canvasView as SKCanvasView).InvalidateSurface(); } else { (canvasView as SKGLView).InvalidateSurface(); } return(true); }
public static SKMatrix Scale(this SKMatrix m, float sx, float sy) { return(m.Concat(SKMatrix.MakeScale(sx, sy))); }
public void ClipRoundRect(SKRoundRect rect, SKClipOperation operation) { rect.Transform(SKMatrix.CreateScale(CurrentState.ScaleX, CurrentState.ScaleY)); Canvas.ClipRoundRect(rect, operation, true); }
public async Task <Tuple <Stream, LoadingResult, ImageInformation> > Resolve(string identifier, TaskParameter parameters, CancellationToken token) { ImageSource source = parameters.Source; if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier) { source = parameters.LoadingPlaceholderSource; } else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier) { source = parameters.ErrorPlaceholderSource; } var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory()) .GetResolver(identifier, source, parameters, Configuration) .Resolve(identifier, parameters, token); if (resolvedData?.Item1 == null) { throw new FileNotFoundException(identifier); } var svg = new SKSvg() { ThrowOnUnsupportedElement = false, }; SKPicture picture; using (var svgStream = resolvedData.Item1) { picture = svg.Load(resolvedData?.Item1); } float sizeX = 0; float sizeY = 0; if (VectorWidth == 0 && VectorHeight == 0) { sizeX = 200; sizeY = (VectorWidth / picture.Bounds.Width) * picture.Bounds.Height; } else if (VectorWidth > 0 && VectorHeight > 0) { sizeX = VectorWidth; sizeY = VectorHeight; } else if (VectorWidth > 0) { sizeX = VectorWidth; sizeY = (VectorWidth / picture.Bounds.Width) * picture.Bounds.Height; } else { sizeX = (VectorHeight / picture.Bounds.Height) * picture.Bounds.Width; sizeY = VectorHeight; } using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY)) using (var canvas = new SKCanvas(bitmap)) using (var paint = new SKPaint()) { canvas.Clear(SKColors.Transparent); float scaleX = sizeX / picture.Bounds.Width; float scaleY = sizeY / picture.Bounds.Height; var matrix = SKMatrix.MakeScale(scaleX, scaleY); canvas.DrawPicture(picture, ref matrix, paint); canvas.Flush(); using (var image = SKImage.FromBitmap(bitmap)) using (var data = image.Encode(SKImageEncodeFormat.Png, 80)) { var stream = new MemoryStream(); data.SaveTo(stream); stream.Position = 0; //var stream = data?.AsStream(); return(new Tuple <Stream, LoadingResult, ImageInformation>(stream, resolvedData.Item2, resolvedData.Item3)); } } }
public virtual void Draw(SKCanvas canvas, Attributes ignoreAttributes, Drawable?until) { if (!IsDrawable) { return; } if (until != null && this == until) { return; } var enableClip = !ignoreAttributes.HasFlag(Attributes.ClipPath); var enableMask = !ignoreAttributes.HasFlag(Attributes.Mask); var enableOpacity = !ignoreAttributes.HasFlag(Attributes.Opacity); var enableFilter = !ignoreAttributes.HasFlag(Attributes.Filter); canvas.Save(); if (Overflow != null) { canvas.ClipRect(Overflow.Value, SKClipOperation.Intersect); } var skMatrixTotal = canvas.TotalMatrix; SKMatrix.PreConcat(ref skMatrixTotal, ref Transform); canvas.SetMatrix(skMatrixTotal); if (Clip != null) { canvas.ClipRect(Clip.Value, SKClipOperation.Intersect); } if (ClipPath != null && enableClip == true) { canvas.ClipPath(ClipPath, SKClipOperation.Intersect, IsAntialias); } if (MaskDrawable != null && enableMask == true) { canvas.SaveLayer(Mask); } if (Opacity != null && enableOpacity == true) { canvas.SaveLayer(Opacity); } if (Filter != null && enableFilter == true) { canvas.SaveLayer(Filter); } OnDraw(canvas, ignoreAttributes, until); if (Filter != null && enableFilter == true) { canvas.Restore(); } if (Opacity != null && enableOpacity == true) { canvas.Restore(); } if (MaskDrawable != null && enableMask == true) { canvas.SaveLayer(MaskDstIn); MaskDrawable.Draw(canvas, ignoreAttributes, until); canvas.Restore(); canvas.Restore(); } canvas.Restore(); }
public void ClipPath(SKPath path, SKClipOperation operation) { path.Transform(SKMatrix.CreateScale(CurrentState.ScaleX, CurrentState.ScaleY)); Canvas.ClipPath(path, operation); }
public static Matrix3x2 ToNumerics(this SKMatrix matrix) => new Matrix3x2(matrix.ScaleX, matrix.SkewY, matrix.SkewX, matrix.ScaleY, matrix.TransX, matrix.TransY);
public void EmptyMatrixForNonInvertableMatrix() { var matrix = SKMatrix.CreateScale(0, 1); Assert.Equal(SKMatrix.Empty, matrix.Invert()); }
internal PaintWrapper CreatePaint(IBrush brush, Size targetSize) { SKPaint paint = new SKPaint(); var rv = new PaintWrapper(paint); paint.IsStroke = false; // TODO: SkiaSharp does not contain alpha yet! double opacity = brush.Opacity * _currentOpacity; //paint.SetAlpha(paint.GetAlpha() * opacity); paint.IsAntialias = true; SKColor color = new SKColor(255, 255, 255, 255); var solid = brush as ISolidColorBrush; if (solid != null) { color = solid.Color.ToSKColor(); } paint.Color = (new SKColor(color.Red, color.Green, color.Blue, (byte)(color.Alpha * opacity))); if (solid != null) { return(rv); } var gradient = brush as IGradientBrush; if (gradient != null) { var tileMode = gradient.SpreadMethod.ToSKShaderTileMode(); var stopColors = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray(); var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray(); var linearGradient = brush as ILinearGradientBrush; if (linearGradient != null) { var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint(); var end = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint(); // would be nice to cache these shaders possibly? using (var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode)) paint.Shader = shader; } else { var radialGradient = brush as IRadialGradientBrush; if (radialGradient != null) { var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint(); var radius = (float)radialGradient.Radius; // TODO: There is no SetAlpha in SkiaSharp //paint.setAlpha(128); // would be nice to cache these shaders possibly? using (var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode)) paint.Shader = shader; } } return(rv); } var tileBrush = brush as ITileBrush; if (tileBrush != null) { var helper = new TileBrushImplHelper(tileBrush, targetSize); var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height); rv.AddDisposable(bitmap); using (var ctx = bitmap.CreateDrawingContext()) helper.DrawIntermediate(ctx); SKMatrix translation = SKMatrix.MakeTranslation(-(float)helper.DestinationRect.X, -(float)helper.DestinationRect.Y); 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; using (var shader = SKShader.CreateBitmap(bitmap.Bitmap, tileX, tileY, translation)) paint.Shader = shader; } return(rv); }
public override void DrawContent(SKCanvas canvas, int width, int height) { var total = Inputs?.Count() ?? 0; if (total > 0) { var captionHeight = Inputs.Max(x => { var result = 0.0f; var hasLabel = !string.IsNullOrEmpty(x.Label); var hasValueLabel = !string.IsNullOrEmpty(x.DisplayValue); if (hasLabel || hasValueLabel) { var hasOffset = hasLabel && hasValueLabel; var captionMargin = LabelTextSize * 0.60f; var space = hasOffset ? captionMargin : 0; if (hasLabel) { result += LabelTextSize; } if (hasValueLabel) { result += LabelTextSize; } } return(result); }); var center = new SKPoint(width / 2, height / 2); var radius = ((Math.Min(width, height) - (2 * Margin)) / 2) - captionHeight; var rangeAngle = (float)((Math.PI * 2) / total); var startAngle = (float)Math.PI; var nextInput = Inputs.First(); var nextAngle = startAngle; var nextPoint = GetPoint(nextInput.Value * AnimationProgress, center, nextAngle, radius); DrawBorder(canvas, center, radius); using (var clip = new SKPath()) { clip.AddCircle(center.X, center.Y, radius); for (int i = 0; i < total; i++) { var angle = nextAngle; var input = nextInput; var point = nextPoint; var nextIndex = (i + 1) % total; nextAngle = startAngle + (rangeAngle * nextIndex); nextInput = Inputs.ElementAt(nextIndex); nextPoint = GetPoint(nextInput.Value * AnimationProgress, center, nextAngle, radius); canvas.Save(); canvas.ClipPath(clip); // Border center bars using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = BorderLineColor, IsAntialias = true, }) { var borderPoint = GetPoint(MaxValue, center, angle, radius); canvas.DrawLine(point.X, point.Y, borderPoint.X, borderPoint.Y, paint); } // Values points and lines using (var paint = new SKPaint() { Style = SKPaintStyle.Stroke, StrokeWidth = BorderLineSize, Color = input.Color.WithAlpha((byte)(input.Color.Alpha * 0.75f * AnimationProgress)), PathEffect = SKPathEffect.CreateDash(new[] { BorderLineSize, BorderLineSize * 2 }, 0), IsAntialias = true, }) { var amount = Math.Abs(input.Value - AbsoluteMinimum) / ValueRange; canvas.DrawCircle(center.X, center.Y, radius * amount, paint); } canvas.DrawGradientLine(center, input.Color.WithAlpha(0), point, input.Color.WithAlpha((byte)(input.Color.Alpha * 0.75f)), LineSize); canvas.DrawGradientLine(point, input.Color, nextPoint, nextInput.Color, LineSize); canvas.DrawPoint(point, input.Color, PointSize, PointMode); canvas.Restore(); // Labels var labelPoint = new SKPoint(0, radius + LabelTextSize + (PointSize / 2)); var rotation = SKMatrix.MakeRotation(angle); labelPoint = center + rotation.MapPoint(labelPoint); var alignment = SKTextAlign.Left; if ((Math.Abs(angle - (startAngle + Math.PI)) < Epsilon) || (Math.Abs(angle - Math.PI) < Epsilon)) { alignment = SKTextAlign.Center; } else if (angle > (float)(startAngle + Math.PI)) { alignment = SKTextAlign.Right; } canvas.DrawCaptionLabels(input.Label, input.TextColor, input.DisplayValue, input.Color.WithAlpha((byte)(255 * AnimationProgress)), LabelTextSize, labelPoint, alignment, base.Typeface); } } } }
/// <summary> /// Paint checkbox /// </summary> /// <param name="e"></param> protected override void OnPaintSelectionElement(SKPaintSurfaceEventArgs e) { if (_checkMarkSvg == null && string.IsNullOrEmpty(CheckMarkIconAssemblyName) == false && string.IsNullOrEmpty(CheckMarkIconResourceKey) == false) { _checkMarkSvg = SvgImage.GetSvgImage(CheckMarkIconAssemblyName, CheckMarkIconResourceKey); } Rectangle checkBoxAvailableLocation = new Rectangle(); Rectangle availableSpace = new Rectangle(EllipseDiameter, EllipseDiameter, Width, Height - Padding.VerticalThickness); if (CheckBoxLocation == HorizontalLocations.Left) { checkBoxAvailableLocation = availableSpace; } else { checkBoxAvailableLocation = new Rectangle(availableSpace.Width - CheckBoxWidthRequest - CheckBoxMargin.HorizontalThickness + EllipseDiameter, EllipseDiameter, availableSpace.Width, availableSpace.Height); } Rectangle checkBoxActualLocation = CheckBoxActualLocation(checkBoxAvailableLocation); float skCheckBoxBorderThickness = (float)CheckBoxBorderThickness * DeviceScale; float skCheckBoxX = (float)checkBoxActualLocation.X * DeviceScale; float skCheckBoxY = (float)checkBoxActualLocation.Y * DeviceScale; float skCheckBoxWidth = (float)CheckBoxWidthRequest * DeviceScale; float skCheckBoxHeight = (float)CheckBoxHeightRequest * DeviceScale; float skCornerRadius = (float)CheckBoxCornerRadius * DeviceScale; SKMatrix checkMarkMatrix = new SKMatrix(); SKPoint checkMarkPosition = new SKPoint(); Size checkMarkIconSize = new Size(CheckBoxWidthRequest - CheckMarkIconMargin.HorizontalThickness, CheckBoxHeightRequest - CheckMarkIconMargin.VerticalThickness); float scale = SvgImage.CalculateScale(_checkMarkSvg.Picture.CullRect.Size, checkMarkIconSize.Width, checkMarkIconSize.Height); Size actualCheckMarkIconSize = new Size(_checkMarkSvg.Picture.CullRect.Width * scale, _checkMarkSvg.Picture.CullRect.Height * scale); scale = scale * DeviceScale; checkMarkPosition.X = (float)skCheckBoxX + (float)((CheckBoxWidthRequest - actualCheckMarkIconSize.Width) / 2) * DeviceScale; checkMarkPosition.Y = (float)skCheckBoxY + (float)((CheckBoxHeightRequest - actualCheckMarkIconSize.Height) / 2) * DeviceScale; checkMarkMatrix.SetScaleTranslate(scale, scale, checkMarkPosition.X, checkMarkPosition.Y); SKRect checkBoxPaintRect = new SKRect(skCheckBoxX + skCheckBoxBorderThickness / 2, skCheckBoxY + skCheckBoxBorderThickness / 2, skCheckBoxX + skCheckBoxWidth - skCheckBoxBorderThickness / 2, skCheckBoxY + skCheckBoxHeight - skCheckBoxBorderThickness / 2); if (EllipseDiameter > 0 && _toggledAnimationProcess > 0 && _toggledAnimationProcess < 1 && IsEllipseAnimationEnabled) { SKPaint ellipsePaint = new SKPaint() { IsAntialias = true, Style = SKPaintStyle.Fill, }; if (_toggledAnimationProcess <= 0.5) { ellipsePaint.Color = EllipseColor.MultiplyAlpha(_toggledAnimationProcessWithoutEasing * 2).ToSKColor(); } else { ellipsePaint.Color = EllipseColor.MultiplyAlpha(1 - (_toggledAnimationProcessWithoutEasing - 0.5) * 2).ToSKColor(); } e.Surface.Canvas.DrawCircle(new SKPoint(checkBoxPaintRect.MidX, checkBoxPaintRect.MidY), (float)(EllipseDiameter / 2) * DeviceScale, ellipsePaint); } Color backgroundColor = Color.Transparent; if (CheckBoxBackgroundColor != null && CheckBoxBackgroundColor != Color.Transparent && ToggledCheckBoxBackgroundColor != null && ToggledCheckBoxBackgroundColor != Color.Transparent) { backgroundColor = AnimationUtils.ColorTransform(_toggledAnimationProcess, CheckBoxBackgroundColor, ToggledCheckBoxBackgroundColor); } else if ((CheckBoxBackgroundColor == null || CheckBoxBackgroundColor == Color.Transparent) && ToggledCheckBoxBackgroundColor != null && ToggledCheckBoxBackgroundColor != Color.Transparent) { backgroundColor = ToggledCheckBoxBackgroundColor; } else { backgroundColor = CheckBoxBackgroundColor; } SKPaint checkBoxBackgroundPaint = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true, Color = backgroundColor.ToSKColor(), }; SKRect rect = new SKRect( skCheckBoxX + skCheckBoxBorderThickness, skCheckBoxY + skCheckBoxBorderThickness, skCheckBoxX + skCheckBoxWidth - skCheckBoxBorderThickness, skCheckBoxY + skCheckBoxHeight - skCheckBoxBorderThickness); e.Surface.Canvas.Save(); SKRect r = SKRect.Create(rect.Left, rect.Top, rect.Width, rect.Height); if (_toggledAnimationProcess <= 0.75) { float v = (float)(_toggledAnimationProcess * (1 / 0.75)); r.Inflate(-rect.Width * v / 2, -rect.Height * v / 2); e.Surface.Canvas.ClipRect(r, SKClipOperation.Difference); } e.Surface.Canvas.DrawRoundRect(checkBoxPaintRect, skCornerRadius, skCornerRadius, checkBoxBackgroundPaint); e.Surface.Canvas.Restore(); SKPaint checkBoxBorderPaint = new SKPaint { Style = SKPaintStyle.Stroke, IsAntialias = true, StrokeWidth = skCheckBoxBorderThickness, Color = AnimationUtils.ColorTransform(_toggledAnimationProcess, CheckBoxBorderColor, ToggledCheckBoxBorderColor).ToSKColor(), }; e.Surface.Canvas.DrawRoundRect(checkBoxPaintRect, skCornerRadius, skCornerRadius, checkBoxBorderPaint); using (var paint = new SKPaint()) { Color color = Color.Transparent; if (_toggledAnimationProcess > 0.75) { float v = (float)((_toggledAnimationProcess - 0.75) * (1 / 0.25)); color = AnimationUtils.ColorTransform(v, CheckMarkIconColor, ToggledCheckMarkIconColor); } if (color != Color.Transparent) { paint.ColorFilter = SKColorFilter.CreateBlendMode(color.ToSKColor(), SKBlendMode.SrcIn); paint.Style = SKPaintStyle.Fill; paint.IsAntialias = true; e.Surface.Canvas.DrawPicture(_checkMarkSvg.Picture, ref checkMarkMatrix, paint); } } }
public static SKMatrix Make(SKSize size, TaperSide taperSide, TaperCorner taperCorner, float taperFraction) { var matrix = SKMatrix.MakeIdentity(); switch (taperSide) { case TaperSide.Left: matrix.ScaleX = taperFraction; matrix.ScaleY = taperFraction; matrix.Persp0 = (taperFraction - 1) / size.Width; switch (taperCorner) { case TaperCorner.RightOrBottom: break; case TaperCorner.LeftOrTop: matrix.SkewY = size.Height * matrix.Persp0; matrix.TransY = size.Height * (1 - taperFraction); break; case TaperCorner.Both: matrix.SkewY = (size.Height / 2) * matrix.Persp0; matrix.TransY = size.Height * (1 - taperFraction) / 2; break; } break; case TaperSide.Top: matrix.ScaleX = taperFraction; matrix.ScaleY = taperFraction; matrix.Persp1 = (taperFraction - 1) / size.Height; switch (taperCorner) { case TaperCorner.RightOrBottom: break; case TaperCorner.LeftOrTop: matrix.SkewX = size.Width * matrix.Persp1; matrix.TransX = size.Width * (1 - taperFraction); break; case TaperCorner.Both: matrix.SkewX = (size.Width / 2) * matrix.Persp1; matrix.TransX = size.Width * (1 - taperFraction) / 2; break; } break; case TaperSide.Right: matrix.ScaleX = 1 / taperFraction; matrix.Persp0 = (1 - taperFraction) / (size.Width * taperFraction); switch (taperCorner) { case TaperCorner.RightOrBottom: break; case TaperCorner.LeftOrTop: matrix.SkewY = size.Height * matrix.Persp0; break; case TaperCorner.Both: matrix.SkewY = (size.Height / 2) * matrix.Persp0; break; } break; case TaperSide.Bottom: matrix.ScaleY = 1 / taperFraction; matrix.Persp1 = (1 - taperFraction) / (size.Height * taperFraction); switch (taperCorner) { case TaperCorner.RightOrBottom: break; case TaperCorner.LeftOrTop: matrix.SkewX = size.Width * matrix.Persp1; break; case TaperCorner.Both: matrix.SkewX = (size.Width / 2) * matrix.Persp1; break; } break; } return(matrix); }
public override void DrawImage(SKCanvas dc) { var rect_Car = GetMainRect(); SKPoint pt_Center = new SKPoint(rect_Car.Left + (rect_Car.Width / 2), rect_Car.Top + (rect_Car.Height / 2)); SKRect rect_Body; SKPath gp_Body; SKRect rect_Tire; float int_TireHeight; SKPoint[] pts_Body; SKRect rect_Hole; int int_Row; int int_Col; float int_HoleWidth; int int_Count; CustomBasicList <SKRect> arr_Holes; SKColor clr_Peg; SKMatrix tmp_Matrix = new SKMatrix(); if (CarType == EnumTypesOfCars.Minivan) { // *** Draw tires int_TireHeight = (rect_Car.Height / 5); rect_Tire = SKRect.Create(rect_Car.Left, rect_Car.Top + (rect_Car.Height / 10), rect_Car.Width, int_TireHeight); dc.DrawRect(rect_Tire, _blackPaint); rect_Tire = SKRect.Create(rect_Car.Left, (rect_Car.Top + rect_Car.Height) - (rect_Car.Height / 10) - int_TireHeight, rect_Car.Width, int_TireHeight); dc.DrawRect(rect_Tire, _blackPaint); // *** Draw the body outline gp_Body = new SKPath(); rect_Body = SKRect.Create(rect_Car.Left + (rect_Car.Width / 12), rect_Car.Top, rect_Car.Width - (rect_Car.Width / 6), rect_Car.Height); pts_Body = new SKPoint[4]; pts_Body[0] = new SKPoint(System.Convert.ToInt32(rect_Body.Left), rect_Body.Top + (rect_Body.Height / 30)); pts_Body[1] = new SKPoint(System.Convert.ToInt32((rect_Body.Left + rect_Body.Width)), rect_Body.Top + (rect_Body.Height / 30)); pts_Body[2] = new SKPoint(System.Convert.ToInt32(((rect_Body.Left + rect_Body.Width) - (rect_Car.Width / 15))), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30)); pts_Body[3] = new SKPoint(System.Convert.ToInt32((rect_Body.Left + (rect_Car.Width / 15))), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30)); gp_Body.AddPoly(pts_Body); SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y); gp_Body.Transform(tmp_Matrix); dc.DrawPath(gp_Body, MainPaint); dc.DrawPath(gp_Body, _borderPaint); gp_Body = new SKPath(); pts_Body = new SKPoint[3]; pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 15), rect_Body.Top + (rect_Body.Height / 15)); pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), rect_Body.Top + (rect_Body.Height / 100)); pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 15), rect_Body.Top + (rect_Body.Height / 15)); gp_Body.AddPoly(pts_Body); SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y); gp_Body.Transform(tmp_Matrix); dc.DrawPath(gp_Body, _blackPaint); // *** Draw the front window gp_Body = new SKPath(); pts_Body = new SKPoint[8]; pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)); pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 30)); pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)); pts_Body[3] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)); pts_Body[4] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 6), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4)); pts_Body[5] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4)) + (rect_Body.Height / 30)); pts_Body[6] = new SKPoint(rect_Body.Left + (rect_Body.Width / 6), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4)); pts_Body[7] = new SKPoint(rect_Body.Left + (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)); gp_Body.AddPoly(pts_Body); SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y); gp_Body.Transform(tmp_Matrix); dc.DrawPath(gp_Body, _blackPaint); // *** Draw the hood gp_Body = new SKPath(); pts_Body = new SKPoint[8]; pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 10)); pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 30) + (rect_Body.Height / 10)); pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 10)); pts_Body[3] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 10)); pts_Body[4] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 5), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30)); pts_Body[5] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), rect_Body.Top + rect_Body.Height); pts_Body[6] = new SKPoint(rect_Body.Left + (rect_Body.Width / 5), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30)); pts_Body[7] = new SKPoint(rect_Body.Left + (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 10)); gp_Body.AddPoly(pts_Body); SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y); gp_Body.Transform(tmp_Matrix); dc.DrawPath(gp_Body, MainPaint); } else if (CarType == EnumTypesOfCars.Car) { } // *** Draw the holes arr_Holes = new CustomBasicList <SKRect>(); int_HoleWidth = rect_Car.Width * 2 / 9; for (int_Row = 0; int_Row <= 2; int_Row++) { for (int_Col = 0; int_Col <= 1; int_Col++) { if (int_Col == 0) { rect_Hole = SKRect.Create(rect_Car.Left + (rect_Car.Width / 5), rect_Car.Top + (rect_Car.Height * 2 / 5) + (int_Row * (int_HoleWidth + (int_HoleWidth / 4))), int_HoleWidth, int_HoleWidth); } else { rect_Hole = SKRect.Create(rect_Car.Left + rect_Car.Width - (rect_Car.Width / 5) - int_HoleWidth, rect_Car.Top + (rect_Car.Height * 2 / 5) + (int_Row * (int_HoleWidth + (int_HoleWidth / 4))), int_HoleWidth, int_HoleWidth); } arr_Holes.Add(rect_Hole); } } var loopTo = arr_Holes.Count; for (int_Count = 1; int_Count <= loopTo; int_Count++) { rect_Hole = arr_Holes[int_Count - 1]; dc.DrawOval(rect_Hole, _blackPaint); if (_arr_Pegs.Count >= int_Count) { clr_Peg = _arr_Pegs[int_Count - 1].ToSKColor(); DrawPeg(dc, rect_Hole, clr_Peg); } } }
public static SKMatrix RotateDegrees(this SKMatrix m, float andegrees) { return(m.Concat(SKMatrix.MakeRotationDegrees(andegrees))); }
public SKLinearGradient(float startX, float startY, float endX, float endY, float[] positions, SKColor[] colors, SKShaderTileMode tileMode, SKMatrix gradientTransform) { StartX = startX; StartY = startY; EndX = endX; EndY = endY; Positions = positions; Colors = colors; TileMode = tileMode; GradientTransform = gradientTransform; }
public static SKMatrix Translate(this SKMatrix m, float dx, float dy) { return(m.Concat(SKMatrix.MakeTranslation(dx, dy))); }
private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill) { ReadPaints(e, ref stroke, ref fill); // transform matrix var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty); canvas.Save(); canvas.Concat(ref transform); // SVG elements var elementName = e.Name.LocalName; switch (elementName) { case "text": if (stroke != null || fill != null) { ReadText(e, canvas, stroke?.Clone(), fill?.Clone()); } break; case "rect": if (stroke != null || fill != null) { var x = ReadNumber(e.Attribute("x")); var y = ReadNumber(e.Attribute("y")); var width = ReadNumber(e.Attribute("width")); var height = ReadNumber(e.Attribute("height")); var rx = ReadNumber(e.Attribute("rx")); var ry = ReadNumber(e.Attribute("ry")); var rect = SKRect.Create(x, y, width, height); if (rx > 0 || ry > 0) { if (fill != null) { canvas.DrawRoundRect(rect, rx, ry, fill); } if (stroke != null) { canvas.DrawRoundRect(rect, rx, ry, stroke); } } else { if (fill != null) { canvas.DrawRect(rect, fill); } if (stroke != null) { canvas.DrawRect(rect, stroke); } } } break; case "ellipse": if (stroke != null || fill != null) { var cx = ReadNumber(e.Attribute("cx")); var cy = ReadNumber(e.Attribute("cy")); var rx = ReadNumber(e.Attribute("rx")); var ry = ReadNumber(e.Attribute("ry")); if (fill != null) { canvas.DrawOval(cx, cy, rx, ry, fill); } if (stroke != null) { canvas.DrawOval(cx, cy, rx, ry, stroke); } } break; case "circle": if (stroke != null || fill != null) { var cx = ReadNumber(e.Attribute("cx")); var cy = ReadNumber(e.Attribute("cy")); var rr = ReadNumber(e.Attribute("r")); if (fill != null) { canvas.DrawCircle(cx, cy, rr, fill); } if (stroke != null) { canvas.DrawCircle(cx, cy, rr, stroke); } } break; case "path": if (stroke != null || fill != null) { var d = e.Attribute("d")?.Value; if (!string.IsNullOrWhiteSpace(d)) { var path = SKPath.ParseSvgPathData(d); if (fill != null) { canvas.DrawPath(path, fill); } if (stroke != null) { canvas.DrawPath(path, stroke); } } } break; case "polygon": case "polyline": if (stroke != null || fill != null) { var close = elementName == "polygon"; var p = e.Attribute("points")?.Value; if (!string.IsNullOrWhiteSpace(p)) { var path = ReadPolyPath(p, close); if (fill != null) { canvas.DrawPath(path, fill); } if (stroke != null) { canvas.DrawPath(path, stroke); } } } break; case "g": if (e.HasElements) { foreach (var gElement in e.Elements()) { ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone()); } } break; case "use": if (e.HasAttributes) { var href = ReadHref(e); if (href != null) { // TODO: copy/process other attributes var x = ReadNumber(e.Attribute("x")); var y = ReadNumber(e.Attribute("y")); var useTransform = SKMatrix.MakeTranslation(x, y); canvas.Save(); canvas.Concat(ref useTransform); ReadElement(href, canvas, stroke?.Clone(), fill?.Clone()); canvas.Restore(); } } break; case "line": if (stroke != null) { var x1 = ReadNumber(e.Attribute("x1")); var x2 = ReadNumber(e.Attribute("x2")); var y1 = ReadNumber(e.Attribute("y1")); var y2 = ReadNumber(e.Attribute("y2")); canvas.DrawLine(x1, y1, x2, y2, stroke); } break; case "switch": if (e.HasElements) { foreach (var ee in e.Elements()) { var requiredFeatures = ee.Attribute("requiredFeatures"); var requiredExtensions = ee.Attribute("requiredExtensions"); var systemLanguage = ee.Attribute("systemLanguage"); // TODO: evaluate requiredFeatures, requiredExtensions and systemLanguage var isVisible = requiredFeatures == null && requiredExtensions == null && systemLanguage == null; if (isVisible) { ReadElement(ee, canvas, stroke?.Clone(), fill?.Clone()); } } } break; case "defs": case "title": case "desc": case "description": // already read earlier break; default: LogOrThrow($"SVG element '{elementName}' is not supported"); break; } // restore matrix canvas.Restore(); }
public static SKMatrix Rotate(this SKMatrix m, float angle) { return(m.Concat(SKMatrix.MakeRotation(angle))); }
private SKMatrix ReadTransform(string raw) { var t = SKMatrix.MakeIdentity(); if (string.IsNullOrWhiteSpace(raw)) { return(t); } var calls = raw.Trim().Split(new[] { ')' }, StringSplitOptions.RemoveEmptyEntries); foreach (var c in calls) { var args = c.Split(new[] { '(', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); var nt = SKMatrix.MakeIdentity(); switch (args[0]) { case "matrix": if (args.Length == 7) { nt.Values = new float[] { ReadNumber(args[1]), ReadNumber(args[3]), ReadNumber(args[5]), ReadNumber(args[2]), ReadNumber(args[4]), ReadNumber(args[6]), 0, 0, 1 }; } else { LogOrThrow($"Matrices are expected to have 6 elements, this one has {args.Length - 1}"); } break; case "translate": if (args.Length >= 3) { nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), ReadNumber(args[2])); } else if (args.Length >= 2) { nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), 0); } break; case "scale": if (args.Length >= 3) { nt = SKMatrix.MakeScale(ReadNumber(args[1]), ReadNumber(args[2])); } else if (args.Length >= 2) { var sx = ReadNumber(args[1]); nt = SKMatrix.MakeScale(sx, sx); } break; case "rotate": var a = ReadNumber(args[1]); if (args.Length >= 4) { var x = ReadNumber(args[2]); var y = ReadNumber(args[3]); var t1 = SKMatrix.MakeTranslation(x, y); var t2 = SKMatrix.MakeRotationDegrees(a); var t3 = SKMatrix.MakeTranslation(-x, -y); SKMatrix.Concat(ref nt, ref t1, ref t2); SKMatrix.Concat(ref nt, ref nt, ref t3); } else { nt = SKMatrix.MakeRotationDegrees(a); } break; default: LogOrThrow($"Can't transform {args[0]}"); break; } SKMatrix.Concat(ref t, ref t, ref nt); } return(t); }
public SKRadialGradient(SKPoint center, float radius, float[] positions, SKColor[] colors, SKShaderTileMode tileMode, SKMatrix matrix) { Center = center; Radius = radius; Positions = positions; Colors = colors; TileMode = tileMode; Matrix = matrix; }
private void PaintSVTriangle(SKCanvas canvas, float canvasRadius) { canvas.Save(); SKMatrix rotationHue = SKMatrix.MakeRotation(-(float)((2D * Math.PI * lastHue) + (Math.PI / 2D)) , canvasRadius, canvasRadius); if (RotateTriangleByHue) { canvas.SetMatrix(rotationHue); } var point1 = new SKPoint(canvasRadius, canvasRadius - WheelSVRadius(canvasRadius)); var point2 = new SKPoint(canvasRadius + (triangleSide * WheelSVRadius(canvasRadius)) , canvasRadius + (triangleVerticalOffset * WheelSVRadius(canvasRadius))); var point3 = new SKPoint(canvasRadius - (triangleSide * WheelSVRadius(canvasRadius)) , canvasRadius + (triangleVerticalOffset * WheelSVRadius(canvasRadius))); using (SKPath pathTriangle = new SKPath()) { pathTriangle.MoveTo(point1); pathTriangle.LineTo(point2); pathTriangle.LineTo(point3); canvas.ClipPath(pathTriangle, SKClipOperation.Intersect, true); } SKMatrix matrix = SKMatrix.MakeRotation(-(float)Math.PI / 3F, point3.X, point3.Y); if (RotateTriangleByHue) { SKMatrix.Concat(ref matrix, rotationHue, matrix); } var shader = SKShader.CreateSweepGradient(point3, new SKColor[] { Color.FromHsla(lastHue, 1, 0.5).ToSKColor() , Color.White.ToSKColor(), Color.FromHsla(lastHue, 1, 0.5).ToSKColor() } , new float[] { 0F, 0.16666666666666F, 1F }); var paint = new SKPaint { IsAntialias = true, Shader = shader, Style = SKPaintStyle.Fill }; canvas.SetMatrix(matrix); canvas.DrawCircle(point3, WheelSVRadius(canvasRadius) * 2, paint); if (RotateTriangleByHue) { canvas.SetMatrix(rotationHue); } else { canvas.ResetMatrix(); } var colors = new SKColor[] { SKColors.Black, SKColors.Transparent }; PaintGradient(canvas, canvasRadius, colors, point3); canvas.ResetMatrix(); canvas.Restore(); }
public Glyph(SvgGlyph svgGlyph) { matrix = SvgHelper.GetSKMatrix(svgGlyph.Transforms); }
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); }
/// <summary> /// Configure paint wrapper for using gradient brush. /// </summary> /// <param name="paintWrapper">Paint wrapper.</param> /// <param name="targetRect">Target bound rect.</param> /// <param name="gradientBrush">Gradient brush.</param> private void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Rect targetRect, IGradientBrush gradientBrush) { var tileMode = gradientBrush.SpreadMethod.ToSKShaderTileMode(); var stopColors = gradientBrush.GradientStops.Select(s => s.Color.ToSKColor()).ToArray(); var stopOffsets = gradientBrush.GradientStops.Select(s => (float)s.Offset).ToArray(); var position = targetRect.Position.ToSKPoint(); switch (gradientBrush) { case ILinearGradientBrush linearGradient: { var start = position + linearGradient.StartPoint.ToPixels(targetRect.Size).ToSKPoint(); var end = position + linearGradient.EndPoint.ToPixels(targetRect.Size).ToSKPoint(); // would be nice to cache these shaders possibly? using (var shader = SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode)) { paintWrapper.Paint.Shader = shader; } break; } case IRadialGradientBrush radialGradient: { var center = position + radialGradient.Center.ToPixels(targetRect.Size).ToSKPoint(); var radius = (float)(radialGradient.Radius * targetRect.Width); var origin = position + radialGradient.GradientOrigin.ToPixels(targetRect.Size).ToSKPoint(); if (origin.Equals(center)) { // when the origin is the same as the center the Skia RadialGradient acts the same as D2D using (var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode)) { paintWrapper.Paint.Shader = shader; } } else { // when the origin is different to the center use a two point ConicalGradient to match the behaviour of D2D // reverse the order of the stops to match D2D var reversedColors = new SKColor[stopColors.Length]; Array.Copy(stopColors, reversedColors, stopColors.Length); Array.Reverse(reversedColors); // and then reverse the reference point of the stops var reversedStops = new float[stopOffsets.Length]; for (var i = 0; i < stopOffsets.Length; i++) { reversedStops[i] = stopOffsets[i]; if (reversedStops[i] > 0 && reversedStops[i] < 1) { reversedStops[i] = Math.Abs(1 - stopOffsets[i]); } } // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color using (var shader = SKShader.CreateCompose( SKShader.CreateColor(reversedColors[0]), SKShader.CreateTwoPointConicalGradient(center, radius, origin, 0, reversedColors, reversedStops, tileMode) )) { paintWrapper.Paint.Shader = shader; } } break; } case IConicGradientBrush conicGradient: { var center = position + conicGradient.Center.ToPixels(targetRect.Size).ToSKPoint(); // Skia's default is that angle 0 is from the right hand side of the center point // but we are matching CSS where the vertical point above the center is 0. var angle = (float)(conicGradient.Angle - 90); var rotation = SKMatrix.CreateRotationDegrees(angle, center.X, center.Y); using (var shader = SKShader.CreateSweepGradient(center, stopColors, stopOffsets, rotation)) { paintWrapper.Paint.Shader = shader; } break; } } }
public SVGPath(string pPath, string Transform) { //Identity matrix must always be default LocalTransform = SKMatrix.MakeIdentity(); }