/// <summary>
        /// Returns a TextSegment that spans the line on which position is located.
        /// </summary>
        /// <param name="position">
        /// Any oriented text position on the line.
        /// </param>
        /// <returns>
        /// TextSegment that spans the line on which position is located.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        internal override TextSegment GetLineRange(ITextPointer position)
        {
            DocumentsTrace.FixedDocumentSequence.TextOM.Trace(string.Format("GetLineRange {0} {1}", position, position.LogicalDirection));
            DocumentSequenceTextPointer tpStart = null;
            DocumentSequenceTextPointer tpEnd   = null;
            DocumentSequenceTextPointer tpLine  = null;

            if (position != null)
            {
                if (ChildTextView != null)
                {
                    tpLine = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(position);

                    if (ChildTextView.TextContainer == tpLine.ChildBlock.ChildContainer)
                    {
                        TextSegment childTR = ChildTextView.GetLineRange(tpLine.ChildPointer.CreatePointer(position.LogicalDirection));
                        if (!childTR.IsNull)
                        {
                            tpStart = new DocumentSequenceTextPointer(ChildBlock, childTR.Start);
                            tpEnd   = new DocumentSequenceTextPointer(ChildBlock, childTR.End);
                            return(new TextSegment(tpStart, tpEnd, true));
                        }
                    }
                }
            }
            return(TextSegment.Null);
        }
        /// <summary>
        /// Retrieves an oriented text position matching position advanced by
        /// a number of lines from its initial position.
        /// </summary>
        /// <param name="position">
        /// Initial text position of an object/character.
        /// </param>
        /// <param name="suggestedX">
        /// The suggested X offset, in pixels, of text position on the destination
        /// line. If suggestedX is set to Double.NaN it will be ignored, otherwise
        /// the method will try to find a position on the destination line closest
        /// to suggestedX.
        /// </param>
        /// <param name="count">
        /// Number of lines to advance. Negative means move backwards.
        /// </param>
        /// <param name="newSuggestedX">
        /// newSuggestedX is the offset at the position moved (useful when moving
        /// between columns or pages).
        /// </param>
        /// <param name="linesMoved">
        /// linesMoved indicates the number of lines moved, which may be less
        /// than count if there is no more content.
        /// </param>
        /// <returns>
        /// A TextPointer and its orientation matching suggestedX on the
        /// destination line.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
        {
            newSuggestedX = suggestedX;
            linesMoved    = count;

            DocumentsTrace.FixedDocumentSequence.TextOM.Trace(string.Format("GetPositionAtNextLine {0} {1} {2} {3} ", position, position.LogicalDirection, suggestedX, count));
            DocumentSequenceTextPointer newTp   = null;
            LogicalDirection            newEdge = LogicalDirection.Forward;
            DocumentSequenceTextPointer tp      = null;

            if (position != null)
            {
                tp = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(position);
            }

            // Note we do not handle cross page navigation
            if (tp != null)
            {
                if (ChildTextView != null)
                {
                    if (ChildTextView.TextContainer == tp.ChildBlock.ChildContainer)
                    {
                        ITextPointer childOTP = ChildTextView.GetPositionAtNextLine(tp.ChildPointer.CreatePointer(position.LogicalDirection), suggestedX, count, out newSuggestedX, out linesMoved);
                        if (childOTP != null)
                        {
                            newTp   = new DocumentSequenceTextPointer(ChildBlock, childOTP);
                            newEdge = childOTP.LogicalDirection;
                        }
                    }
                }
            }
            return(DocumentSequenceTextPointer.CreatePointer(newTp, newEdge));
        }
        /// <summary>
        /// Retrieves the height and offset, in pixels, of the edge of
        /// the object/character represented by position.
        /// </summary>
        /// <param name="position">
        /// Position of an object/character.
        /// </param>
        /// <param name="transform">
        /// Transform to be applied to returned rect
        /// </param>
        /// <returns>
        /// The height, in pixels, of the edge of the object/character
        /// represented by position.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        /// <remarks>
        /// Rect.Width is always 0.
        ///
        /// If the document is empty, then this method returns the expected
        /// height of a character, if placed at the specified position.
        /// </remarks>
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
            DocumentsTrace.FixedDocumentSequence.TextOM.Trace(string.Format("GetRawRectangleFromTextPosition {0} {1}", position, position.LogicalDirection));
            DocumentSequenceTextPointer tp = null;

            // Initialize transform to identity
            transform = Transform.Identity;

            if (position != null)
            {
                tp = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(position);
            }

            if (tp != null)
            {
                if (ChildTextView != null)
                {
                    if (ChildTextView.TextContainer == tp.ChildBlock.ChildContainer)
                    {
                        return(ChildTextView.GetRawRectangleFromTextPosition(tp.ChildPointer.CreatePointer(position.LogicalDirection), out transform));
                    }
                }
            }
            return(Rect.Empty);
        }
        /// <see cref="ITextView.Validate(Point)"/>
        internal override bool Validate(Point point)
        {
            if (ChildTextView != null)
            {
                ChildTextView.Validate(point);
            }

            return(((ITextView)this).IsValid);
        }
        /// <summary>
        /// <see cref="TextViewBase.GetTightBoundingGeometryFromTextPositions"/>
        /// </summary>
        internal override Geometry GetTightBoundingGeometryFromTextPositions(ITextPointer startPosition, ITextPointer endPosition)
        {
            if (startPosition != null && endPosition != null && ChildTextView != null)
            {
                DocumentSequenceTextPointer startTp = null;
                DocumentSequenceTextPointer endTp   = null;

                startTp = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(startPosition);
                endTp   = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(endPosition);

                if (startTp != null && endTp != null)
                {
                    return(ChildTextView.GetTightBoundingGeometryFromTextPositions(startTp.ChildPointer, endTp.ChildPointer));
                }
            }

            return(new PathGeometry());;
        }
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Retrieves a position matching a point.
        /// </summary>
        /// <param name="point">
        /// Point in pixel coordinates to test.
        /// </param>
        /// <param name="snapToText">
        /// If true, this method must always return a positioned text position
        /// (the closest position as calculated by the control's heuristics).
        /// If false, this method should return null position, if the test
        /// point does not fall within any character bounding box.
        /// </param>
        /// <returns>
        /// A text position and its orientation matching or closest to the point.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText)
        {
            DocumentsTrace.FixedDocumentSequence.TextOM.Trace(string.Format("GetTextPositionFromPoint {0}-{1}", point, snapToText));
            DocumentSequenceTextPointer tp   = null;
            LogicalDirection            edge = LogicalDirection.Forward;

            if (ChildTextView != null)
            {
                ITextPointer childOTP = ChildTextView.GetTextPositionFromPoint(point, snapToText);
                if (childOTP != null)
                {
                    tp   = new DocumentSequenceTextPointer(ChildBlock, childOTP);
                    edge = childOTP.LogicalDirection;
                }
            }

            // When snapToText is true, ChildTextView.GetTextPositionFromPoint will guranttee to
            // return a non-null position.
            // In current code, ChildTextView can't be null.
            return(tp == null ? null : DocumentSequenceTextPointer.CreatePointer(tp, edge));
        }
        /// <summary>
        /// Determines whenever TextView contains specified position.
        /// </summary>
        /// <param name="position">
        /// A position to test.
        /// </param>
        /// <returns>
        /// True if TextView contains specified text position.
        /// Otherwise returns false.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        internal override bool Contains(ITextPointer position)
        {
            DocumentsTrace.FixedDocumentSequence.TextOM.Trace(string.Format("Contains {0} {1}", position, position.LogicalDirection));
            DocumentSequenceTextPointer tp = null;

            if (position != null)
            {
                tp = _docPage.FixedDocumentSequence.TextContainer.VerifyPosition(position);
            }

            // Note we do not handle cross page navigation
            if (tp != null)
            {
                if (ChildTextView != null)
                {
                    if (ChildTextView.TextContainer == tp.ChildBlock.ChildContainer)
                    {
                        return(ChildTextView.Contains(tp.ChildPointer.CreatePointer(position.LogicalDirection)));
                    }
                }
            }
            return(false);
        }