Ejemplo n.º 1
0
        public override Brush GetBrush(SvgVisualElement renderingElement, ISvgRenderer renderer, float opacity, bool forStroke = false)
        {
            LoadStops(renderingElement);

            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();
                }
            }
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
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))
                {
                    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)
                        {
                            foreach (var transformation in MarkerElement.Transforms)
                            {
                                transMatrix.Multiply(transformation.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?
                        float          fOpacity  = FillOpacity;

                        if (pFill != null)
                        {
                            using (var pBrush = pFill.GetBrush(this, pRenderer, fOpacity))
                            {
                                pRenderer.FillPath(pBrush, markerPath);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Sets the path on this element and all child elements.  Uses the state
        /// object to track the state of the drawing
        /// </summary>
        /// <param name="state">State of the drawing operation</param>
        /// <param name="doMeasurements">If true, calculate and apply text length adjustments.</param>
        private void SetPath(TextDrawingState state, bool doMeasurements)
        {
            TextDrawingState origState       = null;
            bool             alignOnBaseline = state.BaselinePath != null && (this.TextAnchor == SvgTextAnchor.Middle || this.TextAnchor == SvgTextAnchor.End);

            if (doMeasurements)
            {
                if (this.TextLength != SvgUnit.None)
                {
                    origState = state.Clone();
                }
                else if (alignOnBaseline)
                {
                    origState          = state.Clone();
                    state.BaselinePath = null;
                }
            }

            foreach (var node in GetContentNodes())
            {
                SvgTextBase textNode = node as SvgTextBase;

                if (textNode == null)
                {
                    if (!string.IsNullOrEmpty(node.Content))
                    {
                        state.DrawString(PrepareText(node.Content));
                    }
                }
                else
                {
                    TextDrawingState newState = new TextDrawingState(state, textNode);

                    textNode.SetPath(newState);
                    state.NumChars += newState.NumChars;
                    state.Current   = newState.Current;
                }
            }

            var path = state.GetPath() ?? new GraphicsPath();

            // Apply any text length adjustments
            if (doMeasurements)
            {
                if (this.TextLength != SvgUnit.None)
                {
                    var specLength = this.TextLength.ToDeviceValue(state.Renderer, UnitRenderingType.Horizontal, this);
                    var actLength  = state.TextBounds.Width;
                    var diff       = (actLength - specLength);
                    if (Math.Abs(diff) > 1.5)
                    {
                        if (this.LengthAdjust == SvgTextLengthAdjust.Spacing)
                        {
                            if (this.X.Count < 2)
                            {
                                var numCharDiff = state.NumChars - origState.NumChars - 1;
                                if (numCharDiff != 0)
                                {
                                    origState.LetterSpacingAdjust = -1 * diff / numCharDiff;
                                    SetPath(origState, false);
                                    return;
                                }
                            }
                        }
                        else
                        {
                            using (var matrix = new Matrix())
                            {
                                matrix.Translate(-1 * state.TextBounds.X, 0, MatrixOrder.Append);
                                matrix.Scale(specLength / actLength, 1, MatrixOrder.Append);
                                matrix.Translate(state.TextBounds.X, 0, MatrixOrder.Append);
                                path.Transform(matrix);
                            }
                        }
                    }
                }
                else if (alignOnBaseline)
                {
                    var bounds = path.GetBounds();
                    if (this.TextAnchor == SvgTextAnchor.Middle)
                    {
                        origState.StartOffsetAdjust = -1 * bounds.Width / 2;
                    }
                    else
                    {
                        origState.StartOffsetAdjust = -1 * bounds.Width;
                    }
                    SetPath(origState, false);
                    return;
                }
            }


            _path            = path;
            this.IsPathDirty = false;
        }
Ejemplo n.º 5
0
            private void FlushPath()
            {
                if (_currPath != null)
                {
                    _currPath.CloseFigure();

                    // Abort on empty paths (e.g. rendering a space)
                    if (_currPath.PointCount < 1)
                    {
                        _anchoredPaths.Clear();
                        _xAnchor  = float.MinValue;
                        _currPath = null;
                        return;
                    }

                    if (_xAnchor > float.MinValue)
                    {
                        float      minX = float.MaxValue;
                        float      maxX = float.MinValue;
                        RectangleF bounds;
                        foreach (var path in _anchoredPaths)
                        {
                            bounds = path.GetBounds();
                            if (bounds.Left < minX)
                            {
                                minX = bounds.Left;
                            }
                            if (bounds.Right > maxX)
                            {
                                maxX = bounds.Right;
                            }
                        }

                        var xOffset = 0f; //_xAnchor - minX;
                        switch (Element.TextAnchor)
                        {
                        case SvgTextAnchor.Middle:
                            if (_anchoredPaths.Count() == 1)
                            {
                                xOffset -= this.TextBounds.Width / 2;
                            }
                            else
                            {
                                xOffset -= (maxX - minX) / 2;
                            }
                            break;

                        case SvgTextAnchor.End:
                            if (_anchoredPaths.Count() == 1)
                            {
                                xOffset -= this.TextBounds.Width;
                            }
                            else
                            {
                                xOffset -= (maxX - minX);
                            }
                            break;
                        }

                        if (xOffset != 0)
                        {
                            using (var matrix = new Matrix())
                            {
                                matrix.Translate(xOffset, 0);
                                foreach (var path in _anchoredPaths)
                                {
                                    path.Transform(matrix);
                                }
                            }
                        }

                        _anchoredPaths.Clear();
                        _xAnchor = float.MinValue;
                    }

                    if (_finalPath == null)
                    {
                        _finalPath = _currPath;
                    }
                    else
                    {
                        _finalPath.AddPath(_currPath, false);
                    }

                    _currPath = null;
                }
            }