public static Rect ToRect(ISvgRect rect) { if (rect == null) { return Rect.Empty; } return new Rect(rect.X, rect.Y, rect.Width, rect.Height); }
public void Resize() { // TODO: Invalidate! Fire SVGResize x = null; y = null; width = null; height = null; currentView = null; cachedViewBoxTransform = null; viewport = null; svgFitToViewBox = null; svgFitToViewBox = new SvgFitToViewBox(this); if (this == OwnerDocument.RootElement) { // TODO } else { (OwnerDocument.RootElement as SvgSvgElement).Resize(); } }
/// <summary> /// Returns true if the rendered content of the given element intersects the supplied /// rectangle, honoring the 'pointer-events' property value on each candidate graphics /// element. /// </summary> /// <param name="element">The element on which to perform the given test.</param> /// <param name="rect">The test rectangle. The values are in the initial coordinate system /// for the current 'svg' element.</param> /// <returns>True or false, depending on whether the given element intersects the supplied /// rectangle.</returns> public bool CheckIntersection(ISvgElement element, ISvgRect rect) { throw new NotImplementedException(); }
/// <summary> /// Returns the list of graphics elements whose rendered content intersects the supplied /// rectangle, honoring the 'pointer-events' property value on each candidate graphics /// element. /// </summary> /// <param name="rect">The test rectangle. The values are in the initial coordinate /// system for the current 'svg' element.</param> /// <param name="referenceElement">If not null, then only return elements whose drawing /// order has them below the given reference element.</param> /// <returns>A list of Elements whose content intersects the supplied rectangle.</returns> public XmlNodeList GetIntersectionList(ISvgRect rect, ISvgElement referenceElement) { throw new NotImplementedException(); }
protected void SetClip(GdiGraphics graphics) { if (_svgElement == null) { return; } SvgRenderingHint hint = _svgElement.RenderingHint; // todo: should we correct the clipping to adjust to the off-one-pixel drawing? graphics.TranslateClip(1, 1); #region Clip with clip // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties if (_svgElement is ISvgSvgElement || _svgElement is ISvgMarkerElement || _svgElement is ISvgSymbolElement || _svgElement is ISvgPatternElement) { // check overflow property CssValue overflow = _svgElement.GetComputedCssValue("overflow", string.Empty) as CssValue; // TODO: clip can have "rect(10 10 auto 10)" CssPrimitiveValue clip = _svgElement.GetComputedCssValue("clip", string.Empty) as CssPrimitiveValue; string sOverflow = null; if (overflow != null || overflow.CssText == "") { sOverflow = overflow.CssText; } else { if (this is ISvgSvgElement) { sOverflow = "hidden"; } } if (sOverflow != null) { // "If the 'overflow' property has a value other than hidden or scroll, the property has no effect (i.e., a clipping rectangle is not created)." if (sOverflow == "hidden" || sOverflow == "scroll") { RectangleF clipRect = RectangleF.Empty; if (clip != null && clip.PrimitiveType == CssPrimitiveType.Rect) { if (_svgElement is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)_svgElement; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = GdiConverter.ToRectangle(viewPort); ICssRect clipShape = (CssRect)clip.GetRectValue(); if (clipShape.Top.PrimitiveType != CssPrimitiveType.Ident) { clipRect.Y += (float)clipShape.Top.GetFloatValue(CssPrimitiveType.Number); } if (clipShape.Left.PrimitiveType != CssPrimitiveType.Ident) { clipRect.X += (float)clipShape.Left.GetFloatValue(CssPrimitiveType.Number); } if (clipShape.Right.PrimitiveType != CssPrimitiveType.Ident) { clipRect.Width = (clipRect.Right - clipRect.X) - (float)clipShape.Right.GetFloatValue(CssPrimitiveType.Number); } if (clipShape.Bottom.PrimitiveType != CssPrimitiveType.Ident) { clipRect.Height = (clipRect.Bottom - clipRect.Y) - (float)clipShape.Bottom.GetFloatValue(CssPrimitiveType.Number); } } } else if (clip == null || (clip.PrimitiveType == CssPrimitiveType.Ident && clip.GetStringValue() == "auto")) { if (_svgElement is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)_svgElement; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = GdiConverter.ToRectangle(viewPort); } else if (_svgElement is ISvgMarkerElement || _svgElement is ISvgSymbolElement || _svgElement is ISvgPatternElement) { // TODO: what to do here? } } if (clipRect != RectangleF.Empty) { graphics.SetClip(clipRect); } } } } #endregion #region Clip with clip-path // see: http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath if (hint == SvgRenderingHint.Shape || hint == SvgRenderingHint.Text || hint == SvgRenderingHint.Clipping || hint == SvgRenderingHint.Masking || hint == SvgRenderingHint.Containment || hint == SvgRenderingHint.Image) { CssPrimitiveValue clipPath = _svgElement.GetComputedCssValue("clip-path", string.Empty) as CssPrimitiveValue; if (clipPath != null && clipPath.PrimitiveType == CssPrimitiveType.Uri) { string absoluteUri = _svgElement.ResolveUri(clipPath.GetStringValue()); SvgClipPathElement eClipPath = _svgElement.OwnerDocument.GetNodeByUri(absoluteUri) as SvgClipPathElement; if (eClipPath != null) { GraphicsPath gpClip = CreateClippingRegion(graphics, eClipPath); RectangleF clipBounds = gpClip != null?gpClip.GetBounds() : RectangleF.Empty; if (clipBounds.Width.Equals(0) || clipBounds.Height.Equals(0)) { return; } SvgUnitType pathUnits = (SvgUnitType)eClipPath.ClipPathUnits.AnimVal; if (pathUnits == SvgUnitType.ObjectBoundingBox) { SvgTransformableElement transElement = _svgElement as SvgTransformableElement; if (transElement != null) { ISvgRect bbox = transElement.GetBBox(); // scale clipping path Matrix matrix = new Matrix(); matrix.Scale((float)bbox.Width, (float)bbox.Height); gpClip.Transform(matrix); graphics.SetClip(gpClip); // offset clip graphics.TranslateClip((float)bbox.X, (float)bbox.Y); } else { throw new NotImplementedException("clip-path with SvgUnitType.ObjectBoundingBox " + "not supported for this type of element: " + _svgElement.GetType()); } } else { graphics.SetClip(gpClip); } gpClip.Dispose(); gpClip = null; } } } #endregion }
/// <summary> /// Returns true if the rendered content of the given element is entirely contained within /// the supplied rectangle, honoring the 'pointer-events' property value on each candidate /// graphics element. /// </summary> /// <param name="element">The element on which to perform the given test</param> /// <param name="rect">The test rectangle. The values are in the initial coordinate system /// for the current 'svg' element.</param> /// <returns>True or false, depending on whether the given element is enclosed by the /// supplied rectangle.</returns> public bool CheckEnclosure(ISvgElement element, ISvgRect rect) { throw new NotImplementedException(); }
public override void BeforeRender(WpfDrawingRenderer renderer) { base.BeforeRender(renderer); _idElement = string.Empty; WpfDrawingContext context = renderer.Context; DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } if (currentGroup == context.Root) { if (context.IsFragment) { // Do not add extra layer to fragments... _drawGroup = currentGroup; } else { _drawGroup = new DrawingGroup(); SvgObject.SetName(_drawGroup, SvgObject.DrawLayer); if (context.IncludeRuntime) { SvgLink.SetKey(_drawGroup, SvgObject.DrawLayer); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } } else { _drawGroup = new DrawingGroup(); currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } SvgPatternElement svgElm = (SvgPatternElement)_svgElement; _idElement = svgElm.Id; if (!string.IsNullOrWhiteSpace(_idElement)) { context.AddUrl(_idElement); } double x = Math.Round(svgElm.X.AnimVal.Value, 4); double y = Math.Round(svgElm.Y.AnimVal.Value, 4); double width = Math.Round(svgElm.Width.AnimVal.Value, 4); double height = Math.Round(svgElm.Height.AnimVal.Value, 4); if (width < 0 || height < 0) { // For invalid dimension, prevent the drawing of the children... _isRecursive = true; return; } Rect elmRect = new Rect(x, y, width, height); // XmlNode parentNode = _svgElement.ParentNode; ISvgFitToViewBox fitToView = svgElm as ISvgFitToViewBox; ISvgAnimatedPreserveAspectRatio preserveAspectRatio = null; if (fitToView != null && fitToView.PreserveAspectRatio != null) { preserveAspectRatio = fitToView.PreserveAspectRatio; ISvgAnimatedRect animRect = fitToView.ViewBox; if (animRect != null) { ISvgRect viewRect = animRect.AnimVal; if (viewRect != null) { Rect wpfViewRect = WpfConvert.ToRect(viewRect); if (!wpfViewRect.IsEmpty && wpfViewRect.Width > 0 && wpfViewRect.Height > 0) { elmRect = wpfViewRect; } } } } Transform transform = null; var aspectRatio = (preserveAspectRatio != null) ? preserveAspectRatio.AnimVal : null; if (aspectRatio != null /* && aspectRatio.Align == SvgPreserveAspectRatioType.None*/) { FitToViewbox(context, elmRect); transform = this.Transform; if (transform != null) { _drawGroup.Transform = transform; } } }
public override void BeforeRender(WpfDrawingRenderer renderer) { base.BeforeRender(renderer); WpfDrawingContext context = renderer.Context; if (context.Count == 0) { _drawGroup = new DrawingGroup(); context.Push(_drawGroup); context.Root = _drawGroup; } else if (context.Count == 1) { DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } if (currentGroup == context.Root) { if (context.IsFragment) { // Do not add extra layer to fragments... _drawGroup = currentGroup; } else { _drawGroup = new DrawingGroup(); SvgObject.SetName(_drawGroup, SvgObject.DrawLayer); if (context.IncludeRuntime) { SvgLink.SetKey(_drawGroup, SvgObject.DrawLayer); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } } else { _drawGroup = new DrawingGroup(); currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } } else { _drawGroup = new DrawingGroup(); DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } SvgSvgElement svgElm = (SvgSvgElement)_svgElement; double x = Math.Round(svgElm.X.AnimVal.Value, 4); double y = Math.Round(svgElm.Y.AnimVal.Value, 4); double width = Math.Round(svgElm.Width.AnimVal.Value, 4); double height = Math.Round(svgElm.Height.AnimVal.Value, 4); if (width < 0 || height < 0) { // For invalid dimension, prevent the drawing of the children... _isRecursive = true; return; } Rect elmRect = new Rect(x, y, width, height); XmlNode parentNode = _svgElement.ParentNode; ISvgFitToViewBox fitToView = svgElm as ISvgFitToViewBox; ISvgAnimatedPreserveAspectRatio preserveAspectRatio = null; if (fitToView != null && fitToView.PreserveAspectRatio != null) { preserveAspectRatio = fitToView.PreserveAspectRatio; ISvgAnimatedRect animRect = fitToView.ViewBox; if (animRect != null) { ISvgRect viewRect = animRect.AnimVal; if (viewRect != null) { Rect wpfViewRect = WpfConvert.ToRect(viewRect); if (!wpfViewRect.IsEmpty && wpfViewRect.Width > 0 && wpfViewRect.Height > 0) { elmRect = wpfViewRect; } } } } Transform transform = null; var aspectRatio = (preserveAspectRatio != null) ? preserveAspectRatio.AnimVal : null; if (parentNode.NodeType != XmlNodeType.Document || (aspectRatio != null && aspectRatio.Align == SvgPreserveAspectRatioType.None)) { FitToViewbox(context, elmRect); transform = this.Transform; if (transform != null) { _drawGroup.Transform = transform; } } if (!elmRect.IsEmpty && !elmRect.Width.Equals(0) && !elmRect.Height.Equals(0)) { // Elements such as "pattern" are also rendered by this renderer, so we make sure we are // dealing with the root SVG element... if (parentNode != null && parentNode.NodeType == XmlNodeType.Document) { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } else { if (transform != null) { // We have already applied the transform, which will translate to the start point... if (transform is TranslateTransform) { //_drawGroup.ClipGeometry = new RectangleGeometry( // new Rect(0, 0, elmRect.Width, elmRect.Height)); } else { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } } else { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } } } }
/// <summary> /// Returns the list of graphics elements whose rendered content is entirely contained /// within the supplied rectangle, honoring the 'pointer-events' property value on each /// candidate graphics element. /// </summary> /// <param name="rect">The test rectangle. The values are in the initial coordinate system /// for the current 'svg' element.</param> /// <param name="referenceElement">If not null, then only return elements whose drawing /// order has them below the given reference element.</param> /// <returns>A list of Elements whose content is enclosed by the supplied /// rectangle.</returns> public XmlNodeList GetEnclosureList(ISvgRect rect, ISvgElement referenceElement) { throw new NotImplementedException(); }
public override void BeforeRender(WpfDrawingRenderer renderer) { base.BeforeRender(renderer); WpfDrawingContext context = renderer.Context; _drawGroup = new DrawingGroup(); if (context.Count == 0) { context.Push(_drawGroup); context.Root = _drawGroup; } else if (context.Count == 1) { DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } if (currentGroup == context.Root && !context.IsFragment) { _drawGroup.SetValue(FrameworkElement.NameProperty, SvgObject.DrawLayer); if (context.IncludeRuntime) { SvgLink.SetKey(_drawGroup, SvgObject.DrawLayer); } } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } else { DrawingGroup currentGroup = context.Peek(); if (currentGroup == null) { throw new InvalidOperationException("An existing group is expected."); } currentGroup.Children.Add(_drawGroup); context.Push(_drawGroup); } SvgSvgElement svgElm = (SvgSvgElement)_svgElement; double x = Math.Round(svgElm.X.AnimVal.Value, 4); double y = Math.Round(svgElm.Y.AnimVal.Value, 4); double width = Math.Round(svgElm.Width.AnimVal.Value, 4); double height = Math.Round(svgElm.Height.AnimVal.Value, 4); Rect elmRect = new Rect(x, y, width, height); //if (element.ParentNode is SvgElement) //{ // // TODO: should it be moved with x and y? //} XmlNode parentNode = _svgElement.ParentNode; //if (parentNode.NodeType == XmlNodeType.Document) { ISvgFitToViewBox fitToView = svgElm as ISvgFitToViewBox; if (fitToView != null) { ISvgAnimatedRect animRect = fitToView.ViewBox; if (animRect != null) { ISvgRect viewRect = animRect.AnimVal; if (viewRect != null) { Rect wpfViewRect = WpfConvert.ToRect(viewRect); if (!wpfViewRect.IsEmpty && wpfViewRect.Width > 0 && wpfViewRect.Height > 0) { elmRect = wpfViewRect; } } } } } Transform transform = null; if (parentNode.NodeType != XmlNodeType.Document) { FitToViewbox(context, elmRect); transform = this.Transform; if (transform != null) { _drawGroup.Transform = transform; } } //if (height > 0 && width > 0) //{ // ClipGeometry = new RectangleGeometry(elmRect); //} //Geometry clipGeom = this.ClipGeometry; //if (clipGeom != null) //{ // _drawGroup.ClipGeometry = clipGeom; //} if (((float)elmRect.Width != 0 && (float)elmRect.Height != 0)) { // Elements such as "pattern" are also rendered by this renderer, so we make sure we are // dealing with the root SVG element... if (parentNode != null && parentNode.NodeType == XmlNodeType.Document) { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } else { if (transform != null) { // We have already applied the transform, which will translate to the start point... if (transform is TranslateTransform) { _drawGroup.ClipGeometry = new RectangleGeometry( new Rect(0, 0, elmRect.Width, elmRect.Height)); } else { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } } else { _drawGroup.ClipGeometry = new RectangleGeometry(elmRect); } } //DrawingGroup animationGroup = context.Links; //if (animationGroup != null) //{ // animationGroup.ClipGeometry = clipGeom; //} } }
public override Brush GetBrush(Rect elementBounds, WpfDrawingContext context, Transform viewTransform) { Rect bounds = elementBounds; DrawingGroup image = this.GetImage(context, bounds); if (image == null || image.Bounds.Width.Equals(0) || image.Bounds.Height.Equals(0)) { return(null); } bool isUserSpace = true; if (_renderedElement.PatternContentUnits.AnimVal.Equals((ushort)SvgUnitType.ObjectBoundingBox)) { bounds = new Rect(0, 0, 1, 1); isUserSpace = false; } Rect destRect = GetDestRect(bounds); // Check for validity of the brush... if (destRect.Width.Equals(0) || destRect.Height.Equals(0) || destRect.IsEmpty) { return(null); } // Apply a scale if needed if (isUserSpace && image.Transform != null) { ISvgFitToViewBox fitToView = _renderedElement as ISvgFitToViewBox; if (fitToView != null && fitToView.ViewBox != null) { ISvgAnimatedRect animRect = fitToView.ViewBox; ISvgRect viewRect = animRect.AnimVal; if (viewRect != null) { Rect wpfViewRect = WpfConvert.ToRect(viewRect); if (!wpfViewRect.IsEmpty && wpfViewRect.Width > 0 && wpfViewRect.Height > 0) { var scaleX = elementBounds.Width > 0 ? destRect.Width / wpfViewRect.Width : 1; var scaleY = elementBounds.Height > 0 ? destRect.Height / wpfViewRect.Height : 1; if (!scaleX.Equals(1) || !scaleY.Equals(1)) { var currentTransform = image.Transform as ScaleTransform; if (currentTransform != null) { image.Transform = new ScaleTransform(scaleX, scaleY); } } } } } } DrawingBrush tb = new DrawingBrush(image); tb.Viewbox = destRect; tb.Viewport = destRect; //tb.Viewbox = new Rect(0, 0, destRect.Width, destRect.Height); //tb.Viewport = new Rect(0, 0, bounds.Width, bounds.Height); tb.ViewboxUnits = BrushMappingMode.Absolute; tb.ViewportUnits = isUserSpace ? BrushMappingMode.Absolute : BrushMappingMode.RelativeToBoundingBox; tb.TileMode = TileMode.Tile; // tb.Stretch = isUserSpace ? Stretch.Fill : Stretch.Uniform; if (isUserSpace) { MatrixTransform transform = GetTransformMatrix(image.Bounds, isUserSpace); if (transform != null && !transform.Matrix.IsIdentity) { tb.Transform = transform; } } else { MatrixTransform transform = GetTransformMatrix(bounds, isUserSpace); if (transform != null && !transform.Matrix.IsIdentity) { tb.RelativeTransform = transform; } } return(tb); }