Exemplo n.º 1
0
 public TextDrawingState(TextDrawingState parent, SvgTextBase element)
 {
     throw new NotImplementedException();
     //this.Element = element;
     //this.Renderer = parent.Renderer;
     //this.Parent = parent;
     //this.Current = parent.Current;
     //this.BaselinePath = element.GetBaselinePath(parent.Renderer) ?? parent.BaselinePath;
     //var currPathLength = element.GetAuthorPathLength();
     //_authorPathLength = currPathLength == 0 ? parent._authorPathLength : currPathLength;
 }
Exemplo n.º 2
0
            public TextDrawingState(TextDrawingState parent, SvgTextBase element)
            {
                this.Element      = element;
                this.Renderer     = parent.Renderer;
                this.Parent       = parent;
                this.Current      = parent.Current;
                this.BaselinePath = element.GetBaselinePath(parent.Renderer) ?? parent.BaselinePath;
                var currPathLength = element.GetAuthorPathLength();

                _authorPathLength = currPathLength == 0 ? parent._authorPathLength : currPathLength;
            }
Exemplo n.º 3
0
 public TextDrawingState(TextDrawingState parent, SvgTextBase element)
     : this(parent.Renderer, element)
 {
     this.Parent       = parent;
     this.Current      = parent.Current;
     this.TextBounds   = parent.TextBounds;
     this.BaselinePath = this.BaselinePath ?? parent.BaselinePath;
     if (_authorPathLength == 0)
     {
         _authorPathLength = parent._authorPathLength;
     }
 }
Exemplo n.º 4
0
            public TextDrawingState Clone()
            {
                var result = new TextDrawingState();

                result._anchoredPaths = this._anchoredPaths.ToList();
                result.BaselinePath   = this.BaselinePath;
                result._xAnchor       = this._xAnchor;
                result.Current        = this.Current;
                result.Element        = this.Element;
                result.NumChars       = this.NumChars;
                result.Parent         = this.Parent;
                result.Renderer       = this.Renderer;
                return(result);
            }
Exemplo n.º 5
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;
        }
Exemplo n.º 6
0
 private void SetPath(TextDrawingState state)
 {
     SetPath(state, true);
 }
Exemplo n.º 7
0
 public TextDrawingState Clone()
 {
     var result = new TextDrawingState();
     result._anchoredPaths = this._anchoredPaths.ToList();
     result.BaselinePath = this.BaselinePath;
     result._xAnchor = this._xAnchor;
     result.Current = this.Current;
     result.Element = this.Element;
     result.NumChars = this.NumChars;
     result.Parent = this.Parent;
     result.Renderer = this.Renderer;
     return result;
 }
Exemplo n.º 8
0
 public TextDrawingState(TextDrawingState parent, SvgTextBase element)
 {
     this.Element = element;
     this.Renderer = parent.Renderer;
     this.Parent = parent;
     this.Current = parent.Current;
     this.BaselinePath = element.GetBaselinePath(parent.Renderer) ?? parent.BaselinePath;
     var currPathLength = element.GetAuthorPathLength();
     _authorPathLength = currPathLength == 0 ? parent._authorPathLength : currPathLength;
 }
