예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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;
        }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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);
                            }
                        }
                    }
                }
            }
        }
예제 #8
0
        /// <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();
                }
            }
        }
예제 #9
0
 /// <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);
 }
예제 #10
0
 /// <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);
예제 #11
0
        /// <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);
        }
예제 #12
0
        /// <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);
        }
예제 #13
0
 public override Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity)
 {
     return((Brush)(renderer.KnockoutBrush ?? Brushes.White).Clone());
 }
예제 #14
0
        /// <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();
                }
            }
        }
예제 #15
0
 public override System.Drawing.Brush GetBrush(SvgVisualElement styleOwner, SvgRenderer renderer, float opacity)
 {
     EnsureServer(styleOwner);
     return(_concreteServer.GetBrush(styleOwner, renderer, opacity));
 }
예제 #16
0
 /// <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);
예제 #17
0
파일: SvgUse.cs 프로젝트: heindlalex/SVG
        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);
        }
예제 #18
0
 /// <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);
예제 #19
0
 private PointF CalculateOrigin(SvgVisualElement renderingElement)
 {
     return(CalculateBoundable(renderingElement).Location);
 }
예제 #20
0
        public override GraphicsPath Path(ISvgRenderer renderer)
        {
            SvgVisualElement element = (SvgVisualElement)this.OwnerDocument.IdManager.GetElementById(this.ReferencedElement);

            return((element != null) ? element.Path(renderer) : null);
        }
예제 #21
0
 protected abstract Brush CreateBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke);
예제 #22
0
        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();
                }
            }
        }
예제 #23
0
 /// <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);
예제 #24
0
        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();
                }
            }
        }
예제 #25
0
        /// <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));
 }
예제 #27
0
        /// <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();
                }
            }
        }
예제 #28
0
 protected ISvgBoundable CalculateBoundable(SvgVisualElement renderingElement)
 {
     return((this.GradientUnits == SvgCoordinateUnits.ObjectBoundingBox) ? (ISvgBoundable)renderingElement : renderingElement.OwnerDocument);
 }
예제 #29
0
        /// <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;
        }