protected void Clip(GraphicsWrapper gr) { // todo: should we correct the clipping to adjust to the off-one-pixel drawing? gr.TranslateClip(1,1); #region Clip with clip // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties if(element is ISvgSvgElement || element is ISvgMarkerElement || element is ISvgSymbolElement || element is ISvgPatternElement) { // check overflow property CssValue overflow = ((SvgElement)element).GetComputedCssValue("overflow", String.Empty) as CssValue; // TODO: clip can have "rect(10 10 auto 10)" CssPrimitiveValue clip = ((SvgElement)element).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(element is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)element; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = viewPort.ToRectangleF(); IRect clipShape = (Rect)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(element is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)element; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = viewPort.ToRectangleF(); } else if(element is ISvgMarkerElement || element is ISvgSymbolElement || element is ISvgPatternElement) { // TODO: what to do here? } } if(clipRect != RectangleF.Empty) { gr.SetClip(clipRect); } } } } #endregion #region Clip with clip-path // see: http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath if ( element is IGraphicsElement || element is IContainerElement) { CssPrimitiveValue clipPath = ((SvgElement)element).GetComputedCssValue("clip-path", String.Empty) as CssPrimitiveValue; if(clipPath != null && clipPath.PrimitiveType == CssPrimitiveType.Uri) { string absoluteUri = ((SvgElement)element).ResolveUri(clipPath.GetStringValue()); SvgClipPathElement eClipPath = ((SvgDocument)element.OwnerDocument).GetNodeByUri(absoluteUri) as SvgClipPathElement; if ( eClipPath != null ) { GraphicsPath gpClip = eClipPath.GetGraphicsPath(); SvgUnitType pathUnits = (SvgUnitType)eClipPath.ClipPathUnits.AnimVal; if ( pathUnits == SvgUnitType.ObjectBoundingBox ) { SvgTransformableElement transElement = element 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); gr.SetClip(gpClip); // offset clip gr.TranslateClip( (float)bbox.X, (float)bbox.Y ); } else { throw new NotImplementedException("clip-path with SvgUnitType.ObjectBoundingBox " + "not supported for this type of element: " + element.GetType()); } } else { gr.SetClip(gpClip); } } } } #endregion }
protected void Clip(GraphicsWrapper gr) { // todo: should we correct the clipping to adjust to the off-one-pixel drawing? gr.TranslateClip(1, 1); #region Clip with clip // see http://www.w3.org/TR/SVG/masking.html#OverflowAndClipProperties if (element is ISvgSvgElement || element is ISvgMarkerElement || element is ISvgSymbolElement || element is ISvgPatternElement) { // check overflow property CssValue overflow = ((SvgElement)element).GetComputedCssValue("overflow", String.Empty) as CssValue; // TODO: clip can have "rect(10 10 auto 10)" CssPrimitiveValue clip = ((SvgElement)element).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 (element is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)element; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = viewPort.ToRectangleF(); IRect clipShape = (Rect)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 (element is ISvgSvgElement) { ISvgSvgElement svgElement = (ISvgSvgElement)element; SvgRect viewPort = svgElement.Viewport as SvgRect; clipRect = viewPort.ToRectangleF(); } else if (element is ISvgMarkerElement || element is ISvgSymbolElement || element is ISvgPatternElement) { // TODO: what to do here? } } if (clipRect != RectangleF.Empty) { gr.SetClip(clipRect); } } } } #endregion #region Clip with clip-path // see: http://www.w3.org/TR/SVG/masking.html#EstablishingANewClippingPath if (element is IGraphicsElement || element is IContainerElement) { CssPrimitiveValue clipPath = ((SvgElement)element).GetComputedCssValue("clip-path", String.Empty) as CssPrimitiveValue; if (clipPath != null && clipPath.PrimitiveType == CssPrimitiveType.Uri) { string absoluteUri = ((SvgElement)element).ResolveUri(clipPath.GetStringValue()); SvgClipPathElement eClipPath = ((SvgDocument)element.OwnerDocument).GetNodeByUri(absoluteUri) as SvgClipPathElement; if (eClipPath != null) { GraphicsPath gpClip = eClipPath.GetGraphicsPath(); SvgUnitType pathUnits = (SvgUnitType)eClipPath.ClipPathUnits.AnimVal; if (pathUnits == SvgUnitType.ObjectBoundingBox) { SvgTransformableElement transElement = element 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); gr.SetClip(gpClip); // offset clip gr.TranslateClip((float)bbox.X, (float)bbox.Y); } else { throw new NotImplementedException("clip-path with SvgUnitType.ObjectBoundingBox " + "not supported for this type of element: " + element.GetType()); } } else { gr.SetClip(gpClip); } } } } #endregion }
public override void Render(ISvgRenderer renderer) { GdiRenderer gdiRenderer = renderer as GdiRenderer; GraphicsWrapper graphics = gdiRenderer.GraphicsWrapper; if (!(element is SvgClipPathElement) && !(element.ParentNode is SvgClipPathElement)) { SvgStyleableElement styleElm = element as SvgStyleableElement; if (styleElm != null) { string sVisibility = styleElm.GetPropertyValue("visibility"); string sDisplay = styleElm.GetPropertyValue("display"); if (element is ISharpGDIPath && sVisibility != "hidden" && sDisplay != "none") { GraphicsPath gp = ((ISharpGDIPath)element).GetGraphicsPath(); if (gp != null) { Clip(graphics); GdiSvgPaint fillPaint = new GdiSvgPaint(styleElm, "fill"); Brush brush = fillPaint.GetBrush(gp); GdiSvgPaint strokePaint = new GdiSvgPaint(styleElm, "stroke"); Pen pen = strokePaint.GetPen(gp); if (brush != null) { if (brush is PathGradientBrush) { GradientPaintServer gps = fillPaint.PaintServer as GradientPaintServer; //GraphicsContainer container = graphics.BeginContainer(); graphics.SetClip(gps.GetRadialGradientRegion(gp.GetBounds()), CombineMode.Exclude); SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)brush).InterpolationColors.Colors[0]); graphics.FillPath(this, tempBrush, gp); tempBrush.Dispose(); graphics.ResetClip(); //graphics.EndContainer(container); } graphics.FillPath(this, brush, gp); brush.Dispose(); } if (pen != null) { if (pen.Brush is PathGradientBrush) { GradientPaintServer gps = strokePaint.PaintServer as GradientPaintServer; GraphicsContainerWrapper container = graphics.BeginContainer(); graphics.SetClip(gps.GetRadialGradientRegion(gp.GetBounds()), CombineMode.Exclude); SolidBrush tempBrush = new SolidBrush(((PathGradientBrush)pen.Brush).InterpolationColors.Colors[0]); Pen tempPen = new Pen(tempBrush, pen.Width); graphics.DrawPath(this, tempPen, gp); tempPen.Dispose(); tempBrush.Dispose(); graphics.EndContainer(container); } graphics.DrawPath(this, pen, gp); pen.Dispose(); } } } PaintMarkers(gdiRenderer, styleElm, graphics); } } }