protected override void Render(ISvgRenderer renderer) { switch (this.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: base.Render(renderer); break; default: var prevClip = renderer.GetClip(); try { var size = (this.Parent == null ? renderer.GetBoundable().Bounds.Size : GetDimensions()); var clip = new RectangleF(this.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), this.Y.ToDeviceValue(renderer, UnitRenderingType.Vertical, this), size.Width, size.Height); renderer.SetClip(new Region(clip), CombineMode.Intersect); base.Render(renderer); } finally { renderer.SetClip(prevClip, CombineMode.Replace); } break; } }
/// <summary> /// Sets the clipping region of the specified <see cref="ISvgRenderer"/>. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region set.</param> protected internal virtual void SetClip(ISvgRenderer renderer) { if (this.ClipPath != null || !string.IsNullOrEmpty(this.Clip)) { this._previousClip = renderer.GetClip(); if (this.ClipPath != null) { SvgClipPath clipPath = this.OwnerDocument.GetElementById <SvgClipPath>(this.ClipPath.ToString()); if (clipPath != null) { renderer.SetClip(clipPath.GetClipRegion(this, renderer), CombineMode.Intersect); } } var clip = this.Clip; if (!string.IsNullOrEmpty(clip) && clip.StartsWith("rect(")) { clip = clip.Trim(); var offsets = (from o in clip.Substring(5, clip.Length - 6).Split(',') select float.Parse(o.Trim(), NumberStyles.Any, CultureInfo.InvariantCulture)).ToList(); var bounds = this.Bounds; var clipRect = new RectangleF(bounds.Left + offsets[3], bounds.Top + offsets[0], bounds.Width - (offsets[3] + offsets[1]), bounds.Height - (offsets[2] + offsets[0])); renderer.SetClip(new Region(clipRect), CombineMode.Intersect); } } }
public void ApplyFilter(SvgVisualElement element, ISvgRenderer renderer, Action <ISvgRenderer> renderMethod) { var inflate = 0.5f; var transform = GetTransform(element); var bounds = GetPathBounds(element, renderer, transform); if (bounds.Width == 0 || bounds.Height == 0) { return; } var buffer = new ImageBuffer(bounds, inflate, renderer, renderMethod) { Transform = transform }; foreach (var primitive in this.Children.OfType <SvgFilterPrimitive>()) { primitive.Process(buffer); } // Render the final filtered image var bufferImg = buffer.Buffer; var imgDraw = RectangleF.Inflate(bounds, inflate * bounds.Width, inflate * bounds.Height); var prevClip = renderer.GetClip(); renderer.SetClip(new Region(imgDraw)); renderer.DrawImage(bufferImg, imgDraw, new RectangleF(bounds.X, bounds.Y, imgDraw.Width, imgDraw.Height), GraphicsUnit.Pixel); renderer.SetClip(prevClip); }
/// <summary> /// Removes any previously applied transforms from the specified <see cref="ISvgRenderer"/>. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> that should have transforms removed.</param> protected internal virtual void PopTransforms(ISvgRenderer renderer) { renderer.Transform = _graphicsMatrix; _graphicsMatrix = null; renderer.SetClip(_graphicsClip); _graphicsClip = null; }
/// <summary> /// Resets the clipping region of the specified <see cref="ISvgRenderer"/> back to where it was before the <see cref="SetClip"/> method was called. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> to have its clipping region reset.</param> protected internal virtual void ResetClip(ISvgRenderer renderer) { if (this._previousClip != null) { renderer.SetClip(this._previousClip); this._previousClip = null; } }
/// <summary> /// Removes any previously applied transforms from the specified <see cref="ISvgRenderer"/>. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> that should have transforms removed.</param> protected internal virtual void PopTransforms(ISvgRenderer renderer) { renderer.Transform = _graphicsTransform; _graphicsTransform.Dispose(); _graphicsTransform = null; renderer.SetClip(_graphicsClip); _graphicsClip = null; }
public void AddViewBoxTransform(SvgAspectRatio aspectRatio, ISvgRenderer renderer, SvgFragment frag) { var x = (frag == null ? 0 : frag.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag)); var y = (frag == null ? 0 : frag.Y.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag)); if (this.Equals(SvgViewBox.Empty)) { renderer.TranslateTransform(x, y, MatrixOrder.Prepend); return; } var width = (frag == null ? this.Width : frag.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag)); var height = (frag == null ? this.Height : frag.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag)); var fScaleX = width / this.Width; var fScaleY = height / this.Height; //(this.MinY < 0 ? -1 : 1) * var fMinX = -this.MinX * fScaleX; var fMinY = -this.MinY * fScaleY; if (aspectRatio == null) { aspectRatio = new SvgAspectRatio(SvgPreserveAspectRatio.xMidYMid, false); } if (aspectRatio.Align != SvgPreserveAspectRatio.none) { if (aspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } float fViewMidX = (this.Width / 2) * fScaleX; float fViewMidY = (this.Height / 2) * fScaleY; float fMidX = width / 2; float fMidY = height / 2; fMinX = -this.MinX * fScaleX; fMinY = -this.MinY * fScaleY; switch (aspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: fMinX += fMidX - fViewMidX; break; case SvgPreserveAspectRatio.xMaxYMin: fMinX += width - this.Width * fScaleX; break; case SvgPreserveAspectRatio.xMinYMid: fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMidYMid: fMinX += fMidX - fViewMidX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMaxYMid: fMinX += width - this.Width * fScaleX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMinYMax: fMinY += height - this.Height * fScaleY; break; case SvgPreserveAspectRatio.xMidYMax: fMinX += fMidX - fViewMidX; fMinY += height - this.Height * fScaleY; break; case SvgPreserveAspectRatio.xMaxYMax: fMinX += width - this.Width * fScaleX; fMinY += height - this.Height * fScaleY; break; default: break; } } renderer.SetClip(new Region(new RectangleF(x, y, width, height)), CombineMode.Intersect); renderer.TranslateTransform(x, y, MatrixOrder.Prepend); renderer.TranslateTransform(fMinX, fMinY, MatrixOrder.Prepend); renderer.ScaleTransform(fScaleX, fScaleY, MatrixOrder.Prepend); }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// </summary> protected override void Render(ISvgRenderer renderer) { if (!Visible || !Displayable) { return; } if (Width.Value > 0.0f && Height.Value > 0.0f && this.Href != null) { var img = GetImage(); if (img != null) { RectangleF srcRect; var bmp = img as Bitmap; var svg = img as SvgFragment; if (bmp != null) { srcRect = new RectangleF(0, 0, bmp.Width, bmp.Height); } else if (svg != null) { srcRect = new RectangleF(new PointF(0, 0), svg.GetDimensions()); } else { return; } var destClip = new RectangleF(this.Location.ToDeviceValue(renderer, this), new SizeF(Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this))); RectangleF destRect = destClip; this.PushTransforms(renderer); renderer.SetClip(new Region(destClip), CombineMode.Intersect); this.SetClip(renderer); if (AspectRatio != null && AspectRatio.Align != SvgPreserveAspectRatio.none) { var fScaleX = destClip.Width / srcRect.Width; var fScaleY = destClip.Height / srcRect.Height; var xOffset = 0.0f; var yOffset = 0.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 = new RectangleF(destClip.X + xOffset, destClip.Y + yOffset, srcRect.Width * fScaleX, srcRect.Height * fScaleY); } if (bmp != null) { renderer.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel); bmp.Dispose(); } else if (svg != null) { var currOffset = new PointF(renderer.Transform.OffsetX, renderer.Transform.OffsetY); renderer.TranslateTransform(-currOffset.X, -currOffset.Y); renderer.ScaleTransform(destRect.Width / srcRect.Width, destRect.Height / srcRect.Height); renderer.TranslateTransform(currOffset.X + destRect.X, currOffset.Y + destRect.Y); renderer.SetBoundable(new GenericBoundable(srcRect)); svg.RenderElement(renderer); renderer.PopBoundable(); } this.ResetClip(renderer); this.PopTransforms(renderer); } // TODO: cache images... will need a shared context for this // TODO: support preserveAspectRatio, etc } }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// </summary> protected override void Render(ISvgRenderer renderer) { if (!(Visible && Displayable && Width.Value > 0f && Height.Value > 0f && Href != null)) { return; } var img = GetImage(Href); var bmp = img as Image; var svg = img as SvgFragment; if (bmp == null && svg == null) { return; } try { if (PushTransforms(renderer)) { RectangleF srcRect; if (bmp != null) { srcRect = new RectangleF(0f, 0f, bmp.Width, bmp.Height); } else { srcRect = new RectangleF(new PointF(0f, 0f), svg.GetDimensions()); } var destClip = new RectangleF(Location.ToDeviceValue(renderer, this), new SizeF(Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, this))); var destRect = destClip; renderer.SetClip(new Region(destClip), CombineMode.Intersect); SetClip(renderer); var aspectRatio = 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 = new RectangleF(destClip.X + xOffset, destClip.Y + yOffset, srcRect.Width * fScaleX, srcRect.Height * fScaleY); } if (bmp != null) { var opacity = FixOpacityValue(Opacity); if (opacity == 1f) { renderer.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel); } else { renderer.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel, opacity); } } else { renderer.TranslateTransform(destRect.X, destRect.Y, MatrixOrder.Prepend); renderer.ScaleTransform(destRect.Width / srcRect.Width, destRect.Height / srcRect.Height, MatrixOrder.Prepend); try { renderer.SetBoundable(new GenericBoundable(srcRect)); svg.RenderElement(renderer); } finally { renderer.PopBoundable(); } } ResetClip(renderer); } } finally { PopTransforms(renderer); if (bmp != null) { bmp.Dispose(); } } // TODO: cache images... will need a shared context for this }
protected override Brush CreateBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke) { // TODO: figure out how to do the brush transform in the presence of FocalRadius try { if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.SetBoundable(renderingElement); } // Calculate the path and transform it appropriately var center = new PointF(NormalizeUnit(CenterX).ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), NormalizeUnit(CenterY).ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); var focals = new PointF[] { new PointF(NormalizeUnit(FocalX).ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), NormalizeUnit(FocalY).ToDeviceValue(renderer, UnitRenderingType.Vertical, this)) }; var specifiedRadius = NormalizeUnit(Radius).ToDeviceValue(renderer, UnitRenderingType.Other, this); var path = new GraphicsPath(); path.AddEllipse( center.X - specifiedRadius, center.Y - specifiedRadius, specifiedRadius * 2, specifiedRadius * 2 ); using (var transform = EffectiveGradientTransform) { var bounds = renderer.GetBoundable().Bounds; transform.Translate(bounds.X, bounds.Y, MatrixOrder.Prepend); if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { transform.Scale(bounds.Width, bounds.Height, MatrixOrder.Prepend); } path.Transform(transform); transform.TransformPoints(focals); } // Calculate any required scaling var scaleBounds = RectangleF.Inflate(renderingElement.Bounds, renderingElement.StrokeWidth, renderingElement.StrokeWidth); var scale = CalcScale(scaleBounds, path); // Not ideal, but this makes sure that the rest of the shape gets properly filled or drawn if (scale > 1.0f && SpreadMethod == SvgGradientSpreadMethod.Pad) { var stop = Stops.Last(); var origColor = stop.GetColor(renderingElement); var renderColor = System.Drawing.Color.FromArgb((int)Math.Round(opacity * stop.StopOpacity * 255), origColor); var origClip = renderer.GetClip(); try { using (var solidBrush = new SolidBrush(renderColor)) { var newClip = origClip.Clone(); newClip.Exclude(path); renderer.SetClip(newClip); var renderPath = (GraphicsPath)renderingElement.Path(renderer); if (forStroke) { using (var pen = new Pen(solidBrush, renderingElement.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, renderingElement))) { renderer.DrawPath(pen, renderPath); } } else { renderer.FillPath(solidBrush, renderPath); } } } finally { renderer.SetClip(origClip); } } // Get the color blend and any tweak to the scaling var blend = CalculateColorBlend(renderer, opacity, scale, out scale); // Transform the path based on the scaling var gradBounds = path.GetBounds(); var transCenter = new PointF(gradBounds.Left + gradBounds.Width / 2, gradBounds.Top + gradBounds.Height / 2); using (var scaleMat = new Matrix()) { scaleMat.Translate(-1 * transCenter.X, -1 * transCenter.Y, MatrixOrder.Append); scaleMat.Scale(scale, scale, MatrixOrder.Append); scaleMat.Translate(transCenter.X, transCenter.Y, MatrixOrder.Append); path.Transform(scaleMat); } // calculate the brush var brush = new PathGradientBrush(path); brush.CenterPoint = focals[0]; brush.InterpolationColors = blend; return(brush); } finally { if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.PopBoundable(); } } }
public void AddViewBoxTransform(SvgAspectRatio aspectRatio, ISvgRenderer renderer, SvgFragment frag) { var x = (frag == null ? 0 : frag.X.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag)); var y = (frag == null ? 0 : frag.Y.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag)); if (this.Equals(SvgViewBox.Empty)) { renderer.TranslateTransform(x, y); return; } var width = (frag == null ? this.Width : frag.Width.ToDeviceValue(renderer, UnitRenderingType.Horizontal, frag)); var height = (frag == null ? this.Height : frag.Height.ToDeviceValue(renderer, UnitRenderingType.Vertical, frag)); var fScaleX = width / this.Width; var fScaleY = height / this.Height; //(this.MinY < 0 ? -1 : 1) * var fMinX = -this.MinX * fScaleX; var fMinY = -this.MinY * fScaleY; if (aspectRatio == null) aspectRatio = new SvgAspectRatio(SvgPreserveAspectRatio.xMidYMid, false); if (aspectRatio.Align != SvgPreserveAspectRatio.none) { if (aspectRatio.Slice) { fScaleX = Math.Max(fScaleX, fScaleY); fScaleY = Math.Max(fScaleX, fScaleY); } else { fScaleX = Math.Min(fScaleX, fScaleY); fScaleY = Math.Min(fScaleX, fScaleY); } float fViewMidX = (this.Width / 2) * fScaleX; float fViewMidY = (this.Height / 2) * fScaleY; float fMidX = width / 2; float fMidY = height / 2; fMinX = -this.MinX * fScaleX; fMinY = -this.MinY * fScaleY; switch (aspectRatio.Align) { case SvgPreserveAspectRatio.xMinYMin: break; case SvgPreserveAspectRatio.xMidYMin: fMinX += fMidX - fViewMidX; break; case SvgPreserveAspectRatio.xMaxYMin: fMinX += width - this.Width * fScaleX; break; case SvgPreserveAspectRatio.xMinYMid: fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMidYMid: fMinX += fMidX - fViewMidX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMaxYMid: fMinX += width - this.Width * fScaleX; fMinY += fMidY - fViewMidY; break; case SvgPreserveAspectRatio.xMinYMax: fMinY += height - this.Height * fScaleY; break; case SvgPreserveAspectRatio.xMidYMax: fMinX += fMidX - fViewMidX; fMinY += height - this.Height * fScaleY; break; case SvgPreserveAspectRatio.xMaxYMax: fMinX += width - this.Width * fScaleX; fMinY += height - this.Height * fScaleY; break; default: break; } } renderer.SetClip(new Region(new RectangleF(x, y, width, height)), CombineMode.Intersect); renderer.ScaleTransform(fScaleX, fScaleY, MatrixOrder.Prepend); renderer.TranslateTransform(x, y); renderer.TranslateTransform(fMinX, fMinY); }
public void SetClip(Region region, CombineMode combineMode = CombineMode.Replace) { _svgRendererImplementation.SetClip(region, combineMode); }