public override Brush GetBrush(SvgVisualElement styleOwner, float opacity) { int alpha = (int)((opacity * (this.Colour.A/255) ) * 255); Color colour = Color.FromArgb(alpha, this.Colour); return new SolidBrush(colour); }
/// <summary> /// Gets this <see cref="SvgClipPath"/>'s region to be used as a clipping region. /// </summary> /// <returns>A new <see cref="Region"/> containing the <see cref="Region"/> to be used for clipping.</returns> public Region GetClipRegion(SvgVisualElement owner) { if (cachedClipPath == null || this._pathDirty) { cachedClipPath = new GraphicsPath(); foreach (SvgElement element in this.Children) { this.CombinePaths(cachedClipPath, element); } this._pathDirty = false; } return new Region(cachedClipPath); }
/// <summary> /// Gets this <see cref="SvgClipPath"/>'s region to be used as a clipping region. /// </summary> /// <returns>A new <see cref="Region"/> containing the <see cref="Region"/> to be used for clipping.</returns> public Region GetClipRegion(SvgVisualElement owner) { var path = new GraphicsPath(); if (this._pathDirty) { foreach (SvgElement element in this.Children) { this.CombinePaths(path, element); } this._pathDirty = false; } return new Region(path); }
public override Brush GetBrush(SvgVisualElement renderingElement, float opacity) { GraphicsPath path = new GraphicsPath(); float left = this.CenterX.ToDeviceValue(renderingElement); float top = this.CenterY.ToDeviceValue(renderingElement, true); float radius = this.Radius.ToDeviceValue(renderingElement); RectangleF boundingBox = (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) ? renderingElement.Bounds : renderingElement.OwnerDocument.GetDimensions(); path.AddEllipse(left-radius, top-radius, radius*2, radius*2); PathGradientBrush brush = new PathGradientBrush(path); ColorBlend blend = base.GetColourBlend(renderingElement, opacity); brush.InterpolationColors = blend; brush.CenterPoint = new PointF(this.FocalX.ToDeviceValue(renderingElement), this.FocalY.ToDeviceValue(renderingElement, true)); return brush; }
public override Brush GetBrush(SvgVisualElement owner, float opacity) { // Need at least 2 colours to do the gradient fill if (this.Stops.Count < 2) { return null; } PointF start; PointF end; RectangleF bounds = (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) ? owner.Bounds : owner.OwnerDocument.GetDimensions(); // Have start/end points been set? If not the gradient is horizontal if (!this.End.IsEmpty()) { // Get the points to work out an angle if (this.Start.IsEmpty()) { start = bounds.Location; } else { start = new PointF(this.Start.X.ToDeviceValue(owner), this.Start.Y.ToDeviceValue(owner, true)); } float x = (this.End.X.IsEmpty) ? start.X : this.End.X.ToDeviceValue(owner); end = new PointF(x, this.End.Y.ToDeviceValue(owner, true)); } else { // Default: horizontal start = bounds.Location; end = new PointF(bounds.Right, bounds.Top); } LinearGradientBrush gradient = new LinearGradientBrush(start, end, Color.Transparent, Color.Transparent); gradient.InterpolationColors = base.GetColourBlend(owner, opacity); // Needed to fix an issue where the gradient was being wrapped when though it had the correct bounds gradient.WrapMode = WrapMode.TileFlipX; return gradient; }
public override Brush GetBrush(SvgVisualElement renderingElement, float opacity) { GraphicsPath path = new GraphicsPath(); float left = this.CenterX.ToDeviceValue(renderingElement); float top = this.CenterY.ToDeviceValue(renderingElement, true); float radius = this.Radius.ToDeviceValue(renderingElement); RectangleF boundingBox = (this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) ? renderingElement.Bounds : renderingElement.OwnerDocument.GetDimensions(); if (radius > 0) { path.AddEllipse(left - radius, top - radius, radius * 2, radius * 2); PathGradientBrush brush = new PathGradientBrush(path); ColorBlend blend = base.GetColourBlend(renderingElement, opacity); brush.InterpolationColors = blend; brush.CenterPoint = new PointF(this.FocalX.ToDeviceValue(renderingElement), this.FocalY.ToDeviceValue(renderingElement, true)); return(brush); } return(null); }
/// <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); } } } } } }
/// <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(); } } }
/// <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); }
/// <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 abstract Brush GetBrush(SvgVisualElement styleOwner, float opacity);
/// <summary> /// Gets a <see cref="ColorBlend"/> representing the <see cref="SvgGradientServer"/>'s gradient stops. /// </summary> /// <param name="owner">The parent <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the colour blend.</param> protected ColorBlend GetColourBlend(SvgVisualElement owner, float opacity) { ColorBlend blend = new ColorBlend(); int colourBlends = this.Stops.Count; bool insertStart = false; bool insertEnd = false; //gradient.Transform = renderingElement.Transforms.Matrix; // May need to increase the number of colour blends because the range *must* be from 0.0 to 1.0. // E.g. 0.5 - 0.8 isn't valid therefore the rest need to be calculated. // If the first stop doesn't start at zero if (this.Stops[0].Offset.Value > 0) { colourBlends++; // Indicate that a colour has to be dynamically added at the start insertStart = true; } // If the last stop doesn't end at 1 a stop float lastValue = this.Stops[this.Stops.Count - 1].Offset.Value; if (lastValue < 100 || lastValue < 1) { colourBlends++; // Indicate that a colour has to be dynamically added at the end insertEnd = true; } blend.Positions = new float[colourBlends]; blend.Colors = new Color[colourBlends]; // Set positions and colour values int actualStops = 0; float mergedOpacity; float position; Color colour; for (int i = 0; i < colourBlends; i++) { mergedOpacity = opacity * this.Stops[actualStops].Opacity; position = (this.Stops[actualStops].Offset.ToDeviceValue(owner) / owner.Bounds.Width); colour = Color.FromArgb((int)(mergedOpacity * 255), this.Stops[actualStops++].Colour); // Insert this colour before itself at position 0 if (insertStart && i == 0) { blend.Positions[i] = 0.0f; blend.Colors[i++] = colour; } blend.Positions[i] = position; blend.Colors[i] = colour; // Insert this colour after itself at position 0 if (insertEnd && i == colourBlends - 2) { blend.Positions[i + 1] = 1.0f; blend.Colors[++i] = colour; } } return(blend); }
/// <summary> /// Gets a <see cref="ColorBlend"/> representing the <see cref="SvgGradientServer"/>'s gradient stops. /// </summary> /// <param name="owner">The parent <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the colour blend.</param> protected ColorBlend GetColorBlend(SvgVisualElement owner, float opacity, bool radial) { int colourBlends = this.Stops.Count; bool insertStart = false; bool insertEnd = false; //gradient.Transform = renderingElement.Transforms.Matrix; //stops should be processed in reverse order if it's a radial gradient // May need to increase the number of colour blends because the range *must* be from 0.0 to 1.0. // E.g. 0.5 - 0.8 isn't valid therefore the rest need to be calculated. // If the first stop doesn't start at zero if (this.Stops[0].Offset.Value > 0) { colourBlends++; if (radial) { insertEnd = true; } else { insertStart = true; } } // If the last stop doesn't end at 1 a stop float lastValue = this.Stops[this.Stops.Count - 1].Offset.Value; if (lastValue < 100 || lastValue < 1) { colourBlends++; if (radial) { insertStart = true; } else { insertEnd = true; } } ColorBlend blend = new ColorBlend(colourBlends); // Set positions and colour values int actualStops = 0; float mergedOpacity = 0.0f; float position = 0.0f; Color colour = Color.Black; for (int i = 0; i < colourBlends; i++) { var currentStop = this.Stops[radial ? this.Stops.Count - 1 - actualStops : actualStops]; mergedOpacity = opacity * currentStop.Opacity; position = radial ? 1 - (currentStop.Offset.ToDeviceValue(owner) / owner.Bounds.Width) : (currentStop.Offset.ToDeviceValue(owner) / owner.Bounds.Width); colour = Color.FromArgb((int)(mergedOpacity * 255), currentStop.Colour); actualStops++; // Insert this colour before itself at position 0 if (insertStart && i == 0) { blend.Positions[i] = 0.0f; blend.Colors[i] = colour; i++; } blend.Positions[i] = position; blend.Colors[i] = colour; // Insert this colour after itself at position 0 if (insertEnd && i == colourBlends - 2) { i++; blend.Positions[i] = 1.0f; blend.Colors[i] = colour; } } return(blend); }
public override Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity) { return((Brush)(renderer.KnockoutBrush ?? Brushes.White).Clone()); }
/// <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(); } } }
public override System.Drawing.Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity) { EnsureServer(styleOwner); return(_concreteServer.GetBrush(styleOwner, renderer, opacity)); }
/// <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 abstract Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity, bool forStroke = false);
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); }
private PointF CalculateOrigin(SvgVisualElement renderingElement) { return(CalculateBoundable(renderingElement).Location); }
public override GraphicsPath Path(ISvgRenderer renderer) { SvgVisualElement element = (SvgVisualElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement); return((element != null) ? element.Path(renderer) : null); }
protected abstract Brush CreateBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke);
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 override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke = false) { LoadStops(renderingElement); if (this.Stops.Count < 1) { return(null); } if (this.Stops.Count == 1) { var stopColor = this.Stops[0].GetColor(renderingElement); var alpha = (int)Math.Round((opacity * (stopColor.A / 255.0f)) * 255); var colour = System.Drawing.Color.FromArgb(alpha, stopColor); return(new SolidBrush(colour)); } 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> /// Gets a <see cref="ColourBlend"/> representing the <see cref="SvgGradientServer"/>'s gradient stops. /// </summary> /// <param name="owner">The parent <see cref="SvgVisualElement"/>.</param> /// <param name="opacity">The opacity of the colour blend.</param> protected ColorBlend GetColourBlend(SvgVisualElement owner, float opacity) { ColorBlend blend = new ColorBlend(); int colourBlends = this.Stops.Count; bool insertStart = false; bool insertEnd = false; //gradient.Transform = renderingElement.Transforms.Matrix; // May need to increase the number of colour blends because the range *must* be from 0.0 to 1.0. // E.g. 0.5 - 0.8 isn't valid therefore the rest need to be calculated. // If the first stop doesn't start at zero if (this.Stops[0].Offset.Value > 0) { colourBlends++; // Indicate that a colour has to be dynamically added at the start insertStart = true; } // If the last stop doesn't end at 1 a stop float lastValue = this.Stops[this.Stops.Count - 1].Offset.Value; if (lastValue < 100 || lastValue < 1) { colourBlends++; // Indicate that a colour has to be dynamically added at the end insertEnd = true; } blend.Positions = new float[colourBlends]; blend.Colors = new Color[colourBlends]; // Set positions and colour values int actualStops = 0; float mergedOpacity = 0.0f; float position = 0.0f; Color colour = Color.Black; for (int i = 0; i < colourBlends; i++) { mergedOpacity = opacity * this.Stops[actualStops].Opacity; position = (this.Stops[actualStops].Offset.ToDeviceValue(owner) / owner.Bounds.Width); colour = Color.FromArgb((int)(mergedOpacity * 255), this.Stops[actualStops++].Colour); // Insert this colour before itself at position 0 if (insertStart && i == 0) { blend.Positions[i] = 0.0f; blend.Colors[i++] = colour; } blend.Positions[i] = position; blend.Colors[i] = colour; // Insert this colour after itself at position 0 if (insertEnd && i == colourBlends - 2) { blend.Positions[i + 1] = 1.0f; blend.Colors[++i] = colour; } } return blend; }
public override Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity, bool forStroke = false) { EnsureServer(styleOwner); return(_concreteServer?.GetBrush(styleOwner, renderer, opacity, forStroke) ?? _fallbackServer?.GetBrush(styleOwner, renderer, opacity, forStroke) ?? NotSet?.GetBrush(styleOwner, renderer, opacity, forStroke)); }
/// <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(); } } }
protected ISvgBoundable CalculateBoundable(SvgVisualElement renderingElement) { return((this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) ? (ISvgBoundable)renderingElement : renderingElement.OwnerDocument); }
/// <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, 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 renderer = SvgRenderer.FromImage(image)) { 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); } renderer.Transform = patternMatrix; renderer.CompositingQuality = CompositingQuality.HighQuality; renderer.SmoothingMode = SmoothingMode.AntiAlias; renderer.PixelOffsetMode = PixelOffsetMode.Half; foreach (SvgElement child in this.Children) { child.RenderElement(renderer); } renderer.Save(); } TextureBrush textureBrush = new TextureBrush(image); return textureBrush; }