public void DrawForeignObject(SvgForeignObject svgForeignObject, bool ignoreDisplay) { if (!CanDraw(svgForeignObject, ignoreDisplay)) { return; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgForeignObject.Transforms); SetTransform(skMatrix); SetClipPath(svgForeignObject, _disposable); var skPaintOpacity = SetOpacity(svgForeignObject, _disposable); var skPaintFilter = SetFilter(svgForeignObject, _disposable); // TODO: if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawSymbol(SvgSymbol svgSymbol, bool ignoreDisplay) { if (!CanDraw(svgSymbol, ignoreDisplay)) { return; } _skCanvas.Save(); float x = 0f; float y = 0f; float width = svgSymbol.ViewBox.Width; float height = svgSymbol.ViewBox.Height; if (svgSymbol.CustomAttributes.TryGetValue("width", out string?_widthString)) { if (new SvgUnitConverter().ConvertFrom(_widthString) is SvgUnit _width) { width = _width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgSymbol); } } if (svgSymbol.CustomAttributes.TryGetValue("height", out string?heightString)) { if (new SvgUnitConverter().ConvertFrom(heightString) is SvgUnit _height) { height = _height.ToDeviceValue(null, UnitRenderingType.Vertical, svgSymbol); } } var skRectBounds = SKRect.Create(x, y, width, height); var skMatrixViewBox = SkiaUtil.GetSvgViewBoxTransform(svgSymbol.ViewBox, svgSymbol.AspectRatio, x, y, width, height); var skMatrix = SkiaUtil.GetSKMatrix(svgSymbol.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMatrixViewBox); SetTransform(skMatrix); SetClipPath(svgSymbol, _disposable); var skPaintOpacity = SetOpacity(svgSymbol, _disposable); var skPaintFilter = SetFilter(svgSymbol, _disposable); foreach (var svgElement in svgSymbol.Children) { Draw(svgElement, ignoreDisplay); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawEllipse(SvgEllipse svgEllipse, bool ignoreDisplay) { if (!CanDraw(svgEllipse, ignoreDisplay)) { return; } float cx = svgEllipse.CenterX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgEllipse); float cy = svgEllipse.CenterY.ToDeviceValue(null, UnitRenderingType.Vertical, svgEllipse); float rx = svgEllipse.RadiusX.ToDeviceValue(null, UnitRenderingType.Other, svgEllipse); float ry = svgEllipse.RadiusY.ToDeviceValue(null, UnitRenderingType.Other, svgEllipse); if (rx <= 0f || ry <= 0f) { return; } var skRectBounds = SKRect.Create(cx - rx, cy - ry, rx + rx, ry + ry); _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgEllipse.Transforms); SetTransform(skMatrix); SetClipPath(svgEllipse, _disposable); var skPaintOpacity = SetOpacity(svgEllipse, _disposable); var skPaintFilter = SetFilter(svgEllipse, _disposable); if (SkiaUtil.IsValidFill(svgEllipse)) { var skPaintFill = SkiaUtil.GetFillSKPaint(svgEllipse, _skSize, skRectBounds, _disposable); _skCanvas.DrawOval(cx, cy, rx, ry, skPaintFill); } if (SkiaUtil.IsValidStroke(svgEllipse)) { var skPaintStroke = SkiaUtil.GetStrokeSKPaint(svgEllipse, _skSize, skRectBounds, _disposable); _skCanvas.DrawOval(cx, cy, rx, ry, skPaintStroke); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawPolygon(SvgPolygon svgPolygon, bool ignoreDisplay) { if (!CanDraw(svgPolygon, ignoreDisplay)) { return; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgPolygon.Transforms); SetTransform(skMatrix); SetClipPath(svgPolygon, _disposable); var skPaintOpacity = SetOpacity(svgPolygon, _disposable); var skPaintFilter = SetFilter(svgPolygon, _disposable); var skPath = SkiaUtil.ToSKPath(svgPolygon.Points, svgPolygon.FillRule, true, _disposable); if (skPath != null && !skPath.IsEmpty) { var skBounds = skPath.Bounds; if (SkiaUtil.IsValidFill(svgPolygon)) { var skPaint = SkiaUtil.GetFillSKPaint(svgPolygon, _skSize, skBounds, _disposable); _skCanvas.DrawPath(skPath, skPaint); } if (SkiaUtil.IsValidStroke(svgPolygon)) { var skPaint = SkiaUtil.GetStrokeSKPaint(svgPolygon, _skSize, skBounds, _disposable); _skCanvas.DrawPath(skPath, skPaint); } DrawMarkers(svgPolygon, skPath); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
// TODO: //public void DrawAnchor(SvgAnchor svgAnchor, bool ignoreDisplay) //{ // _skCanvas.Save(); // // var skMatrix = SkiaUtil.GetSKMatrix(svgAnchor.Transforms); // SetTransform(skMatrix); // // var skPaintOpacity = SetOpacity(svgAnchor, _disposable); // // foreach (var svgElement in svgAnchor.Children) // { // Draw(svgElement, ignoreDisplay); // } // // if (skPaintOpacity != null) // { // _skCanvas.Restore(); // } // // _skCanvas.Restore(); //} public void DrawFragment(SvgFragment svgFragment, bool ignoreDisplay) { float x = svgFragment.X.ToDeviceValue(null, UnitRenderingType.Horizontal, svgFragment); float y = svgFragment.Y.ToDeviceValue(null, UnitRenderingType.Vertical, svgFragment); var skSize = SkiaUtil.GetDimensions(svgFragment); _skCanvas.Save(); switch (svgFragment.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: var skClipRect = SKRect.Create(x, y, skSize.Width, skSize.Height); _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect); break; } var skMatrixViewBox = SkiaUtil.GetSvgViewBoxTransform(svgFragment.ViewBox, svgFragment.AspectRatio, x, y, skSize.Width, skSize.Height); var skMatrix = SkiaUtil.GetSKMatrix(svgFragment.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMatrixViewBox); SetTransform(skMatrix); var skPaintOpacity = SetOpacity(svgFragment, _disposable); foreach (var svgElement in svgFragment.Children) { Draw(svgElement, ignoreDisplay); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawGroup(SvgGroup svgGroup, bool ignoreDisplay) { if (!CanDraw(svgGroup, ignoreDisplay)) { return; } // TODO: Call AddMarkers only once. AddMarkers(svgGroup); _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgGroup.Transforms); SetTransform(skMatrix); SetClipPath(svgGroup, _disposable); var skPaintOpacity = SetOpacity(svgGroup, _disposable); var skPaintFilter = SetFilter(svgGroup, _disposable); foreach (var svgElement in svgGroup.Children) { Draw(svgElement, ignoreDisplay); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawUse(SvgUse svgUse, bool ignoreDisplay) { if (!CanDraw(svgUse, ignoreDisplay)) { return; } var svgVisualElement = SkiaUtil.GetReference <SvgVisualElement>(svgUse, svgUse.ReferencedElement); if (svgVisualElement == null || SkiaUtil.HasRecursiveReference(svgUse)) { return; } float x = svgUse.X.ToDeviceValue(null, UnitRenderingType.Horizontal, svgUse); float y = svgUse.Y.ToDeviceValue(null, UnitRenderingType.Vertical, svgUse); var skMatrixTranslateXY = SKMatrix.MakeTranslation(x, y); var skMatrix = SkiaUtil.GetSKMatrix(svgUse.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMatrixTranslateXY); var ew = svgUse.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgUse); var eh = svgUse.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgUse); if (ew > 0 && eh > 0) { var _attributes = svgVisualElement.GetType().GetField("_attributes", BindingFlags.NonPublic | BindingFlags.Instance); if (_attributes != null) { var attributes = _attributes.GetValue(svgVisualElement) as SvgAttributeCollection; if (attributes != null) { var viewBox = attributes.GetAttribute <SvgViewBox>("viewBox"); if (viewBox != SvgViewBox.Empty && Math.Abs(ew - viewBox.Width) > float.Epsilon && Math.Abs(eh - viewBox.Height) > float.Epsilon) { var sw = ew / viewBox.Width; var sh = eh / viewBox.Height; var skMatrixTranslateSWSH = SKMatrix.MakeTranslation(sw, sh); SKMatrix.PreConcat(ref skMatrix, ref skMatrixTranslateSWSH); } } } } var originalParent = svgUse.Parent; var useParent = svgUse.GetType().GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance); if (useParent != null) { useParent.SetValue(svgVisualElement, svgUse); } svgVisualElement.InvalidateChildPaths(); _skCanvas.Save(); SetTransform(skMatrix); SetClipPath(svgUse, _disposable); var skPaintOpacity = SetOpacity(svgUse, _disposable); var skPaintFilter = SetFilter(svgUse, _disposable); if (svgVisualElement is SvgSymbol svgSymbol) { DrawSymbol(svgSymbol, ignoreDisplay); } else { Draw(svgVisualElement, ignoreDisplay); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); if (useParent != null) { useParent.SetValue(svgVisualElement, originalParent); } }
public void DrawImage(SvgImage svgImage, bool ignoreDisplay) { if (!CanDraw(svgImage, ignoreDisplay)) { return; } float width = svgImage.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgImage); float height = svgImage.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgImage); var location = svgImage.Location.ToDeviceValue(null, svgImage); if (width <= 0f || height <= 0f || svgImage.Href == null) { return; } var image = SkiaUtil.GetImage(svgImage, svgImage.Href); var skImage = image as SKImage; var svgFragment = image as SvgFragment; if (skImage == null && svgFragment == null) { return; } if (skImage != null) { _disposable.Add(skImage); } SKRect srcRect = default; if (skImage != null) { srcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height); } if (svgFragment != null) { var skSize = SkiaUtil.GetDimensions(svgFragment); srcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height); } var destClip = SKRect.Create(location.X, location.Y, width, height); var destRect = destClip; var aspectRatio = svgImage.AspectRatio; if (aspectRatio.Align != SvgPreserveAspectRatio.none) { var fScaleX = destClip.Width / srcRect.Width; var fScaleY = destClip.Height / srcRect.Height; var xOffset = 0f; var yOffset = 0f; if (aspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } switch (aspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; break; case SvgPreserveAspectRatio.xMaxYMin: xOffset = (destClip.Width - srcRect.Width * fScaleX); break; case SvgPreserveAspectRatio.xMinYMid: yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMidYMid: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMaxYMid: xOffset = (destClip.Width - srcRect.Width * fScaleX); yOffset = (destClip.Height - srcRect.Height * fScaleY) / 2; break; case SvgPreserveAspectRatio.xMinYMax: yOffset = (destClip.Height - srcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMidYMax: xOffset = (destClip.Width - srcRect.Width * fScaleX) / 2; yOffset = (destClip.Height - srcRect.Height * fScaleY); break; case SvgPreserveAspectRatio.xMaxYMax: xOffset = (destClip.Width - srcRect.Width * fScaleX); yOffset = (destClip.Height - srcRect.Height * fScaleY); break; } destRect = SKRect.Create( destClip.Left + xOffset, destClip.Top + yOffset, srcRect.Width * fScaleX, srcRect.Height * fScaleY); } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgImage.Transforms); SetTransform(skMatrix); SetClipPath(svgImage, _disposable); var skPaintOpacity = SetOpacity(svgImage, _disposable); var skPaintFilter = SetFilter(svgImage, _disposable); _skCanvas.ClipRect(destClip, SKClipOperation.Intersect); SetClip(svgImage, destClip); if (skImage != null) { _skCanvas.DrawImage(skImage, srcRect, destRect); } if (svgFragment != null) { _skCanvas.Save(); float dx = destRect.Left; float dy = destRect.Top; float sx = destRect.Width / srcRect.Width; float sy = destRect.Height / srcRect.Height; var skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy); var skScaleMatrix = SKMatrix.MakeScale(sx, sy); SKMatrix.PreConcat(ref skTranslationMatrix, ref skScaleMatrix); SetTransform(skTranslationMatrix); DrawFragment(svgFragment, ignoreDisplay); _skCanvas.Restore(); } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
internal void DrawMarker(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle) { var markerElement = GetMarkerElement(svgMarker); if (markerElement == null) { return; } var skMarkerMatrix = SKMatrix.MakeIdentity(); var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(null, UnitRenderingType.Other, svgMarker); var refX = svgMarker.RefX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); var refY = svgMarker.RefY.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); float markerWidth = svgMarker.MarkerWidth; float markerHeight = svgMarker.MarkerHeight; float viewBoxToMarkerUnitsScaleX = 1f; float viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth); var viewBoxWidth = svgMarker.ViewBox.Width; var viewBoxHeight = svgMarker.ViewBox.Height; var scaleFactorWidth = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth); var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight); viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight); viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight); var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); } break; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgMarker.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMarkerMatrix); SetTransform(skMatrix); SetClipPath(svgMarker, _disposable); var skPaintOpacity = SetOpacity(svgMarker, _disposable); var skPaintFilter = SetFilter(svgMarker, _disposable); switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: var skClipRect = SKRect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect); break; } Draw(markerElement, true); if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawText(SvgText svgText, bool ignoreDisplay) { if (!CanDraw(svgText, ignoreDisplay)) { return; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgText.Transforms); SetTransform(skMatrix); SetClipPath(svgText, _disposable); var skPaintOpacity = SetOpacity(svgText, _disposable); var skPaintFilter = SetFilter(svgText, _disposable); // TODO: bool isValidFill = SkiaUtil.IsValidFill(svgText); bool isValidStroke = SkiaUtil.IsValidStroke(svgText); if (isValidFill || isValidStroke) { var text = svgText.Text?.Trim(); if (svgText.X.Count == 1 && svgText.Y.Count == 1 && !string.IsNullOrEmpty(text)) { // TODO: float x0 = svgText.X[0].ToDeviceValue(null, UnitRenderingType.HorizontalOffset, svgText); float y0 = svgText.Y[0].ToDeviceValue(null, UnitRenderingType.VerticalOffset, svgText); // TODO: var skBounds = SKRect.Create(0f, 0f, _skSize.Width, _skSize.Height); if (SkiaUtil.IsValidFill(svgText)) { var skPaint = SkiaUtil.GetFillSKPaint(svgText, _skSize, skBounds, _disposable); SkiaUtil.SetSKPaintText(svgText, _skSize, skBounds, skPaint, _disposable); _skCanvas.DrawText(text, x0, y0, skPaint); } if (SkiaUtil.IsValidStroke(svgText)) { var skPaint = SkiaUtil.GetStrokeSKPaint(svgText, _skSize, skBounds, _disposable); SkiaUtil.SetSKPaintText(svgText, _skSize, skBounds, skPaint, _disposable); _skCanvas.DrawText(text, x0, y0, skPaint); } } } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public void DrawRectangle(SvgRectangle svgRectangle, bool ignoreDisplay) { if (!CanDraw(svgRectangle, ignoreDisplay)) { return; } float x = svgRectangle.X.ToDeviceValue(null, UnitRenderingType.Horizontal, svgRectangle); float y = svgRectangle.Y.ToDeviceValue(null, UnitRenderingType.Vertical, svgRectangle); float width = svgRectangle.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgRectangle); float height = svgRectangle.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgRectangle); float rx = svgRectangle.CornerRadiusX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgRectangle); float ry = svgRectangle.CornerRadiusY.ToDeviceValue(null, UnitRenderingType.Vertical, svgRectangle); if (width <= 0f || height <= 0f || rx < 0f || ry < 0f) { return; } if (rx > 0f) { float halfWidth = width / 2f; if (rx > halfWidth) { rx = halfWidth; } } if (ry > 0f) { float halfHeight = height / 2f; if (ry > halfHeight) { ry = halfHeight; } } bool isRound = rx > 0f && ry > 0f; var skRectBounds = SKRect.Create(x, y, width, height); _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgRectangle.Transforms); SetTransform(skMatrix); SetClipPath(svgRectangle, _disposable); var skPaintOpacity = SetOpacity(svgRectangle, _disposable); var skPaintFilter = SetFilter(svgRectangle, _disposable); if (SkiaUtil.IsValidFill(svgRectangle)) { var skPaintFill = SkiaUtil.GetFillSKPaint(svgRectangle, _skSize, skRectBounds, _disposable); if (isRound) { _skCanvas.DrawRoundRect(x, y, width, height, rx, ry, skPaintFill); } else { _skCanvas.DrawRect(x, y, width, height, skPaintFill); } } if (SkiaUtil.IsValidStroke(svgRectangle)) { var skPaintStroke = SkiaUtil.GetStrokeSKPaint(svgRectangle, _skSize, skRectBounds, _disposable); if (isRound) { _skCanvas.DrawRoundRect(skRectBounds, rx, ry, skPaintStroke); } else { _skCanvas.DrawRect(skRectBounds, skPaintStroke); } } if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }