//Baseline calculation to match http://bobpowell.net/formattingtext.aspx public float Ascent(ISvgRenderer renderer) { var ff = _font.FontFamily; float ascent = ff.GetCellAscent(_font.Style); float baselineOffset = _font.SizeInPoints / ff.GetEmHeight(_font.Style) * ascent; return renderer.DpiY / 72f * baselineOffset; }
public override GraphicsPath Path(ISvgRenderer renderer) { if (_Path == null || this.IsPathDirty) { _Path = new GraphicsPath(); try { for (int i = 0; (i + 1) < Points.Count; i += 2) { PointF endPoint = new PointF(Points[i].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), Points[i + 1].ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); // TODO: Remove unrequired first line if (_Path.PointCount == 0) { _Path.AddLine(endPoint, endPoint); } else { _Path.AddLine(_Path.GetLastPoint(), endPoint); } } } catch (Exception exc) { Trace.TraceError("Error rendering points: " + exc.Message); } this.IsPathDirty = false; } return _Path; }
public System.Drawing.SizeF MeasureString(ISvgRenderer renderer, string text) { var result = new List<RectangleF>(); using (var path = GetPath(renderer, text, result, true)) { } var nonEmpty = result.Where(r => r != RectangleF.Empty); if (!nonEmpty.Any()) return SizeF.Empty; return new SizeF(nonEmpty.Last().Right - nonEmpty.First().Left, Ascent(renderer)); }
public SvgPictureBoxWindow(SvgPictureBox control, ISvgRenderer renderer) : base(control.Width, control.Height, renderer) { if (control == null) { throw new NullReferenceException("control cannot be null"); } _svgPictureBox = control; }
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 SizeF MeasureString(ISvgRenderer renderer, string text) { var g = GetGraphics(renderer); StringFormat format = StringFormat.GenericTypographic.Clone() as StringFormat; format.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, text.Length)}); format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; Region[] r = g.MeasureCharacterRanges(text, _font, new Rectangle(0, 0, 1000, 1000), format); RectangleF rect = r[0].GetBounds(g); return new SizeF(rect.Width, Ascent(renderer)); }
protected SvgWindow(long innerWidth, long innerHeight, ISvgRenderer renderer) { this.renderer = renderer; if (this.renderer != null) { this.renderer.Window = this; } this.innerWidth = innerWidth; this.innerHeight = innerHeight; }
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 void AddStringToPath(ISvgRenderer renderer, GraphicsPath path, string text, PointF location) { var textPath = GetPath(renderer, text, null, false); if (textPath.PointCount > 0) { using (var translate = new Matrix()) { translate.Translate(location.X, location.Y); textPath.Transform(translate); path.AddPath(textPath, false); } } }
private GraphicsPath GetPath(ISvgRenderer renderer, string text, IList<RectangleF> ranges, bool measureSpaces) { EnsureDictionaries(); RectangleF bounds; SvgGlyph glyph; SvgKern kern; GraphicsPath path; SvgGlyph prevGlyph = null; Matrix scaleMatrix; float xPos = 0; var ascent = Ascent(renderer); var result = new GraphicsPath(); if (string.IsNullOrEmpty(text)) return result; for (int i = 0; i < text.Length; i++) { if (!_glyphs.TryGetValue(text.Substring(i, 1), out glyph)) glyph = _font.Descendants().OfType<SvgMissingGlyph>().First(); if (prevGlyph != null && _kerning.TryGetValue(prevGlyph.GlyphName + "|" + glyph.GlyphName, out kern)) { xPos -= kern.Kerning * _emScale; } path = (GraphicsPath)glyph.Path(renderer).Clone(); scaleMatrix = new Matrix(); scaleMatrix.Scale(_emScale, -1 * _emScale, MatrixOrder.Append); scaleMatrix.Translate(xPos, ascent, MatrixOrder.Append); path.Transform(scaleMatrix); scaleMatrix.Dispose(); bounds = path.GetBounds(); if (ranges != null) { if (measureSpaces && bounds == RectangleF.Empty) { ranges.Add(new RectangleF(xPos, 0, glyph.HorizAdvX * _emScale, ascent)); } else { ranges.Add(bounds); } } if (path.PointCount > 0) result.AddPath(path, false); xPos += glyph.HorizAdvX * _emScale; prevGlyph = glyph; } return result; }
public virtual bool NeedRender(ISvgRenderer renderer) { // We make this assumption so that the first pass is still fast // That way we don't have to calculate the screen regions // Before a full rerender if (screenRegion == RectangleF.Empty) return true; if (renderer.InvalidRect == RectangleF.Empty) return true; if (renderer.InvalidRect.IntersectsWith(screenRegion)) // TODO: Eventually add a full path check here? return true; return false; }
public IList<RectangleF> MeasureCharacters(ISvgRenderer renderer, string text) { var g = GetGraphics(renderer); var regions = new List<RectangleF>(); StringFormat format; for (int s = 0; s <= (text.Length - 1) / 32; s++) { format = StringFormat.GenericTypographic; format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; format.SetMeasurableCharacterRanges((from r in Enumerable.Range(32 * s, Math.Min(32, text.Length - 32 * s)) select new CharacterRange(r, 1)).ToArray()); regions.AddRange(from r in g.MeasureCharacterRanges(text, _font, new Rectangle(0, 0, 1000, 1000), format) select r.GetBounds(g)); } return regions; }
public override void RenderChildren(ISvgRenderer renderer) { // search through all child elements and find one that passes all tests foreach ( XmlNode node in ChildNodes ) { SvgElement element = node as SvgElement; ISvgTests testsElement = node as ISvgTests; if ( element != null && testsElement != null && passesAllTest(testsElement)) { element.Render(renderer); // make sure we only render the first element that passes break; } } }
public override void CacheRenderingRegion(ISvgRenderer renderer) { base.CacheRenderingRegion(renderer); if (renderingNode != null) { if (renderingNode.ScreenRegion != RectangleF.Empty) return; //TODO this is still fairly experimental, a margin of 20 gives us some overlap for leeway //TODO in general, overlap is necessary to handle strokes, which are not covered in bbox, but are //TODO for rendering purposes (same with markers) string strokeWidth = this.GetPropertyValue("stroke-width"); if(strokeWidth.Length == 0) strokeWidth = "1px"; SvgLength strokeWidthLength = new SvgLength(this, "stroke-width", SvgLengthDirection.Viewport, strokeWidth); renderingNode.ScreenRegion = GetBRect((float)strokeWidthLength.Value); } }
protected override GraphicsPath GetBaselinePath(ISvgRenderer renderer) { var path = this.OwnerDocument.IdManager.GetElementById(this.ReferencedPath) as SvgVisualElement; if (path == null) return null; var pathData = (GraphicsPath)path.Path(renderer).Clone(); if (path.Transforms.Count > 0) { Matrix transformMatrix = new Matrix(1, 0, 0, 1, 0, 0); foreach (var transformation in path.Transforms) { transformMatrix.Multiply(transformation.Matrix); } pathData.Transform(transformMatrix); } return pathData; }
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); }
public override GraphicsPath Path(ISvgRenderer renderer) { if ((_Path == null || this.IsPathDirty) && base.StrokeWidth > 0) { _Path = new GraphicsPath(); try { for (int i = 0; (i + 1) < Points.Count; i += 2) { PointF endPoint = new PointF(Points[i].ToDeviceValue(renderer, UnitRenderingType.Horizontal, this), Points[i + 1].ToDeviceValue(renderer, UnitRenderingType.Vertical, this)); if (renderer == null) { var radius = base.StrokeWidth / 2; _Path.AddEllipse(endPoint.X - radius, endPoint.Y - radius, 2 * radius, 2 * radius); continue; } // TODO: Remove unrequired first line if (_Path.PointCount == 0) { _Path.AddLine(endPoint, endPoint); } else { _Path.AddLine(_Path.GetLastPoint(), endPoint); } } } catch (Exception exc) { Trace.TraceError("Error rendering points: " + exc.Message); } if (renderer != null) this.IsPathDirty = false; } return _Path; }
private IFontDefn GetFont(ISvgRenderer renderer, SvgElement owner) { if (owner == null) return null; var visual = owner.Parents.OfType<SvgVisualElement>().FirstOrDefault(); return visual?.GetFont(renderer); }
protected internal override void RenderFillAndStroke(ISvgRenderer renderer) { base.RenderFillAndStroke(renderer); RenderChildren(renderer); }
private IFontDefn GetFont(ISvgRenderer renderer, SvgElement owner, SvgFontManager fontManager) { var visual = owner?.Parents.OfType <SvgVisualElement>().FirstOrDefault(); return(visual?.GetFont(renderer, fontManager)); }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> void ISvgElement.Render(ISvgRenderer renderer) { this.Render(renderer); }
/// <summary> /// Renders this element to the <see cref="ISvgRenderer"/>. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> that the element should use to render itself.</param> public void RenderElement(ISvgRenderer renderer) { this.Render(renderer); }
/// <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; 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(); } } }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected override void Render(ISvgRenderer renderer) { // Never render paint servers or their children }
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.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="ISvgRenderer"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected override void Render(ISvgRenderer renderer) { // Do nothing. Children should NOT be rendered. }
/// <summary> /// Gets the <see cref="System.Drawing.Drawing2D.GraphicsPath"/> for this element. /// </summary> /// <value></value> public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer) { return(GetPaths(this, renderer)); }
/// <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> void ISvgClipable.ResetClip(ISvgRenderer renderer) { this.ResetClip(renderer); }
/// <summary> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/> /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected internal virtual bool RenderStroke(ISvgRenderer renderer) { if (this.Stroke != null && this.Stroke != SvgColourServer.None && this.StrokeWidth > 0) { float strokeWidth = this.StrokeWidth.ToDeviceValue(renderer, UnitRenderingType.Other, this); using (var brush = this.Stroke.GetBrush(this, renderer, Math.Min(Math.Max(this.StrokeOpacity * this.Opacity, 0), 1), true)) { if (brush != null) { var path = this.Path(renderer); var bounds = path.GetBounds(); if (path.PointCount < 1) { return(false); } if (bounds.Width <= 0 && bounds.Height <= 0) { switch (this.StrokeLineCap) { case SvgStrokeLineCap.Round: using (var capPath = new GraphicsPath()) { capPath.AddEllipse(path.PathPoints[0].X - strokeWidth / 2, path.PathPoints[0].Y - strokeWidth / 2, strokeWidth, strokeWidth); renderer.FillPath(brush, capPath); } break; case SvgStrokeLineCap.Square: using (var capPath = new GraphicsPath()) { capPath.AddRectangle(new RectangleF(path.PathPoints[0].X - strokeWidth / 2, path.PathPoints[0].Y - strokeWidth / 2, strokeWidth, strokeWidth)); renderer.FillPath(brush, capPath); } break; } } else { using (var pen = new Pen(brush, strokeWidth)) { if (this.StrokeDashArray != null && this.StrokeDashArray.Count > 0) { if (this.StrokeDashArray.Count % 2 != 0) { // handle odd dash arrays by repeating them once this.StrokeDashArray.AddRange(this.StrokeDashArray); } /* divide by stroke width - GDI behaviour that I don't quite understand yet.*/ pen.DashPattern = this.StrokeDashArray.ConvertAll(u => ((u.ToDeviceValue(renderer, UnitRenderingType.Other, this) <= 0) ? 1 : u.ToDeviceValue(renderer, UnitRenderingType.Other, this)) / ((strokeWidth <= 0) ? 1 : strokeWidth)).ToArray(); if (this.StrokeDashOffset != null && this.StrokeDashOffset.Value != 0) { pen.DashOffset = ((this.StrokeDashOffset.ToDeviceValue(renderer, UnitRenderingType.Other, this) <= 0) ? 1 : this.StrokeDashOffset.ToDeviceValue(renderer, UnitRenderingType.Other, this)) / ((strokeWidth <= 0) ? 1 : strokeWidth); } } switch (this.StrokeLineJoin) { case SvgStrokeLineJoin.Bevel: pen.LineJoin = LineJoin.Bevel; break; case SvgStrokeLineJoin.Round: pen.LineJoin = LineJoin.Round; break; default: pen.LineJoin = LineJoin.Miter; break; } pen.MiterLimit = this.StrokeMiterLimit; switch (this.StrokeLineCap) { case SvgStrokeLineCap.Round: pen.StartCap = LineCap.Round; pen.EndCap = LineCap.Round; break; case SvgStrokeLineCap.Square: pen.StartCap = LineCap.Square; pen.EndCap = LineCap.Square; break; } renderer.DrawPath(pen, path); return(true); } } } } } return(false); }
/// <summary> /// Gets the <see cref="GraphicsPath"/> for this element. /// </summary> public abstract GraphicsPath Path(ISvgRenderer renderer);
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected override void Render(ISvgRenderer renderer) { this.Render(renderer, true); }
public override void AfterRender(ISvgRenderer renderer) { }
/// <summary> /// Renders the stroke of the <see cref="SvgVisualElement"/> to the specified <see cref="ISvgRenderer"/> /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected internal override bool RenderStroke(ISvgRenderer renderer) { var result = base.RenderStroke(renderer); var path = this.Path(renderer); if (this.MarkerStart != null) { SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerStart.ToString()); marker.RenderMarker(renderer, this, path.PathPoints[0], path.PathPoints[0], path.PathPoints[1]); } if (this.MarkerMid != null) { SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerMid.ToString()); for (int i = 1; i <= path.PathPoints.Length - 2; i++) marker.RenderMarker(renderer, this, path.PathPoints[i], path.PathPoints[i - 1], path.PathPoints[i], path.PathPoints[i + 1]); } if (this.MarkerEnd != null) { SvgMarker marker = this.OwnerDocument.GetElementById<SvgMarker>(this.MarkerEnd.ToString()); marker.RenderMarker(renderer, this, path.PathPoints[path.PathPoints.Length - 1], path.PathPoints[path.PathPoints.Length - 2], path.PathPoints[path.PathPoints.Length - 1]); } return result; }
/// <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.HasValue).FirstOrDefault(); var firstPatternContentUnit = chain.Where(p => p._patternContentUnits.HasValue).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(); } } }
/// <summary> /// Gets a <see cref="Color"/> 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 Color GetColor(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke = false) { return(System.Drawing.Color.Black); }
protected virtual GraphicsPath GetBaselinePath(ISvgRenderer renderer) { return(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> void ISvgTransformable.PopTransforms(ISvgRenderer renderer) { this.PopTransforms(renderer); }
/// <summary> /// Get the font information based on data stored with the text object or inherited from the parent. /// </summary> /// <returns></returns> internal IFontDefn GetFont(ISvgRenderer renderer) { // Get the font-size float fontSize; var fontSizeUnit = this.FontSize; if (fontSizeUnit == SvgUnit.None || fontSizeUnit == SvgUnit.Empty) { fontSize = 1.0f; } else { fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); } var family = ValidateFontFamily(this.FontFamily, this.OwnerDocument); var sFaces = family as IEnumerable <SvgFontFace>; if (sFaces == null) { var fontStyle = System.Drawing.FontStyle.Regular; // Get the font-weight switch (this.FontWeight) { //Note: Bold is not listed because it is = W700. case SvgFontWeight.Bolder: case SvgFontWeight.W600: case SvgFontWeight.W700: case SvgFontWeight.W800: case SvgFontWeight.W900: fontStyle |= System.Drawing.FontStyle.Bold; break; } // Get the font-style switch (this.FontStyle) { case SvgFontStyle.Italic: case SvgFontStyle.Oblique: fontStyle |= System.Drawing.FontStyle.Italic; break; } // Get the text-decoration switch (this.TextDecoration) { case SvgTextDecoration.LineThrough: fontStyle |= System.Drawing.FontStyle.Strikeout; break; case SvgTextDecoration.Underline: fontStyle |= System.Drawing.FontStyle.Underline; break; } var ff = family as FontFamily; if (!ff.IsStyleAvailable(fontStyle)) { // Do Something } // Get the font-family return(new GdiFontDefn(new System.Drawing.Font(ff, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel))); } else { var font = sFaces.First().Parent as SvgFont; if (font == null) { var uri = sFaces.First().Descendants().OfType <SvgFontFaceUri>().First().ReferencedElement; font = OwnerDocument.IdManager.GetElementById(uri) as SvgFont; } return(new SvgFontDefn(font, fontSize, OwnerDocument.Ppi)); } }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="ISvgRenderer"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> protected virtual void Render(ISvgRenderer renderer) { this.PushTransforms(renderer); this.RenderChildren(renderer); this.PopTransforms(renderer); }
public WpfSvgWindow(long innerWidth, long innerHeight, ISvgRenderer renderer) : base(innerWidth, innerHeight, renderer) { // _preferUserSize = true; }
/// <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 Image; 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); SvgAspectRatio aspectRatio = AspectRatio ?? new SvgAspectRatio(SvgPreserveAspectRatio.xMidYMid); if (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) { if (Opacity == 1F) { renderer.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel); } else { renderer.DrawImage(bmp, destRect, srcRect, GraphicsUnit.Pixel, Opacity); } 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 } }
/// <summary> /// Common code for rendering a marker once the orientation angle has been calculated /// </summary> /// <param name="fAngle"></param> /// <param name="pRenderer"></param> /// <param name="pOwner"></param> /// <param name="pMarkerPoint"></param> private void RenderPart2(float fAngle, ISvgRenderer pRenderer, SvgVisualElement pOwner, PointF pMarkerPoint) { using (var pRenderPen = CreatePen(pOwner, pRenderer)) { using (var markerPath = GetClone(pOwner, pRenderer)) { using (var transMatrix = new Matrix()) { transMatrix.Translate(pMarkerPoint.X, pMarkerPoint.Y); if (Orient.IsAuto) { transMatrix.Rotate(fAngle); } else { transMatrix.Rotate(Orient.Angle); } switch (MarkerUnits) { case SvgMarkerUnits.StrokeWidth: if (ViewBox.Width > 0 && ViewBox.Height > 0) { transMatrix.Scale(MarkerWidth, MarkerHeight); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(pRenderer, UnitRenderingType.Other, this); transMatrix.Translate(AdjustForViewBoxWidth(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this) * strokeWidth), AdjustForViewBoxHeight(-RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this) * strokeWidth)); } else { // SvgMarkerUnits.UserSpaceOnUse // TODO: We know this isn't correct. // But use this until the TODOs from AdjustForViewBoxWidth and AdjustForViewBoxHeight are done. // MORE see Unit Test "MakerEndTest.TestArrowCodeCreation()" transMatrix.Translate(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this), -RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this)); } break; case SvgMarkerUnits.UserSpaceOnUse: transMatrix.Translate(-RefX.ToDeviceValue(pRenderer, UnitRenderingType.Horizontal, this), -RefY.ToDeviceValue(pRenderer, UnitRenderingType.Vertical, this)); break; } if (MarkerElement != null && MarkerElement.Transforms != null) { using (var matrix = MarkerElement.Transforms.GetMatrix()) transMatrix.Multiply(matrix); } markerPath.Transform(transMatrix); if (pRenderPen != null) { pRenderer.DrawPath(pRenderPen, markerPath); } SvgPaintServer pFill = this.Children.First().Fill; SvgFillRule pFillRule = FillRule; // TODO: What do we use the fill rule for? if (pFill != null) { using (var pBrush = pFill.GetBrush(this, pRenderer, FixOpacityValue(FillOpacity))) { pRenderer.FillPath(pBrush, markerPath); } } } } } }
public static System.Drawing.PointF GetDevicePointOffset(SvgUnit x, SvgUnit y, ISvgRenderer renderer, SvgElement owner) { return(new System.Drawing.PointF(x.ToDeviceValue(renderer, UnitRenderingType.HorizontalOffset, owner), y.ToDeviceValue(renderer, UnitRenderingType.VerticalOffset, owner))); }
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> /// <remarks>Necessary to make sure that any internal tspan elements get rendered as well</remarks> protected override void Render(ISvgRenderer renderer) { if ((this.Path(renderer) != null) && this.Visible && this.Displayable) { this.PushTransforms(renderer); this.SetClip(renderer); // If this element needs smoothing enabled turn anti-aliasing on if (this.RequiresSmoothRendering) { renderer.SmoothingMode = SmoothingMode.AntiAlias; } this.RenderFill(renderer); this.RenderStroke(renderer); this.RenderChildren(renderer); // Reset the smoothing mode if (this.RequiresSmoothRendering && renderer.SmoothingMode == SmoothingMode.AntiAlias) { renderer.SmoothingMode = SmoothingMode.Default; } this.ResetClip(renderer); this.PopTransforms(renderer); } }
/// <summary> /// Converts the current unit to one that can be used at render time. /// </summary> /// <param name="boundable">The container element used as the basis for calculations</param> /// <returns>The representation of the current unit in a device value (usually pixels).</returns> public float ToDeviceValue(ISvgRenderer renderer, UnitRenderingType renderType, SvgElement owner) { // If it's already been calculated if (this._deviceValue.HasValue) { return this._deviceValue.Value; } if (this._value == 0.0f) { this._deviceValue = 0.0f; return this._deviceValue.Value; } // http://www.w3.org/TR/CSS21/syndata.html#values // http://www.w3.org/TR/SVG11/coords.html#Units const float cmInInch = 2.54f; int ppi = SvgDocument.PointsPerInch; var type = this.Type; var value = this.Value; float points; switch (type) { case SvgUnitType.Em: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points / 72.0f) * ppi; } else { _deviceValue = value * (currFont.SizeInPoints / 72.0f) * ppi; } } break; case SvgUnitType.Ex: using (var currFont = GetFont(renderer, owner)) { if (currFont == null) { points = (float)(value * 9); _deviceValue = (points * 0.5f / 72.0f) * ppi; } else { _deviceValue = value * 0.5f * (currFont.SizeInPoints / 72.0f) * ppi; } break; } case SvgUnitType.Centimeter: _deviceValue = (float)((value / cmInInch) * ppi); break; case SvgUnitType.Inch: _deviceValue = value * ppi; break; case SvgUnitType.Millimeter: _deviceValue = (float)((value / 10) / cmInInch) * ppi; break; case SvgUnitType.Pica: _deviceValue = ((value * 12) / 72) * ppi; break; case SvgUnitType.Point: _deviceValue = (value / 72) * ppi; break; case SvgUnitType.Pixel: _deviceValue = value; break; case SvgUnitType.User: _deviceValue = value; break; case SvgUnitType.Percentage: // Can't calculate if there is no style owner var boundable = (renderer == null ? (owner == null ? null : owner.OwnerDocument) : renderer.GetBoundable()); if (boundable == null) { _deviceValue = value; break; } System.Drawing.SizeF size = boundable.Bounds.Size; switch (renderType) { case UnitRenderingType.Horizontal: _deviceValue = (size.Width / 100) * value; break; case UnitRenderingType.HorizontalOffset: _deviceValue = (size.Width / 100) * value + boundable.Location.X; break; case UnitRenderingType.Vertical: _deviceValue = (size.Height / 100) * value; break; case UnitRenderingType.VerticalOffset: _deviceValue = (size.Height / 100) * value + boundable.Location.Y; break; default: _deviceValue = (float)(Math.Sqrt(Math.Pow(size.Width, 2) + Math.Pow(size.Height, 2)) / Math.Sqrt(2) * value / 100.0); break; } break; default: _deviceValue = value; break; } return this._deviceValue.Value; }
protected virtual GraphicsPath GetBaselinePath(ISvgRenderer renderer) { return null; }
public override void Render(ISvgRenderer renderer) { }
public TextDrawingState(ISvgRenderer renderer, SvgTextBase element) { this.Element = element; this.Renderer = renderer; this.Current = PointF.Empty; _xAnchor = 0; this.BaselinePath = element.GetBaselinePath(renderer); _authorPathLength = element.GetAuthorPathLength(); }
// disable default rendering public override void BeforeRender(ISvgRenderer renderer) { }
public WpfSvgWindow(long innerWidth, long innerHeight, ISvgRenderer renderer) : base(innerWidth, innerHeight, renderer) { }
public override System.Drawing.Drawing2D.GraphicsPath Path(ISvgRenderer renderer) { SvgVisualElement element = (SvgVisualElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); return((element != null && !this.HasRecursiveReference()) ? element.Path(renderer) : null); }
/// <summary> /// Gets a <see cref="Brush"/> representing the current paint server. /// </summary> /// <param name="styleOwner">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 abstract Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity, bool forStroke = false);
/// <summary> /// Renders the <see cref="SvgElement"/> and contents to the specified <see cref="Graphics"/> object. /// </summary> /// <param name="renderer">The <see cref="ISvgRenderer"/> object to render to.</param> /// <remarks>Necessary to make sure that any internal tspan elements get rendered as well</remarks> protected override void Render(ISvgRenderer renderer) { if ((this.Path(renderer) != null) && this.Visible && this.Displayable) { this.PushTransforms(renderer); this.SetClip(renderer); // If this element needs smoothing enabled turn anti-aliasing on if (this.RequiresSmoothRendering) { renderer.SmoothingMode = SmoothingMode.AntiAlias; } // If text color blends with background color, text will be rendered blurry // To avoid it, we set SourceCopy which overwrite background color var compositingMode = renderer.CompositingMode; renderer.CompositingMode = CompositingMode.SourceCopy; this.RenderFill(renderer); this.RenderStroke(renderer); this.RenderChildren(renderer); // Reset the smoothing mode if (this.RequiresSmoothRendering && renderer.SmoothingMode == SmoothingMode.AntiAlias) { renderer.SmoothingMode = SmoothingMode.Default; } renderer.CompositingMode = compositingMode; this.ResetClip(renderer); this.PopTransforms(renderer); } }
public void AddStringToPath(ISvgRenderer renderer, GraphicsPath path, string text, PointF location) { path.AddString(text, _font.FontFamily, (int)_font.Style, _font.Size, location, StringFormat.GenericTypographic); }
/// <summary> /// Gets the <see cref="GraphicsPath"/> for this element. /// </summary> /// <value></value> public override GraphicsPath Path(ISvgRenderer renderer) { //if there is a TSpan inside of this text element then path should not be null (even if this text is empty!) var nodes = GetContentNodes().Where(x => x is SvgContentNode && string.IsNullOrEmpty(x.Content.Trim(new[] { '\r', '\n', '\t' }))); if (_path == null || IsPathDirty || nodes.Count() == 1) { renderer = (renderer ?? SvgRenderer.FromNull()); SetPath(new TextDrawingState(renderer, this)); } return _path; }
protected override Brush CreateBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke) { try { if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.SetBoundable(renderingElement); } var points = new PointF[] { SvgUnit.GetDevicePoint(NormalizeUnit(this.X1), NormalizeUnit(this.Y1), renderer, this), SvgUnit.GetDevicePoint(NormalizeUnit(this.X2), NormalizeUnit(this.Y2), renderer, this) }; var bounds = renderer.GetBoundable().Bounds; if (bounds.Width <= 0 || bounds.Height <= 0 || ((points[0].X == points[1].X) && (points[0].Y == points[1].Y))) { if (this.GetCallback != null) { return(GetCallback().GetBrush(renderingElement, renderer, opacity, forStroke)); } return(null); } using (var transform = EffectiveGradientTransform) { transform.Translate(bounds.X, bounds.Y, MatrixOrder.Prepend); if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { // Transform a normal (i.e. perpendicular line) according to the transform transform.Scale(bounds.Width, bounds.Height, MatrixOrder.Prepend); } transform.TransformPoints(points); } points[0].X = (float)Math.Round(points[0].X, 4); points[0].Y = (float)Math.Round(points[0].Y, 4); points[1].X = (float)Math.Round(points[1].X, 4); points[1].Y = (float)Math.Round(points[1].Y, 4); if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { // Transform the normal line back to a line such that the gradient still starts in the correct corners, but // has the proper normal vector based on the transforms. If you work out the geometry, these formulas should work. var midPoint = new PointF((points[0].X + points[1].X) / 2, (points[0].Y + points[1].Y) / 2); var dy = points[1].Y - points[0].Y; var dx = points[1].X - points[0].X; var x1 = points[0].X; var y2 = points[1].Y; if (dx != 0f && dy != 0f) { var startX = (float)((dy * dx * (midPoint.Y - y2) + Math.Pow(dx, 2) * midPoint.X + Math.Pow(dy, 2) * x1) / (Math.Pow(dx, 2) + Math.Pow(dy, 2))); var endY = dy * (startX - x1) / dx + y2; points[0] = new PointF(startX, midPoint.Y + (midPoint.Y - endY)); points[1] = new PointF(midPoint.X + (midPoint.X - startX), endY); } } var effectiveStart = points[0]; var effectiveEnd = points[1]; if (PointsToMove(renderingElement, points[0], points[1]) > LinePoints.None) { var expansion = ExpandGradient(renderingElement, points[0], points[1]); effectiveStart = expansion.StartPoint; effectiveEnd = expansion.EndPoint; } var result = new LinearGradientBrush(effectiveStart, effectiveEnd, System.Drawing.Color.Transparent, System.Drawing.Color.Transparent) { InterpolationColors = CalculateColorBlend(renderer, opacity, points[0], effectiveStart, points[1], effectiveEnd), WrapMode = WrapMode.TileFlipX }; return(result); } finally { if (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) { renderer.PopBoundable(); } } }
/// <summary> /// Get the font information based on data stored with the text object or inherited from the parent. /// </summary> /// <returns></returns> internal IFontDefn GetFont(ISvgRenderer renderer) { // Get the font-size float fontSize; var fontSizeUnit = this.FontSize; if (fontSizeUnit == SvgUnit.None || fontSizeUnit == SvgUnit.Empty) { fontSize = 1.0f; } else { fontSize = fontSizeUnit.ToDeviceValue(renderer, UnitRenderingType.Vertical, this); } var family = ValidateFontFamily(this.FontFamily, this.OwnerDocument); var sFaces = family as IEnumerable<SvgFontFace>; if (sFaces == null) { var fontStyle = System.Drawing.FontStyle.Regular; // Get the font-weight switch (this.FontWeight) { case SvgFontWeight.bold: case SvgFontWeight.bolder: case SvgFontWeight.w600: case SvgFontWeight.w700: case SvgFontWeight.w800: case SvgFontWeight.w900: fontStyle |= System.Drawing.FontStyle.Bold; break; } // Get the font-style switch (this.FontStyle) { case SvgFontStyle.italic: case SvgFontStyle.oblique: fontStyle |= System.Drawing.FontStyle.Italic; break; } // Get the text-decoration switch (this.TextDecoration) { case SvgTextDecoration.lineThrough: fontStyle |= System.Drawing.FontStyle.Strikeout; break; case SvgTextDecoration.underline: fontStyle |= System.Drawing.FontStyle.Underline; break; } var ff = family as FontFamily; if (!ff.IsStyleAvailable(fontStyle)) { // Do Something } // Get the font-family return new GdiFontDefn(new System.Drawing.Font(ff, fontSize, fontStyle, System.Drawing.GraphicsUnit.Pixel)); } else { var font = sFaces.First().Parent as SvgFont; if (font == null) { var uri = sFaces.First().Descendants().OfType<SvgFontFaceUri>().First().ReferencedElement; font = OwnerDocument.IdManager.GetElementById(uri) as SvgFont; } return new SvgFontDefn(font, fontSize, OwnerDocument.Ppi); } }
private ColorBlend CalculateColorBlend(ISvgRenderer renderer, float opacity, PointF specifiedStart, PointF effectiveStart, PointF specifiedEnd, PointF effectiveEnd) { float startExtend; float endExtend; List <Color> colors; List <float> positions; var colorBlend = GetColorBlend(renderer, opacity, false); var startDelta = CalculateDistance(specifiedStart, effectiveStart); var endDelta = CalculateDistance(specifiedEnd, effectiveEnd); if (!(startDelta > 0) && !(endDelta > 0)) { return(colorBlend); } var specifiedLength = CalculateDistance(specifiedStart, specifiedEnd); var specifiedUnitVector = new PointF((specifiedEnd.X - specifiedStart.X) / (float)specifiedLength, (specifiedEnd.Y - specifiedStart.Y) / (float)specifiedLength); var effectiveLength = CalculateDistance(effectiveStart, effectiveEnd); switch (SpreadMethod) { case SvgGradientSpreadMethod.Reflect: startExtend = (float)(Math.Ceiling(CalculateDistance(effectiveStart, specifiedStart) / specifiedLength)); endExtend = (float)(Math.Ceiling(CalculateDistance(effectiveEnd, specifiedEnd) / specifiedLength)); colors = colorBlend.Colors.ToList(); positions = (from p in colorBlend.Positions select p + startExtend).ToList(); for (var i = 0; i < startExtend; i++) { if (i % 2 == 0) { for (var j = 1; j < colorBlend.Positions.Length; j++) { positions.Insert(0, (float)((startExtend - 1 - i) + 1 - colorBlend.Positions[j])); colors.Insert(0, colorBlend.Colors[j]); } } else { for (var j = 0; j < colorBlend.Positions.Length - 1; j++) { positions.Insert(j, (float)((startExtend - 1 - i) + colorBlend.Positions[j])); colors.Insert(j, colorBlend.Colors[j]); } } } int insertPos; for (var i = 0; i < endExtend; i++) { if (i % 2 == 0) { insertPos = positions.Count; for (var j = 0; j < colorBlend.Positions.Length - 1; j++) { positions.Insert(insertPos, (float)((startExtend + 1 + i) + 1 - colorBlend.Positions[j])); colors.Insert(insertPos, colorBlend.Colors[j]); } } else { for (var j = 1; j < colorBlend.Positions.Length; j++) { positions.Add((float)((startExtend + 1 + i) + colorBlend.Positions[j])); colors.Add(colorBlend.Colors[j]); } } } colorBlend.Colors = colors.ToArray(); colorBlend.Positions = (from p in positions select p / (startExtend + 1 + endExtend)).ToArray(); break; case SvgGradientSpreadMethod.Repeat: startExtend = (float)(Math.Ceiling(CalculateDistance(effectiveStart, specifiedStart) / specifiedLength)); endExtend = (float)(Math.Ceiling(CalculateDistance(effectiveEnd, specifiedEnd) / specifiedLength)); colors = new List <Color>(); positions = new List <float>(); for (int i = 0; i < startExtend + endExtend + 1; i++) { for (int j = 0; j < colorBlend.Positions.Length; j++) { positions.Add((i + colorBlend.Positions[j] * 0.9999f) / (startExtend + endExtend + 1)); colors.Add(colorBlend.Colors[j]); } } positions[positions.Count - 1] = 1.0f; colorBlend.Colors = colors.ToArray(); colorBlend.Positions = positions.ToArray(); break; default: for (var i = 0; i < colorBlend.Positions.Length; i++) { var originalPoint = MovePointAlongVector(specifiedStart, specifiedUnitVector, (float)specifiedLength * colorBlend.Positions[i]); var distanceFromEffectiveStart = CalculateDistance(effectiveStart, originalPoint); colorBlend.Positions[i] = (float)Math.Round(Math.Max(0F, Math.Min((distanceFromEffectiveStart / effectiveLength), 1.0F)), 5); } if (startDelta > 0) { colorBlend.Positions = new[] { 0F }.Concat(colorBlend.Positions).ToArray(); colorBlend.Colors = new[] { colorBlend.Colors.First() }.Concat(colorBlend.Colors).ToArray(); } if (endDelta > 0) { colorBlend.Positions = colorBlend.Positions.Concat(new[] { 1F }).ToArray(); colorBlend.Colors = colorBlend.Colors.Concat(new[] { colorBlend.Colors.Last() }).ToArray(); } break; } return(colorBlend); }
/// <summary> /// Gets the <see cref="GraphicsPath"/> for this element. /// </summary> /// <value></value> public override GraphicsPath Path(ISvgRenderer renderer) { return(GetPaths(this, renderer)); }
private void Draw(ISvgRenderer renderer, ISvgBoundable boundable) { renderer.SetBoundable(boundable); this.Render(renderer); }