private void RenderInternal(ISvgRenderer renderer, bool renderFilter) { if (!(renderFilter && RenderFilter(renderer))) { var opacity = FixOpacityValue(Opacity); if (opacity == 1f) { RenderInternal(renderer); } else { IsPathDirty = true; var bounds = Renderable ? Bounds : Path(null).GetBounds(); IsPathDirty = true; if (bounds.Width > 0f && bounds.Height > 0f) { using (var canvas = new Bitmap((int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height))) { using (var canvasRenderer = SvgRenderer.FromImage(canvas)) { canvasRenderer.SetBoundable(renderer.GetBoundable()); canvasRenderer.TranslateTransform(-bounds.X, -bounds.Y); RenderInternal(canvasRenderer); } var srcRect = new RectangleF(0f, 0f, bounds.Width, bounds.Height); renderer.DrawImage(canvas, bounds, srcRect, GraphicsUnit.Pixel, opacity); } } } } }
/// <summary> /// Initializes the <see cref="SvgText"/> class. /// </summary> static SvgText() { Bitmap bitmap = new Bitmap(1, 1); _stringMeasure = SvgRenderer.FromImage(bitmap); _stringMeasure.TextRenderingHint = TextRenderingHint.AntiAlias; }
/// <summary> /// Renders the <see cref="SvgDocument"/> and returns the image as a <see cref="Bitmap"/>. /// </summary> /// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns> public virtual Bitmap Draw() { //Trace.TraceInformation("Begin Render"); var size = GetDimensions(); var bitmap = new Bitmap((int)Math.Ceiling(size.Width), (int)Math.Ceiling(size.Height)); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.TextRenderingHint = TextRenderingHint.AntiAlias; renderer.TextContrast = 1; renderer.PixelOffsetMode = PixelOffsetMode.Half; this.Render(renderer); renderer.Save(); } } catch { bitmap.Dispose(); throw; } //Trace.TraceInformation("End Render"); return(bitmap); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.SetBoundable(new GenericBoundable(0, 0, bitmap.Width, bitmap.Height)); //EO, 2014-12-05: Requested to ensure proper zooming (draw the svg in the bitmap size, ==> proper scaling) //EO, 2015-01-09, Added GetDimensions to use its returned size instead of this.Width and this.Height (request of Icarrere). SizeF size = this.GetDimensions(); renderer.ScaleTransform(bitmap.Width / size.Width, bitmap.Height / size.Height); //EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image. this.Overflow = SvgOverflow.auto; this.Render(renderer); } } catch { throw; } //Trace.TraceInformation("End Render"); }
/// <summary> /// Renders the <see cref="SvgDocument"/> in given size and returns the image as a <see cref="Bitmap"/>. /// If one of rasterWidth and rasterHeight is zero, the image is scaled preserving aspect ratio, /// otherwise the aspect ratio is ignored. /// </summary> /// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns> public virtual Bitmap Draw(int rasterWidth, int rasterHeight) { var imageSize = GetDimensions(); var bitmapSize = imageSize; RasterizeDimensions(ref bitmapSize, rasterWidth, rasterHeight); if (bitmapSize.Width == 0 || bitmapSize.Height == 0) { return(null); } var bitmap = new Bitmap((int)Math.Round(bitmapSize.Width), (int)Math.Round(bitmapSize.Height)); try { var renderer = SvgRenderer.FromImage(bitmap); renderer.ScaleTransform(bitmapSize.Width / imageSize.Width, bitmapSize.Height / imageSize.Height); Draw(renderer); } catch { bitmap.Dispose(); throw; } return(bitmap); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.SetBoundable(new GenericBoundable(0, 0, bitmap.Width, bitmap.Height)); //EO, 2014-12-05: Requested to ensure proper zooming (draw the svg in the bitmap size, ==> proper scaling) //EO, 2015-01-09, Added GetDimensions to use its returned size instead of this.Width and this.Height (request of Icarrere). //BBN, 2015-07-29, it is unnecassary to call again GetDimensions and transform to 1x1 //JA, 2015-12-18, this is actually necessary to correctly render the Draw(rasterHeight, rasterWidth) overload, otherwise the rendered graphic doesn't scale correctly SizeF size = this.GetDimensions(); renderer.ScaleTransform(bitmap.Width / size.Width, bitmap.Height / size.Height); //EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image. this.Overflow = SvgOverflow.Auto; this.Render(renderer); } } catch { throw; } //Trace.TraceInformation("End Render"); }
private void Render(ISvgRenderer renderer, bool renderFilter) { if (Visible && Displayable && (!Renderable || Path(renderer) != null)) { if (!(renderFilter && RenderFilter(renderer))) { try { if (PushTransforms(renderer)) { SetClip(renderer); if (Renderable) { var opacity = Math.Min(Math.Max(Opacity, 0f), 1f); if (opacity == 1f) { RenderFillAndStroke(renderer); } else { IsPathDirty = true; var bounds = Bounds; IsPathDirty = true; if (bounds.Width > 0f && bounds.Height > 0f) { using (var canvas = new Bitmap((int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height))) { using (var canvasRenderer = SvgRenderer.FromImage(canvas)) { canvasRenderer.SetBoundable(renderer.GetBoundable()); canvasRenderer.TranslateTransform(-bounds.X, -bounds.Y); RenderFillAndStroke(canvasRenderer); } var srcRect = new RectangleF(0f, 0f, bounds.Width, bounds.Height); renderer.DrawImage(canvas, bounds, srcRect, GraphicsUnit.Pixel, opacity); } } } } else { RenderChildren(renderer); } ResetClip(renderer); } } finally { PopTransforms(renderer); } } } }
public void TestRenderRect() { var doc = new SvgBuilder().OpenPath("rect.svg"); using (var bmp = new Bitmap(800, 800)) { var render = SvgRenderer.FromImage(bmp); doc.RenderElement(render); } }
/// <summary> /// Gets a <see cref="Brush"/> representing the current paint server. /// </summary> /// <param name="styleOwner">The owner <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the brush.</param> public override Brush GetBrush(SvgVisualElement renderingElement, SvgRenderer renderer, float opacity) { // If there aren't any children, return null if (this.Children.Count == 0) { return(null); } // Can't render if there are no dimensions if (this._width.Value == 0.0f || this._height.Value == 0.0f) { return(null); } float width = this._width.ToDeviceValue(renderingElement); float height = this._height.ToDeviceValue(renderingElement, true); Bitmap image = new Bitmap((int)width, (int)height); using (SvgRenderer texture_renderer = SvgRenderer.FromImage(image)) using (Matrix patternMatrix = new Matrix()) { // Apply a translate if needed if (this._x.Value > 0.0f || this._y.Value > 0.0f) { patternMatrix.Translate(this._x.ToDeviceValue(renderingElement) + -1.0f, this._y.ToDeviceValue(renderingElement, true) + -1.0f); } else { patternMatrix.Translate(-1, -1); } if (this.ViewBox.Height > 0 || this.ViewBox.Width > 0) { patternMatrix.Scale(this.Width.ToDeviceValue() / this.ViewBox.Width, this.Height.ToDeviceValue() / this.ViewBox.Height); } texture_renderer.Transform = patternMatrix; texture_renderer.CompositingQuality = CompositingQuality.HighQuality; texture_renderer.SmoothingMode = SmoothingMode.AntiAlias; texture_renderer.PixelOffsetMode = PixelOffsetMode.Half; texture_renderer.KnockoutBrush = renderer.KnockoutBrush; foreach (SvgElement child in this.Children) { child.RenderElement(texture_renderer); } texture_renderer.Save(); } TextureBrush textureBrush = new TextureBrush(image); return(textureBrush); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); using (var renderer = SvgRenderer.FromImage(bitmap)) { var boundable = new GenericBoundable(0, 0, bitmap.Width, bitmap.Height); this.Draw(renderer, boundable); } //Trace.TraceInformation("End Render"); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.TextRenderingHint = TextRenderingHint.AntiAlias; renderer.TextContrast = 1; renderer.PixelOffsetMode = PixelOffsetMode.Half; this.Render(renderer); renderer.Save(); } //Trace.TraceInformation("End Render"); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); using (var renderer = SvgRenderer.FromImage(bitmap)) { // EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image. this.Overflow = SvgOverflow.Auto; var boundable = new GenericBoundable(0, 0, bitmap.Width, bitmap.Height); this.Draw(renderer, boundable); } //Trace.TraceInformation("End Render"); }
private void Render(ISvgRenderer renderer, bool renderFilter) { if (this.Visible && this.Displayable && this.PushTransforms(renderer) && (!this.Renderable || this.Path(renderer) != null)) { if (!(renderFilter && this.RenderFilter(renderer))) { this.SetClip(renderer); if (this.Renderable) { var opacity = Math.Min(Math.Max(this.Opacity, 0), 1); if (opacity == 1f) { this.RenderFillAndStroke(renderer); } else { IsPathDirty = true; var bounds = this.Bounds; IsPathDirty = true; using (var canvas = new Bitmap((int)Math.Ceiling(bounds.Width), (int)Math.Ceiling(bounds.Height))) { using (var canvasRenderer = SvgRenderer.FromImage(canvas)) { canvasRenderer.SetBoundable(renderer.GetBoundable()); canvasRenderer.TranslateTransform(-bounds.X, -bounds.Y); this.RenderFillAndStroke(canvasRenderer); } var srcRect = new RectangleF(0f, 0f, bounds.Width, bounds.Height); renderer.DrawImage(canvas, bounds, srcRect, GraphicsUnit.Pixel, opacity); } } } else { base.RenderChildren(renderer); } this.ResetClip(renderer); this.PopTransforms(renderer); } } }
/// <summary> /// Renders the <see cref="SvgDocument"/> in given size and returns the image as a <see cref="Bitmap"/>. /// If one of rasterWidth and rasterHeight is zero, the image is scaled preserving aspect ratio, /// otherwise the aspect ratio is ignored. /// </summary> /// <returns>A <see cref="Bitmap"/> containing the rendered document.</returns> public virtual Bitmap Draw(int rasterWidth, int rasterHeight) { var imageSize = GetDimensions(); var bitmapSize = imageSize; this.RasterizeDimensions(ref bitmapSize, rasterWidth, rasterHeight); if (bitmapSize.Width == 0 || bitmapSize.Height == 0) { return(null); } Bitmap bitmap = null; try { try { bitmap = new Bitmap((int)Math.Round(bitmapSize.Width), (int)Math.Round(bitmapSize.Height)); } catch (ArgumentException e) { // When processing too many files at one the system can run out of memory throw new SvgMemoryException("Cannot process SVG file, cannot allocate the required memory", e); } using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.ScaleTransform(bitmapSize.Width / imageSize.Width, bitmapSize.Height / imageSize.Height); var boundable = new GenericBoundable(0, 0, imageSize.Width, imageSize.Height); this.Draw(renderer, boundable); } } catch { if (bitmap != null) { bitmap.Dispose(); } throw; } return(bitmap); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.SetBoundable(new GenericBoundable(0, 0, bitmap.Width, bitmap.Height)); this.Render(renderer); } } catch { throw; } //Trace.TraceInformation("End Render"); }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap) { //Trace.TraceInformation("Begin Render"); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.Boundable(new GenericBoundable(0, 0, bitmap.Width, bitmap.Height)); renderer.TextRenderingHint = TextRenderingHint.AntiAlias; renderer.TextContrast = 1; renderer.PixelOffsetMode = PixelOffsetMode.Half; this.Render(renderer); renderer.Save(); } } catch { throw; } //Trace.TraceInformation("End Render"); }
public void SaveJPEG(String filepath, Int32 DPI = 300) { Int32 oldDPI = Ppi; Ppi = DPI; // Int32 m_rate = Convert.ToInt32(DPI.GetRatio(Ppi)); Int32 w = Convert.ToInt32(Width.ToDeviceValue()); Int32 h = Convert.ToInt32(Height.ToDeviceValue()); Bitmap bitmap = new Bitmap(w, h); SvgRenderer renderer = SvgRenderer.FromImage(bitmap); // ImageFormatConverter.StandardValuesCollection; // ImageConverter imageConverter = new ImageConverter.StandardValuesCollection; Render(renderer); bitmap.Save(filepath, ImageFormat.Jpeg); Ppi = oldDPI; }
/// <summary> /// Renders the <see cref="SvgDocument"/> into a given Bitmap <see cref="Bitmap"/>. /// </summary> public virtual void Draw(Bitmap bitmap, bool wireframe = false) { //Trace.TraceInformation("Begin Render"); try { using (var renderer = SvgRenderer.FromImage(bitmap)) { renderer.Wireframe = wireframe; renderer.SetBoundable(new GenericBoundable(0, 0, bitmap.Width, bitmap.Height)); //EO, 2014-12-05: Requested to ensure proper zooming out (reduce size). Otherwise it clip the image. this.Overflow = SvgOverflow.Auto; this.Render(renderer); } } catch { throw; } //Trace.TraceInformation("End Render"); }
/// <summary> /// Gets a <see cref="Brush"/> representing the current paint server. /// </summary> /// <param name="renderingElement">The owner <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the brush.</param> public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke = false) { var chain = new List <SvgPatternServer>(); var curr = this; while (curr != null) { chain.Add(curr); curr = SvgDeferredPaintServer.TryGet <SvgPatternServer>(curr._inheritGradient, renderingElement); } var childElem = chain.Where((p) => p.Children != null && p.Children.Count > 0).FirstOrDefault(); if (childElem == null) { return(null); } var widthElem = chain.Where((p) => p.Width != null && p.Width != SvgUnit.None).FirstOrDefault(); var heightElem = chain.Where((p) => p.Height != null && p.Height != SvgUnit.None).FirstOrDefault(); if (widthElem == null && heightElem == null) { return(null); } var viewBoxElem = chain.Where((p) => p.ViewBox != null && p.ViewBox != SvgViewBox.Empty).FirstOrDefault(); var viewBox = viewBoxElem == null ? SvgViewBox.Empty : viewBoxElem.ViewBox; var xElem = chain.Where((p) => p.X != null && p.X != SvgUnit.None).FirstOrDefault(); var yElem = chain.Where((p) => p.Y != null && p.Y != SvgUnit.None).FirstOrDefault(); var xUnit = xElem == null ? SvgUnit.Empty : xElem.X; var yUnit = yElem == null ? SvgUnit.Empty : yElem.Y; var patternUnitElem = chain.Where((p) => p.PatternUnits != SvgCoordinateUnits.Inherit).FirstOrDefault(); var patternUnits = (patternUnitElem == null ? SvgCoordinateUnits.ObjectBoundingBox : patternUnitElem.PatternUnits); var patternContentUnitElem = chain.Where((p) => p.PatternContentUnits != SvgCoordinateUnits.Inherit).FirstOrDefault(); var patternContentUnits = (patternContentUnitElem == null ? SvgCoordinateUnits.UserSpaceOnUse : patternContentUnitElem.PatternContentUnits); try { if (patternUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.SetBoundable(renderingElement); } using (var patternMatrix = new Matrix()) { var bounds = renderer.GetBoundable().Bounds; var xScale = (patternUnits == SvgCoordinateUnits.ObjectBoundingBox ? bounds.Width : 1); var yScale = (patternUnits == SvgCoordinateUnits.ObjectBoundingBox ? bounds.Height : 1); float x = xScale * NormalizeUnit(xUnit).ToDeviceValue(renderer, UnitRenderingType.Horizontal, this); float y = yScale * NormalizeUnit(yUnit).ToDeviceValue(renderer, UnitRenderingType.Vertical, this); float width = xScale * NormalizeUnit(widthElem.Width).ToDeviceValue(renderer, UnitRenderingType.Horizontal, this); float height = yScale * NormalizeUnit(heightElem.Height).ToDeviceValue(renderer, UnitRenderingType.Vertical, this); // Apply a scale if needed patternMatrix.Scale((patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox ? bounds.Width : 1) * (viewBox.Width > 0 ? width / viewBox.Width : 1), (patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox ? bounds.Height : 1) * (viewBox.Height > 0 ? height / viewBox.Height : 1), MatrixOrder.Prepend); Bitmap image = new Bitmap((int)width, (int)height); using (var iRenderer = SvgRenderer.FromImage(image)) { iRenderer.SetBoundable((_patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox) ? new GenericBoundable(0, 0, width, height) : renderer.GetBoundable()); iRenderer.Transform = patternMatrix; iRenderer.SmoothingMode = SmoothingMode.AntiAlias; iRenderer.SetClip(new Region(new RectangleF(0, 0, viewBox.Width > 0 ? viewBox.Width : width, viewBox.Height > 0 ? viewBox.Height : height))); foreach (SvgElement child in childElem.Children) { child.RenderElement(iRenderer); } } TextureBrush textureBrush = new TextureBrush(image); var brushTransform = EffectivePatternTransform.Clone(); brushTransform.Translate(x, y, MatrixOrder.Append); textureBrush.Transform = brushTransform; return(textureBrush); } } finally { if (this.PatternUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.PopBoundable(); } } }
public static ISvgRenderer FromNull() { var img = new Bitmap(1, 1); return(SvgRenderer.FromImage(img)); }
/// <summary> /// Gets a <see cref="Brush"/> representing the current paint server. /// </summary> /// <param name="renderingElement">The owner <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the brush.</param> public override Brush GetBrush(SvgVisualElement renderingElement, SvgRenderer renderer, float opacity) { // If there aren't any children, return null if (this.Children.Count == 0) { return(null); } // Can't render if there are no dimensions if (this._width.Value == 0.0f || this._height.Value == 0.0f) { return(null); } try { if (this.PatternUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.Boundable(renderingElement); } float width = this._width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this); float height = this._height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); Matrix patternMatrix = new Matrix(); // Apply a translate if needed if (this._x.Value > 0.0f || this._y.Value > 0.0f) { float x = this._x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, this); float y = this._y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, this); patternMatrix.Translate(x + -1.0f, y + -1.0f); } else { patternMatrix.Translate(-1, -1); } if (this.ViewBox.Height > 0 || this.ViewBox.Width > 0) { patternMatrix.Scale(this.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this) / this.ViewBox.Width, this.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this) / this.ViewBox.Height); } Bitmap image = new Bitmap((int)width, (int)height); using (SvgRenderer iRenderer = SvgRenderer.FromImage(image)) { iRenderer.Boundable((_patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox) ? new GenericBoundable(0, 0, width, height) : renderer.Boundable()); iRenderer.Transform = patternMatrix; iRenderer.CompositingQuality = CompositingQuality.HighQuality; iRenderer.SmoothingMode = SmoothingMode.AntiAlias; iRenderer.PixelOffsetMode = PixelOffsetMode.Half; foreach (SvgElement child in this.Children) { child.RenderElement(iRenderer); } iRenderer.Save(); } image.Save(string.Format(@"C:\test{0:D3}.png", imgNumber++)); TextureBrush textureBrush = new TextureBrush(image); return(textureBrush); } finally { if (this.PatternUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.PopBoundable(); } } }
private void RenderInternal(ISvgRenderer renderer, bool renderFilter) { if (!(renderFilter && RenderFilter(renderer))) { var opacity = FixOpacityValue(Opacity); if (opacity == 1f) { if (Renderable) { RenderInternal(renderer, RenderFillAndStroke); } else { RenderInternal(renderer, RenderChildren); } } else { IsPathDirty = true; var bounds = Renderable ? Bounds : Path(null).GetBounds(); IsPathDirty = true; if (bounds.Width > 0f && bounds.Height > 0f) { var scaleX = 1f; var scaleY = 1f; using (var transform = renderer.Transform) { scaleX = Math.Max(scaleX, Math.Abs(transform.Elements[0])); scaleY = Math.Max(scaleY, Math.Abs(transform.Elements[3])); } using (var canvas = new Bitmap((int)Math.Ceiling(bounds.Width * scaleX), (int)Math.Ceiling(bounds.Height * scaleY))) { using (var canvasRenderer = SvgRenderer.FromImage(canvas)) { canvasRenderer.SetBoundable(renderer.GetBoundable()); canvasRenderer.TranslateTransform(-bounds.X, -bounds.Y); canvasRenderer.ScaleTransform(scaleX, scaleY); if (Renderable) { RenderInternal(canvasRenderer, RenderFillAndStroke); } else { RenderChildren(canvasRenderer); } } var srcRect = new RectangleF(0f, 0f, bounds.Width * scaleX, bounds.Height * scaleY); if (Renderable) { renderer.DrawImage(canvas, bounds, srcRect, GraphicsUnit.Pixel, opacity); } else { RenderInternal(renderer, r => r.DrawImage(canvas, bounds, srcRect, GraphicsUnit.Pixel, opacity)); } } } } } }
/// <summary> /// Gets a <see cref="Brush"/> representing the current paint server. /// </summary> /// <param name="renderingElement">The owner <see cref="SvgVisualElement"/>.</param> /// <param name="renderer">The renderer object.</param> /// <param name="opacity">The opacity of the brush.</param> /// <param name="forStroke">Not used.</param> public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke = false) { var chain = new List <SvgPatternServer>(); var curr = this; do { chain.Add(curr); curr = SvgDeferredPaintServer.TryGet <SvgPatternServer>(curr.InheritGradient, renderingElement); } while (curr != null); var firstChildren = chain.Where(p => p.Children.Count > 0).FirstOrDefault(); if (firstChildren == null) { return(null); } var firstX = chain.Where(p => p.X != null && p.X != SvgUnit.None).FirstOrDefault(); var firstY = chain.Where(p => p.Y != null && p.Y != SvgUnit.None).FirstOrDefault(); var firstWidth = chain.Where(p => p.Width != null && p.Width != SvgUnit.None).FirstOrDefault(); var firstHeight = chain.Where(p => p.Height != null && p.Height != SvgUnit.None).FirstOrDefault(); if (firstWidth == null || firstHeight == null) { return(null); } var firstPatternUnit = chain.Where(p => p.PatternUnits != SvgCoordinateUnits.Inherit).FirstOrDefault(); var firstPatternContentUnit = chain.Where(p => p.PatternContentUnits != SvgCoordinateUnits.Inherit).FirstOrDefault(); var firstViewBox = chain.Where(p => p.ViewBox != null && p.ViewBox != SvgViewBox.Empty).FirstOrDefault(); var xUnit = firstX == null ? new SvgUnit(0f) : firstX.X; var yUnit = firstY == null ? new SvgUnit(0f) : firstY.Y; var widthUnit = firstWidth.Width; var heightUnit = firstHeight.Height; var patternUnits = firstPatternUnit == null ? SvgCoordinateUnits.ObjectBoundingBox : firstPatternUnit.PatternUnits; var patternContentUnits = firstPatternContentUnit == null ? SvgCoordinateUnits.UserSpaceOnUse : firstPatternContentUnit.PatternContentUnits; var viewBox = firstViewBox == null ? SvgViewBox.Empty : firstViewBox.ViewBox; var isPatternObjectBoundingBox = patternUnits == SvgCoordinateUnits.ObjectBoundingBox; try { if (isPatternObjectBoundingBox) { renderer.SetBoundable(renderingElement); } var x = xUnit.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this); var y = yUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); var width = widthUnit.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this); var height = heightUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); if (isPatternObjectBoundingBox) { var bounds = renderer.GetBoundable().Bounds; // Boundary without stroke is expect... if (xUnit.Type != SvgUnitType.Percentage) { x *= bounds.Width; } if (yUnit.Type != SvgUnitType.Percentage) { y *= bounds.Height; } if (widthUnit.Type != SvgUnitType.Percentage) { width *= bounds.Width; } if (heightUnit.Type != SvgUnitType.Percentage) { height *= bounds.Height; } x += bounds.X; y += bounds.Y; } var tile = new Bitmap((int)Math.Ceiling(width), (int)Math.Ceiling(height)); using (var tileRenderer = SvgRenderer.FromImage(tile)) { tileRenderer.SetBoundable(renderingElement); if (viewBox != SvgViewBox.Empty) { var bounds = tileRenderer.GetBoundable().Bounds; tileRenderer.ScaleTransform(width / viewBox.Width, height / viewBox.Height); } else if (patternContentUnits == SvgCoordinateUnits.ObjectBoundingBox) { var bounds = tileRenderer.GetBoundable().Bounds; tileRenderer.ScaleTransform(bounds.Width, bounds.Height); } foreach (var child in firstChildren.Children) { child.RenderElement(tileRenderer); } } using (var transform = EffectivePatternTransform) { var textureBrush = new TextureBrush(tile, new RectangleF(0f, 0f, width, height)) { Transform = transform }; textureBrush.TranslateTransform(x, y); return(textureBrush); } } finally { if (isPatternObjectBoundingBox) { renderer.PopBoundable(); } } }