Exemplo n.º 9
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>
        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 bounds = path.GetBounds();
                    var specLength = this.TextLength.ToDeviceValue(state.Renderer, UnitRenderingType.Horizontal, this);
                    var actLength = bounds.Width;
                    var diff = (actLength - specLength);
                    if (Math.Abs(diff) > 1.5)
                    {
                        if (this.LengthAdjust == SvgTextLengthAdjust.Spacing)
                        {
                            origState.LetterSpacingAdjust = -1 * diff / (state.NumChars - origState.NumChars - 1);
                            SetPath(origState, false);
                            return;
                        }
                        else
                        {
                            using (var matrix = new Matrix())
                            {
                                matrix.Translate(-1 * bounds.X, 0, MatrixOrder.Append);
                                matrix.Scale(specLength / actLength, 1, MatrixOrder.Append);
                                matrix.Translate(bounds.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;
        }
Exemplo n.º 10
0
 private void SetPath(TextDrawingState state)
 {
     SetPath(state, true);
 }
Exemplo n.º 11
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>
        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 bounds     = path.GetBounds();
                    var specLength = this.TextLength.ToDeviceValue(state.Renderer, UnitRenderingType.Horizontal, this);
                    var actLength  = bounds.Width;
                    var diff       = (actLength - specLength);
                    if (Math.Abs(diff) > 1.5)
                    {
                        if (this.LengthAdjust == SvgTextLengthAdjust.spacing)
                        {
                            origState.LetterSpacingAdjust = -1 * diff / (state.NumChars - origState.NumChars - 1);
                            SetPath(origState, false);
                            return;
                        }
                        else
                        {
                            using (var matrix = new Matrix())
                            {
                                matrix.Translate(-1 * bounds.X, 0, MatrixOrder.Append);
                                matrix.Scale(specLength / actLength, 1, MatrixOrder.Append);
                                matrix.Translate(bounds.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;

            // If we have child tspans we need to correct the position to account for text-anchor
            var childTSpans = GetContentNodes().OfType <SvgTextSpan>().ToList();

            if (childTSpans.Count > 1) // If there's only one tspan we'll allow it to adjust itself in FlushPath()
            {
                if (!(TextAnchor == SvgTextAnchor.Middle || TextAnchor == SvgTextAnchor.End))
                {
                    return;
                }

                // BUG: If we have rotations things break
                // Skip them for now
                if (this.Transforms.OfType <SvgRotate>().Any())
                {
                    return;
                }

                // Need to split tspans by line
                // An element with an x attribute set seems to start a new render line
                var lines = new List <List <SvgTextSpan> >();
                foreach (var tspan in childTSpans)
                {
                    if (lines.Count == 0 || tspan.X.Any())
                    {
                        lines.Add(new List <SvgTextSpan>());
                    }

                    lines.Last().Add(tspan);
                }

                foreach (var line in lines)
                {
                    // Find total width of line
                    var totalLineWidth = line.Sum(o => o.Bounds.Width);
                    // BUG: If we have tspans with spaces in the source between them (like '<a></a> <b></b>'), they should be
                    // rendered with that space, but there's a bug elsewhere which does this wrong and ignores it.
                    // I'm also ignoring it here, because I don't know how to fix this correctly.

                    float xOffset = 0;
                    switch (TextAnchor)
                    {
                    case SvgTextAnchor.Middle:
                        xOffset = -totalLineWidth / 2;
                        break;

                    case SvgTextAnchor.End:
                        xOffset = -totalLineWidth;
                        break;

                    default:
                        throw new InvalidOperationException("Shouldn't have got here with TextAnchor " + TextAnchor);
                    }

                    using (var matrix = new Matrix())
                    {
                        matrix.Translate(xOffset, 0);

                        foreach (var node in line)
                        {
                            node._path.Transform(matrix);
                        }
                    }
                }

                // The path for the parent text node renders a black copy of the text for some reason
                _path.Reset();
            }
        }
Exemplo n.º 12
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>
        private void SetPath(TextDrawingState state, bool doMeasurements)
        {
            throw new NotImplementedException();
            //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 bounds = path.GetBounds();
            //        var specLength = this.TextLength.ToDeviceValue(state.Renderer, UnitRenderingType.Horizontal, this);
            //        var actLength = bounds.Width;
            //        var diff = (actLength - specLength);
            //        if (Math.Abs(diff) > 1.5)
            //        {
            //            if (this.LengthAdjust == SvgTextLengthAdjust.Spacing)
            //            {
            //                origState.LetterSpacingAdjust = -1 * diff / (state.NumChars - origState.NumChars - 1);
            //                SetPath(origState, false);
            //                return;
            //            }
            //            else
            //            {
            //                using (var matrix = new Matrix())
            //                {
            //                    matrix.Translate(-1 * bounds.X, 0, MatrixOrder.Append);
            //                    matrix.Scale(specLength / actLength, 1, MatrixOrder.Append);
            //                    matrix.Translate(bounds.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;
        }