public override void Render(ISvgRenderer renderer) { GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; SvgImageElement iElement = (SvgImageElement)element; //HttpResource resource = iElement.ReferencedResource; /*if (resource != null ) * {*/ ImageAttributes imageAttributes = new ImageAttributes(); string sOpacity = iElement.GetPropertyValue("opacity"); if (sOpacity.Length > 0) { double opacity = SvgNumber.ParseToFloat(sOpacity); ColorMatrix myColorMatrix = new ColorMatrix(); myColorMatrix.Matrix00 = 1.00f; // Red myColorMatrix.Matrix11 = 1.00f; // Green myColorMatrix.Matrix22 = 1.00f; // Blue myColorMatrix.Matrix33 = (float)opacity; // alpha myColorMatrix.Matrix44 = 1.00f; // w imageAttributes.SetColorMatrix(myColorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); } float width = (float)iElement.Width.AnimVal.Value; float height = (float)iElement.Height.AnimVal.Value; Rectangle destRect = new Rectangle(); destRect.X = Convert.ToInt32(iElement.X.AnimVal.Value); destRect.Y = Convert.ToInt32(iElement.Y.AnimVal.Value); destRect.Width = Convert.ToInt32(width); destRect.Height = Convert.ToInt32(height); Image image; if (iElement.IsSvgImage) { SvgWindow wnd = getSvgWindow(); gdiRenderer.BackColor = Color.Empty; gdiRenderer.Render(wnd.Document as SvgDocument); //wnd.Render(); image = gdiRenderer.RasterImage; image.Save(@"c:\inlinesvg.png", ImageFormat.Png); } else { image = iElement.Bitmap; } if (image != null) { graphics.DrawImage(this, image, destRect, 0f, 0f, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes); } //} }
public override void BeforeRender(ISvgRenderer renderer) { if (_uniqueColor.IsEmpty) { _uniqueColor = ((GdiRenderer)renderer)._getNextColor(this); } GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; graphicsContainer = graphics.BeginContainer(); SetQuality(graphics); Transform(graphics); }
public override void Render(ISvgRenderer renderer) { GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; SvgSvgElement svgElm = (SvgSvgElement)element; float x = (float)svgElm.X.AnimVal.Value; float y = (float)svgElm.Y.AnimVal.Value; float width = (float)svgElm.Width.AnimVal.Value; float height = (float)svgElm.Height.AnimVal.Value; RectangleF elmRect = new RectangleF(x, y, width, height); fitToViewbox(graphics, elmRect); }
protected void fitToViewbox(GraphicsWrapper graphics, RectangleF elmRect) { if (element is ISvgFitToViewBox) { ISvgFitToViewBox fitToVBElm = (ISvgFitToViewBox)element; SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)fitToVBElm.PreserveAspectRatio.AnimVal; float[] translateAndScale = spar.FitToViewBox( (SvgRect)fitToVBElm.ViewBox.AnimVal, new SvgRect(elmRect.X, elmRect.Y, elmRect.Width, elmRect.Height) ); graphics.TranslateTransform(translateAndScale[0], translateAndScale[1]); graphics.ScaleTransform(translateAndScale[2], translateAndScale[3]); } }
/// <summary> /// AfterRender - Dispose of Graphics object created for rendering. /// </summary> private void RendererAfterRender() { if (graphics != null) { // Check if we only invalidated a rect if (invalidRect != RectangleF.Empty && invalidatedRasterImage != null) { // We actually drew everything on invalidatedRasterImage and now we // need to copy that to rasterImage Graphics tempGraphics = Graphics.FromImage(rasterImage); tempGraphics.DrawImage(invalidatedRasterImage, invalidRect.X, invalidRect.Y, invalidRect, GraphicsUnit.Pixel); tempGraphics.Dispose(); tempGraphics = null; // If we currently have an idMapRaster here, then we need to create // a temporary graphics object to draw the invalidated portion from // our main graphics window onto it. if (idMapRaster != null) { tempGraphics = Graphics.FromImage(idMapRaster); tempGraphics.DrawImage(graphics.IdMapRaster, invalidRect.X, invalidRect.Y, invalidRect, GraphicsUnit.Pixel); tempGraphics.Dispose(); tempGraphics = null; } else { idMapRaster = graphics.IdMapRaster; } // We have updated the invalid region invalidRect = RectangleF.Empty; } else { if (idMapRaster != null && idMapRaster != graphics.IdMapRaster) { idMapRaster.Dispose(); } idMapRaster = graphics.IdMapRaster; } graphics.Dispose(); graphics = null; } }
public override void Render(ISvgRenderer renderer) { GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; SvgSvgElement svgElm = (SvgSvgElement)element; float x = (float)svgElm.X.AnimVal.Value; float y = (float)svgElm.Y.AnimVal.Value; float width = (float)svgElm.Width.AnimVal.Value; float height = (float)svgElm.Height.AnimVal.Value; RectangleF elmRect = new RectangleF(x, y, width, height); if (element.ParentNode is SvgElement) { // TODO: should it be moved with x and y? } fitToViewbox(graphics, elmRect); }
protected void Transform(GraphicsWrapper gr) { if (element is ISvgTransformable) { if (TransformMatrix == null) { ISvgTransformable transElm = (ISvgTransformable)element; SvgTransformList svgTList = (SvgTransformList)transElm.Transform.AnimVal; //SvgTransform svgTransform = (SvgTransform)svgTList.Consolidate(); SvgMatrix svgMatrix = ((SvgTransformList)transElm.Transform.AnimVal).TotalMatrix; TransformMatrix = new Matrix( (float)svgMatrix.A, (float)svgMatrix.B, (float)svgMatrix.C, (float)svgMatrix.D, (float)svgMatrix.E, (float)svgMatrix.F); } gr.Transform = TransformMatrix; } }
protected void SetQuality(GraphicsWrapper gr) { Graphics graphics = gr.Graphics; string colorRendering = ((SvgElement)element).GetComputedStringValue("color-rendering", String.Empty); switch (colorRendering) { case "optimizeSpeed": graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; break; case "optimizeQuality": graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; break; default: // "auto" // todo: could use AssumeLinear for slightly better graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default; break; } if (element is SvgTextContentElement) { // Unfortunately the text rendering hints are not applied because the // text path is recorded and painted to the Graphics object as a path // not as text. string textRendering = ((SvgElement)element).GetComputedStringValue("text-rendering", String.Empty); switch (textRendering) { case "optimizeSpeed": graphics.SmoothingMode = SmoothingMode.HighSpeed; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; break; case "optimizeLegibility": graphics.SmoothingMode = SmoothingMode.HighQuality; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; break; case "geometricPrecision": graphics.SmoothingMode = SmoothingMode.AntiAlias; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; break; default: // "auto" graphics.SmoothingMode = SmoothingMode.AntiAlias; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault; break; } } else { string shapeRendering = ((SvgElement)element).GetComputedStringValue("shape-rendering", String.Empty); switch (shapeRendering) { case "optimizeSpeed": graphics.SmoothingMode = SmoothingMode.HighSpeed; break; case "crispEdges": graphics.SmoothingMode = SmoothingMode.None; break; case "geometricPrecision": graphics.SmoothingMode = SmoothingMode.HighQuality; break; default: // "auto" graphics.SmoothingMode = SmoothingMode.AntiAlias; break; } } }
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 Transform(GraphicsWrapper gr) { if ( element is ISvgTransformable ) { if ( TransformMatrix == null ) { ISvgTransformable transElm = (ISvgTransformable) element; SvgTransformList svgTList = (SvgTransformList)transElm.Transform.AnimVal; //SvgTransform svgTransform = (SvgTransform)svgTList.Consolidate(); SvgMatrix svgMatrix = ((SvgTransformList)transElm.Transform.AnimVal).TotalMatrix; TransformMatrix = new Matrix( (float) svgMatrix.A, (float) svgMatrix.B, (float) svgMatrix.C, (float) svgMatrix.D, (float) svgMatrix.E, (float) svgMatrix.F); } gr.Transform = TransformMatrix; } }
protected void SetQuality(GraphicsWrapper gr) { Graphics graphics = gr.Graphics; string colorRendering = ((SvgElement)element).GetComputedStringValue("color-rendering", String.Empty); switch(colorRendering) { case "optimizeSpeed": graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; break; case "optimizeQuality": graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; break; default: // "auto" // todo: could use AssumeLinear for slightly better graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.Default; break; } if (element is SvgTextContentElement) { // Unfortunately the text rendering hints are not applied because the // text path is recorded and painted to the Graphics object as a path // not as text. string textRendering = ((SvgElement)element).GetComputedStringValue("text-rendering", String.Empty); switch(textRendering) { case "optimizeSpeed": graphics.SmoothingMode = SmoothingMode.HighSpeed; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel; break; case "optimizeLegibility": graphics.SmoothingMode = SmoothingMode.HighQuality; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; break; case "geometricPrecision": graphics.SmoothingMode = SmoothingMode.AntiAlias; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; break; default: // "auto" graphics.SmoothingMode = SmoothingMode.AntiAlias; //graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault; break; } } else { string shapeRendering = ((SvgElement)element).GetComputedStringValue("shape-rendering", String.Empty); switch(shapeRendering) { case "optimizeSpeed": graphics.SmoothingMode = SmoothingMode.HighSpeed; break; case "crispEdges": graphics.SmoothingMode = SmoothingMode.None; break; case "geometricPrecision": graphics.SmoothingMode = SmoothingMode.HighQuality; break; default: // "auto" graphics.SmoothingMode = SmoothingMode.AntiAlias; break; } } }
public void PaintMarker(GdiRenderer renderer, GraphicsWrapper gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement) element; PointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length-1; len = 1; break; } for ( int i = start; i<start+len; i++ ) { PointF point = vertexPositions[i]; GraphicsContainerWrapper gc = gr.BeginContainer(); gr.TranslateTransform(point.X, point.Y); if ( markerElm.OrientType.AnimVal.Equals(SvgMarkerOrient.Angle) ) { gr.RotateTransform((float)markerElm.OrientAngle.AnimVal.Value); } else { float angle; switch(markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } gr.RotateTransform(angle); } if ( markerElm.MarkerUnits.AnimVal.Equals(SvgMarkerUnit.StrokeWidth) ) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); float strokeWidth = (float)strokeWidthLength.Value; gr.ScaleTransform(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; float[] translateAndScale = spar.FitToViewBox( (SvgRect)markerElm.ViewBox.AnimVal, new SvgRect( 0, 0, (float)markerElm.MarkerWidth.AnimVal.Value, (float)markerElm.MarkerHeight.AnimVal.Value) ); gr.TranslateTransform( -(float)markerElm.RefX.AnimVal.Value * translateAndScale[2], -(float)markerElm.RefY.AnimVal.Value * translateAndScale[3] ); gr.ScaleTransform(translateAndScale[2], translateAndScale[3]); Clip(gr); markerElm.RenderChildren(renderer); gr.EndContainer(gc); } }
public void PaintMarker(GdiRenderer renderer, GraphicsWrapper gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)element; PointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { PointF point = vertexPositions[i]; GraphicsContainerWrapper gc = gr.BeginContainer(); gr.TranslateTransform(point.X, point.Y); if (markerElm.OrientType.AnimVal.Equals(SvgMarkerOrient.Angle)) { gr.RotateTransform((float)markerElm.OrientAngle.AnimVal.Value); } else { float angle; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } gr.RotateTransform(angle); } if (markerElm.MarkerUnits.AnimVal.Equals(SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); float strokeWidth = (float)strokeWidthLength.Value; gr.ScaleTransform(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; float[] translateAndScale = spar.FitToViewBox( (SvgRect)markerElm.ViewBox.AnimVal, new SvgRect( 0, 0, (float)markerElm.MarkerWidth.AnimVal.Value, (float)markerElm.MarkerHeight.AnimVal.Value) ); gr.TranslateTransform( -(float)markerElm.RefX.AnimVal.Value * translateAndScale[2], -(float)markerElm.RefY.AnimVal.Value * translateAndScale[3] ); gr.ScaleTransform(translateAndScale[2], translateAndScale[3]); Clip(gr); markerElm.RenderChildren(renderer); gr.EndContainer(gc); } }
private void PaintMarkers(GdiRenderer renderer, SvgStyleableElement styleElm, GraphicsWrapper gr) { // OPTIMIZE if ( styleElm is ISharpMarkerHost ) { string markerStartUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-start", "marker")); string markerMiddleUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-mid", "marker")); string markerEndUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-end", "marker")); RenderingNode grNode; if ( markerStartUrl.Length > 0 ) { grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerStartUrl); if (grNode is SvgMarkerGraphicsNode) { ((SvgMarkerGraphicsNode) grNode).PaintMarker(renderer, gr, SvgMarkerPosition.Start, styleElm); } } if ( markerMiddleUrl.Length > 0 ) { // TODO markerMiddleUrl != markerStartUrl grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerMiddleUrl); if ( grNode is SvgMarkerGraphicsNode ) { ((SvgMarkerGraphicsNode) grNode).PaintMarker(renderer, gr, SvgMarkerPosition.Mid, styleElm); } } if ( markerEndUrl.Length > 0 ) { // TODO: markerEndUrl != markerMiddleUrl grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerEndUrl); if(grNode is SvgMarkerGraphicsNode) { ((SvgMarkerGraphicsNode) grNode).PaintMarker(renderer, gr, SvgMarkerPosition.End, styleElm); } } } }
/// <summary> /// BeforeRender - Make sure we have a Graphics object to render to. /// If we don't have one, then create one to matche the SvgWindow's /// physical dimensions. /// </summary> internal void RendererBeforeRender() { // Testing for null here allows "advanced" developers to create their own Graphics object for rendering if (graphics == null) { // Get the current SVGWindow's width and height int innerWidth = (int)window.InnerWidth; int innerHeight = (int)window.InnerHeight; // Make sure we have an actual area to render to if (innerWidth > 0 && innerHeight > 0) { // See if we already have a rasterImage that matches the current SVGWindow dimensions if (rasterImage == null || rasterImage.Width != innerWidth || rasterImage.Height != innerHeight) { // Nope, so create one if (rasterImage != null) { rasterImage.Dispose(); rasterImage = null; } rasterImage = new Bitmap(innerWidth, innerHeight); } // Maybe we are only repainting an invalidated section if (invalidRect != RectangleF.Empty) { // TODO: Worry about pan... if (invalidRect.X < 0) { invalidRect.X = 0; } if (invalidRect.Y < 0) { invalidRect.Y = 0; } if (invalidRect.Right > innerWidth) { invalidRect.Width = innerWidth - invalidRect.X; } if (invalidRect.Bottom > innerHeight) { invalidRect.Height = innerHeight - invalidRect.Y; } if (invalidatedRasterImage == null || invalidatedRasterImage.Width < invalidRect.Right || invalidatedRasterImage.Height < invalidRect.Bottom) { // Nope, so create one if (invalidatedRasterImage != null) { invalidatedRasterImage.Dispose(); invalidatedRasterImage = null; } invalidatedRasterImage = new Bitmap((int)invalidRect.Right, (int)invalidRect.Bottom); } // Make a GraphicsWrapper object from the regionRasterImage and clear it to the background color graphics = GraphicsWrapper.FromImage(invalidatedRasterImage, false); graphics.Clear(backColor); } else { // Make a GraphicsWrapper object from the rasterImage and clear it to the background color graphics = GraphicsWrapper.FromImage(rasterImage, false); graphics.Clear(backColor); } } } }
private void PaintMarkers(GdiRenderer renderer, SvgStyleableElement styleElm, GraphicsWrapper gr) { // OPTIMIZE if (styleElm is ISharpMarkerHost) { string markerStartUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-start", "marker")); string markerMiddleUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-mid", "marker")); string markerEndUrl = extractMarkerUrl(styleElm.GetPropertyValue("marker-end", "marker")); RenderingNode grNode; if (markerStartUrl.Length > 0) { grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerStartUrl); if (grNode is SvgMarkerGraphicsNode) { ((SvgMarkerGraphicsNode)grNode).PaintMarker(renderer, gr, SvgMarkerPosition.Start, styleElm); } } if (markerMiddleUrl.Length > 0) { // TODO markerMiddleUrl != markerStartUrl grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerMiddleUrl); if (grNode is SvgMarkerGraphicsNode) { ((SvgMarkerGraphicsNode)grNode).PaintMarker(renderer, gr, SvgMarkerPosition.Mid, styleElm); } } if (markerEndUrl.Length > 0) { // TODO: markerEndUrl != markerMiddleUrl grNode = renderer.GetGraphicsNodeByUri(styleElm.BaseURI, markerEndUrl); if (grNode is SvgMarkerGraphicsNode) { ((SvgMarkerGraphicsNode)grNode).PaintMarker(renderer, gr, SvgMarkerPosition.End, styleElm); } } } }
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); } } }
public override void AfterRender(ISvgRenderer renderer) { GraphicsWrapper graphics = ((GdiRenderer)renderer).GraphicsWrapper; graphics.EndContainer(graphicsContainer); }
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 }
/// <summary> /// AfterRender - Dispose of Graphics object created for rendering. /// </summary> private void RendererAfterRender() { if (graphics != null) { // Check if we only invalidated a rect if (invalidRect != RectangleF.Empty) { // We actually drew everything on invalidatedRasterImage and now we // need to copy that to rasterImage Graphics tempGraphics = Graphics.FromImage(rasterImage); tempGraphics.DrawImage(invalidatedRasterImage, invalidRect.X, invalidRect.Y, invalidRect, GraphicsUnit.Pixel); tempGraphics.Dispose(); tempGraphics = null; // If we currently have an idMapRaster here, then we need to create // a temporary graphics object to draw the invalidated portion from // our main graphics window onto it. if (idMapRaster != null) { tempGraphics = Graphics.FromImage(idMapRaster); tempGraphics.DrawImage(graphics.IdMapRaster, invalidRect.X, invalidRect.Y, invalidRect, GraphicsUnit.Pixel); tempGraphics.Dispose(); tempGraphics = null; } else { idMapRaster = graphics.IdMapRaster; } // We have updated the invalid region invalidRect = RectangleF.Empty; } else { if (idMapRaster != null && idMapRaster != graphics.IdMapRaster) idMapRaster.Dispose(); idMapRaster = graphics.IdMapRaster; } graphics.Dispose(); graphics = null; } }
protected void fitToViewbox(GraphicsWrapper graphics, RectangleF elmRect) { if ( element is ISvgFitToViewBox ) { ISvgFitToViewBox fitToVBElm = (ISvgFitToViewBox) element; SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)fitToVBElm.PreserveAspectRatio.AnimVal; float[] translateAndScale = spar.FitToViewBox( (SvgRect)fitToVBElm.ViewBox.AnimVal, new SvgRect(elmRect.X, elmRect.Y, elmRect.Width, elmRect.Height) ); graphics.TranslateTransform(translateAndScale[0], translateAndScale[1]); graphics.ScaleTransform(translateAndScale[2], translateAndScale[3]); } }
/// <summary> /// BeforeRender - Make sure we have a Graphics object to render to. /// If we don't have one, then create one to matche the SvgWindow's /// physical dimensions. /// </summary> internal void RendererBeforeRender() { // Testing for null here allows "advanced" developers to create their own Graphics object for rendering if (graphics == null) { // Get the current SVGWindow's width and height int innerWidth = (int)window.InnerWidth; int innerHeight = (int)window.InnerHeight; // Make sure we have an actual area to render to if (innerWidth > 0 && innerHeight > 0) { // See if we already have a rasterImage that matches the current SVGWindow dimensions if (rasterImage == null || rasterImage.Width != innerWidth || rasterImage.Height != innerHeight) { // Nope, so create one if (rasterImage != null) { rasterImage.Dispose(); rasterImage = null; } rasterImage = new Bitmap(innerWidth, innerHeight); } // Maybe we are only repainting an invalidated section if (invalidRect != RectangleF.Empty) { // TODO: Worry about pan... if (invalidRect.X < 0) invalidRect.X = 0; if (invalidRect.Y < 0) invalidRect.Y = 0; if (invalidRect.Right > innerWidth) invalidRect.Width = innerWidth-invalidRect.X; if (invalidRect.Bottom > innerHeight) invalidRect.Height = innerHeight-invalidRect.Y; if (invalidatedRasterImage == null || invalidatedRasterImage.Width < invalidRect.Right || invalidatedRasterImage.Height < invalidRect.Bottom) { // Nope, so create one if (invalidatedRasterImage != null) { invalidatedRasterImage.Dispose(); invalidatedRasterImage = null; } invalidatedRasterImage = new Bitmap((int)invalidRect.Right, (int)invalidRect.Bottom); } // Make a GraphicsWrapper object from the regionRasterImage and clear it to the background color graphics = GraphicsWrapper.FromImage(invalidatedRasterImage, false); graphics.Clear(backColor); } else { // Make a GraphicsWrapper object from the rasterImage and clear it to the background color graphics = GraphicsWrapper.FromImage(rasterImage, false); graphics.Clear(backColor); } } } }