Example #1
0
        //Find the first valid insertion position after or before the boundary node
        private bool _GetFirstFixedPosition(FixedTextPointer ftp, out FixedPosition fixedP)
        {
            LogicalDirection dir = LogicalDirection.Forward;

            if (ftp.FlowPosition.FlowNode.Fp != 0)
            {
                //End boundary
                dir = LogicalDirection.Backward;
            }
            FlowPosition flowP = (FlowPosition)ftp.FlowPosition.Clone();

            //Get the first node that comes before or after the boundary node(probably a start or end node)
            flowP.Move(dir);

            FixedTextPointer nav = new FixedTextPointer(true, dir, flowP);

            if (flowP.IsStart || flowP.IsEnd)
            {
                ((ITextPointer)nav).MoveToNextInsertionPosition(dir);
            }
            if (this.Container.GetPageNumber(nav) == this.PageIndex)
            {
                return(Container.FixedTextBuilder.GetFixedPosition(nav.FlowPosition, dir, out fixedP));
            }
            else
            {
                //This position is on another page.
                fixedP = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
                return(false);
            }
        }
Example #2
0
        //-------------------------------------------------------------------
        //
        //  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)
        /// unless the point is outside the boundaries of the page.
        /// 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)
        {
            //Return ITextPointer to the end of this view in this special case
            if (point.Y == Double.MaxValue && point.X == Double.MaxValue)
            {
                FixedPosition fixedp;
                ITextPointer  textPos = this.End;
                if (_GetFixedPosition(this.End, out fixedp))
                {
                    textPos = _CreateTextPointer(fixedp, LogicalDirection.Backward);
                    if (textPos == null)
                    {
                        textPos = this.End;
                    }
                }
                return(textPos);
            }

            ITextPointer pos = null;

            UIElement e;
            bool      isHit = _HitTest(point, out e);

            if (isHit)
            {
                Glyphs g = e as Glyphs;
                if (g != null)
                {
                    pos = _CreateTextPointerFromGlyphs(g, point);
                }
                else if (e is Image)
                {
                    Image         im     = (Image)e;
                    FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, im), 0);
                    pos = _CreateTextPointer(fixedp, LogicalDirection.Forward);
                }
                else if (e is Path)
                {
                    Path p = (Path)e;
                    if (p.Fill is ImageBrush)
                    {
                        FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, p), 0);
                        pos = _CreateTextPointer(fixedp, LogicalDirection.Forward);
                    }
                }
            }

            if (snapToText && pos == null)
            {
                pos = _SnapToText(point);
                Debug.Assert(pos != null);
            }


            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetTextPositionFromPoint P{0}, STT={1}, CP={2}", point, snapToText, pos == null ? "null" : ((FixedTextPointer)pos).ToString()));
            return(pos);
        }
        // Token: 0x06002EF8 RID: 12024 RVA: 0x000D4754 File Offset: 0x000D2954
        private ITextPointer _CreateTextPointer(FixedPosition fixedPosition, LogicalDirection edge)
        {
            FlowPosition flowPosition = this.Container.FixedTextBuilder.CreateFlowPosition(fixedPosition);

            if (flowPosition != null)
            {
                return(new FixedTextPointer(true, edge, flowPosition));
            }
            return(null);
        }
Example #4
0
        // Token: 0x0600350E RID: 13582 RVA: 0x000F0634 File Offset: 0x000EE834
        private ITextPointer _GetTextPosition(FixedNode node, int charIndex)
        {
            FixedPosition fixedPosition = new FixedPosition(node, charIndex);
            FlowPosition  flowPosition  = this._panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition);

            if (flowPosition != null)
            {
                return(new FixedTextPointer(false, LogicalDirection.Forward, flowPosition));
            }
            return(null);
        }
Example #5
0
        //--------------------------------------------------------------------
        // FlowPosition --> FixedPosition
        //---------------------------------------------------------------------

        // Helper function to overcome the limitation in FixedTextBuilder.GetFixedPosition
        // Making sure we are asking a position that is either a Run or an EmbeddedElement.
        private bool _GetFixedPosition(FixedTextPointer ftp, out FixedPosition fixedp)
        {
            LogicalDirection   textdir    = ftp.LogicalDirection;
            TextPointerContext symbolType = ((ITextPointer)ftp).GetPointerContext(textdir);

            if (ftp.FlowPosition.IsBoundary || symbolType == TextPointerContext.None)
            {
                return(_GetFirstFixedPosition(ftp, out fixedp));
            }

            if (symbolType == TextPointerContext.ElementStart || symbolType == TextPointerContext.ElementEnd)
            {
                //Try to find the first valid insertion position if exists
                switch (symbolType)
                {
                case TextPointerContext.ElementStart:
                    textdir = LogicalDirection.Forward;
                    break;

                case TextPointerContext.ElementEnd:
                    textdir = LogicalDirection.Backward;
                    break;
                }

                FixedTextPointer nav = new FixedTextPointer(true, textdir, (FlowPosition)ftp.FlowPosition.Clone());

                _SkipFormattingTags(nav);

                symbolType = ((ITextPointer)nav).GetPointerContext(textdir);
                if (symbolType != TextPointerContext.Text && symbolType != TextPointerContext.EmbeddedElement)
                {
                    //Try moving to the next insertion position
                    if (((ITextPointer)nav).MoveToNextInsertionPosition(textdir) &&
                        this.Container.GetPageNumber(nav) == this.PageIndex)
                    {
                        return(Container.FixedTextBuilder.GetFixedPosition(nav.FlowPosition, textdir, out fixedp));
                    }
                    else
                    {
                        fixedp = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
                        return(false);
                    }
                }
                else
                {
                    ftp = nav;
                }
            }

            Debug.Assert(symbolType == TextPointerContext.Text || symbolType == TextPointerContext.EmbeddedElement);
            return(Container.FixedTextBuilder.GetFixedPosition(ftp.FlowPosition, textdir, out fixedp));
        }
        // Token: 0x06002EF1 RID: 12017 RVA: 0x000D3FAC File Offset: 0x000D21AC
        private ITextPointer _SnapToText(Point point)
        {
            FixedNode[]  line = this.Container.FixedTextBuilder.GetLine(this.PageIndex, point);
            ITextPointer textPointer;

            if (line != null && line.Length != 0)
            {
                double    num       = double.MaxValue;
                double    xoffset   = 0.0;
                Glyphs    glyphs    = null;
                FixedNode fixedNode = line[0];
                foreach (FixedNode fixedNode2 in line)
                {
                    Glyphs           glyphsElement    = this.FixedPage.GetGlyphsElement(fixedNode2);
                    GeneralTransform generalTransform = this.FixedPage.TransformToDescendant(glyphsElement);
                    Point            inPoint          = point;
                    if (generalTransform != null)
                    {
                        generalTransform.TryTransform(inPoint, out inPoint);
                    }
                    GlyphRun glyphRun = glyphsElement.ToGlyphRun();
                    Rect     rect     = glyphRun.ComputeAlignmentBox();
                    rect.Offset(glyphsElement.OriginX, glyphsElement.OriginY);
                    double num2 = Math.Max(0.0, (inPoint.X > rect.X) ? (inPoint.X - rect.Right) : (rect.X - inPoint.X));
                    double num3 = Math.Max(0.0, (inPoint.Y > rect.Y) ? (inPoint.Y - rect.Bottom) : (rect.Y - inPoint.Y));
                    double num4 = num2 + num3;
                    if (glyphs == null || num4 < num)
                    {
                        num       = num4;
                        glyphs    = glyphsElement;
                        fixedNode = fixedNode2;
                        xoffset   = inPoint.X;
                    }
                }
                int offset;
                LogicalDirection edge;
                this._GlyphRunHitTest(glyphs, xoffset, out offset, out edge);
                FixedPosition fixedPosition = new FixedPosition(fixedNode, offset);
                textPointer = this._CreateTextPointer(fixedPosition, edge);
            }
            else if (point.Y < this.FixedPage.Height / 2.0)
            {
                textPointer = ((ITextPointer)this.Start).CreatePointer(LogicalDirection.Forward);
                textPointer.MoveToInsertionPosition(LogicalDirection.Forward);
            }
            else
            {
                textPointer = ((ITextPointer)this.End).CreatePointer(LogicalDirection.Backward);
                textPointer.MoveToInsertionPosition(LogicalDirection.Backward);
            }
            return(textPointer);
        }
Example #7
0
        //--------------------------------------------------------------------
        // FixedPosition --> ITextPointer
        //---------------------------------------------------------------------

        // Create a text position from description of a fixed position.
        // This is primarily called from HitTesting code
        private ITextPointer _CreateTextPointer(FixedPosition fixedPosition, LogicalDirection edge)
        {
            // Create a FlowPosition to represent this fixed position
            FlowPosition flowHit = Container.FixedTextBuilder.CreateFlowPosition(fixedPosition);

            if (flowHit != null)
            {
                DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("_CreatetTextPointer {0}:{1}", fixedPosition.ToString(), flowHit.ToString()));

                // Create a TextPointer from the flow position
                return(new FixedTextPointer(true, edge, flowHit));
            }
            return(null);
        }
Example #8
0
        private ITextPointer _GetTextPosition(FixedNode node, int charIndex)
        {
            FixedPosition fixedPosition = new FixedPosition(node, charIndex);

            // Create a FlowPosition to represent this fixed position
            FlowPosition flowHit = _panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition);

            if (flowHit != null)
            {
                // Create a TextPointer from the flow position
                return(new FixedTextPointer(false, LogicalDirection.Forward, flowHit));
            }
            return(null);
        }
        // Token: 0x06002EDE RID: 11998 RVA: 0x000D3528 File Offset: 0x000D1728
        internal override ITextPointer GetTextPositionFromPoint(Point point, bool snapToText)
        {
            if (point.Y == 1.7976931348623157E+308 && point.X == 1.7976931348623157E+308)
            {
                ITextPointer  textPointer = this.End;
                FixedPosition fixedPosition;
                if (this._GetFixedPosition(this.End, out fixedPosition))
                {
                    textPointer = this._CreateTextPointer(fixedPosition, LogicalDirection.Backward);
                    if (textPointer == null)
                    {
                        textPointer = this.End;
                    }
                }
                return(textPointer);
            }
            ITextPointer textPointer2 = null;
            UIElement    uielement;
            bool         flag = this._HitTest(point, out uielement);

            if (flag)
            {
                Glyphs glyphs = uielement as Glyphs;
                if (glyphs != null)
                {
                    textPointer2 = this._CreateTextPointerFromGlyphs(glyphs, point);
                }
                else if (uielement is Image)
                {
                    Image         e = (Image)uielement;
                    FixedPosition fixedPosition2 = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, e), 0);
                    textPointer2 = this._CreateTextPointer(fixedPosition2, LogicalDirection.Forward);
                }
                else if (uielement is Path)
                {
                    Path path = (Path)uielement;
                    if (path.Fill is ImageBrush)
                    {
                        FixedPosition fixedPosition3 = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, path), 0);
                        textPointer2 = this._CreateTextPointer(fixedPosition3, LogicalDirection.Forward);
                    }
                }
            }
            if (snapToText && textPointer2 == null)
            {
                textPointer2 = this._SnapToText(point);
            }
            return(textPointer2);
        }
        // Token: 0x06002EF9 RID: 12025 RVA: 0x000D4780 File Offset: 0x000D2980
        private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point)
        {
            GeneralTransform generalTransform = this.VisualRoot.TransformToDescendant(g);

            if (generalTransform != null)
            {
                generalTransform.TryTransform(point, out point);
            }
            int offset;
            LogicalDirection edge;

            this._GlyphRunHitTest(g, point.X, out offset, out edge);
            FixedPosition fixedPosition = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), offset);

            return(this._CreateTextPointer(fixedPosition, edge));
        }
Example #11
0
        // Create a text position from description of a fixed position.
        // This is primarily called from HitTesting code
        private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point)
        {
            GeneralTransform transform = this.VisualRoot.TransformToDescendant(g);

            if (transform != null)
            {
                transform.TryTransform(point, out point);
            }

            int charIndex;
            LogicalDirection edge;

            _GlyphRunHitTest(g, point.X, out charIndex, out edge);
            FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), charIndex);

            return(_CreateTextPointer(fixedp, edge));
        }
        // Token: 0x06002EF6 RID: 12022 RVA: 0x000D45B4 File Offset: 0x000D27B4
        private bool _GetFixedPosition(FixedTextPointer ftp, out FixedPosition fixedp)
        {
            LogicalDirection   logicalDirection = ftp.LogicalDirection;
            TextPointerContext pointerContext   = ((ITextPointer)ftp).GetPointerContext(logicalDirection);

            if (ftp.FlowPosition.IsBoundary || pointerContext == TextPointerContext.None)
            {
                return(this._GetFirstFixedPosition(ftp, out fixedp));
            }
            if (pointerContext == TextPointerContext.ElementStart || pointerContext == TextPointerContext.ElementEnd)
            {
                if (pointerContext != TextPointerContext.ElementStart)
                {
                    if (pointerContext == TextPointerContext.ElementEnd)
                    {
                        logicalDirection = LogicalDirection.Backward;
                    }
                }
                else
                {
                    logicalDirection = LogicalDirection.Forward;
                }
                FixedTextPointer fixedTextPointer = new FixedTextPointer(true, logicalDirection, (FlowPosition)ftp.FlowPosition.Clone());
                this._SkipFormattingTags(fixedTextPointer);
                pointerContext = ((ITextPointer)fixedTextPointer).GetPointerContext(logicalDirection);
                if (pointerContext != TextPointerContext.Text && pointerContext != TextPointerContext.EmbeddedElement)
                {
                    if (((ITextPointer)fixedTextPointer).MoveToNextInsertionPosition(logicalDirection) && this.Container.GetPageNumber(fixedTextPointer) == this.PageIndex)
                    {
                        return(this.Container.FixedTextBuilder.GetFixedPosition(fixedTextPointer.FlowPosition, logicalDirection, out fixedp));
                    }
                    fixedp = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
                    return(false);
                }
                else
                {
                    ftp = fixedTextPointer;
                }
            }
            return(this.Container.FixedTextBuilder.GetFixedPosition(ftp.FlowPosition, logicalDirection, out fixedp));
        }
        // Token: 0x06002EF7 RID: 12023 RVA: 0x000D46A8 File Offset: 0x000D28A8
        private bool _GetFirstFixedPosition(FixedTextPointer ftp, out FixedPosition fixedP)
        {
            LogicalDirection logicalDirection = LogicalDirection.Forward;

            if (ftp.FlowPosition.FlowNode.Fp != 0)
            {
                logicalDirection = LogicalDirection.Backward;
            }
            FlowPosition flowPosition = (FlowPosition)ftp.FlowPosition.Clone();

            flowPosition.Move(logicalDirection);
            FixedTextPointer fixedTextPointer = new FixedTextPointer(true, logicalDirection, flowPosition);

            if (flowPosition.IsStart || flowPosition.IsEnd)
            {
                ((ITextPointer)fixedTextPointer).MoveToNextInsertionPosition(logicalDirection);
            }
            if (this.Container.GetPageNumber(fixedTextPointer) == this.PageIndex)
            {
                return(this.Container.FixedTextBuilder.GetFixedPosition(fixedTextPointer.FlowPosition, logicalDirection, out fixedP));
            }
            fixedP = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
            return(false);
        }
        // Token: 0x06002EF2 RID: 12018 RVA: 0x000D4194 File Offset: 0x000D2394
        private bool _GetNextLineGlyphs(ref FixedPosition fixedp, ref LogicalDirection edge, double suggestedX, LogicalDirection scanDir)
        {
            int  num    = 1;
            int  page   = fixedp.Page;
            bool result = false;

            FixedNode[] nextLine = this.Container.FixedTextBuilder.GetNextLine(fixedp.Node, scanDir == LogicalDirection.Forward, ref num);
            if (nextLine != null && nextLine.Length != 0)
            {
                FixedPage fixedPage = this.Container.FixedDocument.SyncGetPage(page, false);
                if (double.IsInfinity(suggestedX))
                {
                    suggestedX = 0.0;
                }
                Point     point     = new Point(suggestedX, 0.0);
                Point     point2    = new Point(suggestedX, 1000.0);
                FixedNode fixedNode = nextLine[0];
                Glyphs    g         = null;
                double    num2      = double.MaxValue;
                double    xoffset   = 0.0;
                for (int i = nextLine.Length - 1; i >= 0; i--)
                {
                    FixedNode fixedNode2    = nextLine[i];
                    Glyphs    glyphsElement = fixedPage.GetGlyphsElement(fixedNode2);
                    if (glyphsElement != null)
                    {
                        GeneralTransform generalTransform = fixedPage.TransformToDescendant(glyphsElement);
                        Point            inPoint          = point;
                        Point            inPoint2         = point2;
                        if (generalTransform != null)
                        {
                            generalTransform.TryTransform(inPoint, out inPoint);
                            generalTransform.TryTransform(inPoint2, out inPoint2);
                        }
                        double   num3     = (inPoint2.X - inPoint.X) / (inPoint2.Y - inPoint.Y);
                        GlyphRun glyphRun = glyphsElement.ToGlyphRun();
                        Rect     rect     = glyphRun.ComputeAlignmentBox();
                        rect.Offset(glyphsElement.OriginX, glyphsElement.OriginY);
                        double num4;
                        double num5;
                        if (num3 > 1000.0 || num3 < -1000.0)
                        {
                            num4 = 0.0;
                            num5 = ((inPoint.Y > rect.Y) ? (inPoint.Y - rect.Bottom) : (rect.Y - inPoint.Y));
                        }
                        else
                        {
                            double num6 = (rect.Top + rect.Bottom) / 2.0;
                            num4 = inPoint.X + num3 * (num6 - inPoint.Y);
                            num5 = ((num4 > rect.X) ? (num4 - rect.Right) : (rect.X - num4));
                        }
                        if (num5 < num2)
                        {
                            num2      = num5;
                            xoffset   = num4;
                            fixedNode = fixedNode2;
                            g         = glyphsElement;
                            if (num5 <= 0.0)
                            {
                                break;
                            }
                        }
                    }
                }
                int offset;
                this._GlyphRunHitTest(g, xoffset, out offset, out edge);
                fixedp = new FixedPosition(fixedNode, offset);
                result = true;
            }
            return(result);
        }
        // If return false, nothing has been modified, which implies out of page boundary
        // The input of suggestedX is in the VisualRoot's cooridnate system
        private bool _GetNextLineGlyphs(ref FixedPosition fixedp, ref LogicalDirection edge, double suggestedX, LogicalDirection scanDir)
        {
            int count = 1;
            int pageIndex = fixedp.Page;
            bool moved = false;
            FixedNode[] fixedNodes = Container.FixedTextBuilder.GetNextLine(fixedp.Node, (scanDir == LogicalDirection.Forward), ref count);

            if (fixedNodes != null && fixedNodes.Length > 0)
            {
                FixedPage page = Container.FixedDocument.SyncGetPage(pageIndex, false);
                // This line contains multiple Glyhs. Scan backward
                // util we hit the first one whose OriginX is smaller 
                // then suggestedX;
                if (Double.IsInfinity(suggestedX))
                {
                    suggestedX = 0;
                }
                Point topOfPage = new Point(suggestedX, 0);
                Point secondPoint = new Point(suggestedX, 1000);

                FixedNode hitNode = fixedNodes[0];
                Glyphs hitGlyphs = null;
                double closestDistance = Double.MaxValue;
                double xoffset = 0;

                for (int i = fixedNodes.Length - 1; i >= 0; i--)
                {
                    FixedNode node = fixedNodes[i];
                    Glyphs g = page.GetGlyphsElement(node);
                    if (g != null)
                    {
                        GeneralTransform transform = page.TransformToDescendant(g);
                        Point pt1 = topOfPage;
                        Point pt2 = secondPoint;
                        if (transform != null)
                        {                            
                            transform.TryTransform(pt1, out pt1);
                            transform.TryTransform(pt2, out pt2);
                        }
                        double invSlope = (pt2.X - pt1.X) / (pt2.Y - pt1.Y);
                        double xoff, distance;

                        GlyphRun run = g.ToGlyphRun();
                        Rect box = run.ComputeAlignmentBox();
                        box.Offset(g.OriginX, g.OriginY);

                        if (invSlope > 1000 || invSlope < -1000)
                        {
                            // special case for vertical text
                            xoff = 0;
                            distance = (pt1.Y > box.Y) ? (pt1.Y - box.Bottom) : (box.Y - pt1.Y);
                        }
                        else
                        {
                            double centerY = (box.Top + box.Bottom) / 2;
                            xoff = pt1.X + invSlope * (centerY - pt1.Y);
                            distance = (xoff > box.X) ? (xoff - box.Right) : (box.X - xoff);
                        }

                        if (distance < closestDistance)
                        {
                            closestDistance = distance;
                            xoffset = xoff;
                            hitNode = node;
                            hitGlyphs = g;

                            if (distance <= 0)
                            {
                                break;
                            }
                        }
                    }
                }

                Debug.Assert(hitGlyphs != null);

                int charIdx;
                _GlyphRunHitTest(hitGlyphs, xoffset, out charIdx, out edge);

                fixedp = new FixedPosition(hitNode, charIdx);
                moved = true;
            }

            return moved;
        }
        private ITextPointer _SnapToText(Point point)
        {

            ITextPointer itp = null;
            FixedNode[] fixedNodes = Container.FixedTextBuilder.GetLine(this.PageIndex, point);
            if (fixedNodes != null && fixedNodes.Length > 0)
            {
                double closestDistance = Double.MaxValue;
                double xoffset = 0;
                Glyphs closestGlyphs = null;
                FixedNode closestNode = fixedNodes[0];

                foreach (FixedNode node in fixedNodes)
                {
                    Glyphs startGlyphs = this.FixedPage.GetGlyphsElement(node);
                    GeneralTransform tranToGlyphs = this.FixedPage.TransformToDescendant(startGlyphs);
                    Point transformedPt = point;
                    if (tranToGlyphs != null)
                    {                        
                        tranToGlyphs.TryTransform(transformedPt, out transformedPt);
                    }

                    GlyphRun run = startGlyphs.ToGlyphRun();
                    Rect alignmentRect = run.ComputeAlignmentBox();
                    alignmentRect.Offset(startGlyphs.OriginX, startGlyphs.OriginY);

                    double horizontalDistance = Math.Max(0, (transformedPt.X > alignmentRect.X) ? (transformedPt.X - alignmentRect.Right) : (alignmentRect.X - transformedPt.X));
                    double verticalDistance = Math.Max(0, (transformedPt.Y > alignmentRect.Y) ? (transformedPt.Y - alignmentRect.Bottom) : (alignmentRect.Y - transformedPt.Y));
                    double manhattanDistance = horizontalDistance + verticalDistance;

                    if (closestGlyphs == null || manhattanDistance < closestDistance)
                    {
                        closestDistance = manhattanDistance;
                        closestGlyphs = startGlyphs;
                        closestNode = node;
                        xoffset = transformedPt.X;
                    }
                }

                int index;
                LogicalDirection dir;
                _GlyphRunHitTest(closestGlyphs, xoffset, out index, out dir);

                FixedPosition fixedp = new FixedPosition(closestNode, index);
                itp = _CreateTextPointer(fixedp, dir);
				Debug.Assert(itp != null);
            }
            else
            {
                //
                // That condition is only possible when there is no line in the page
                //
                if (point.Y < this.FixedPage.Height / 2)
                {
                    itp = ((ITextPointer)this.Start).CreatePointer(LogicalDirection.Forward);
                    itp.MoveToInsertionPosition(LogicalDirection.Forward);
                }
                else
                {
                    itp = ((ITextPointer)this.End).CreatePointer(LogicalDirection.Backward);
                    itp.MoveToInsertionPosition(LogicalDirection.Backward);
                }
            }
            return itp;
        }
        //-------------------------------------------------------------------
        //
        //  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)
        /// unless the point is outside the boundaries of the page.
        /// 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)
        {
            //Return ITextPointer to the end of this view in this special case
            if (point.Y == Double.MaxValue && point.X == Double.MaxValue)
            {
                FixedPosition fixedp;
                ITextPointer textPos = this.End;
                if (_GetFixedPosition(this.End, out fixedp))
                {
                    textPos = _CreateTextPointer(fixedp, LogicalDirection.Backward);
                    if (textPos == null)
                    {
                        textPos = this.End;
                    }
                }
                return textPos;
            }
        
            ITextPointer pos = null;
            
            UIElement e;
            bool isHit = _HitTest(point, out e);
            if (isHit)
            {
                Glyphs g = e as Glyphs;
                if (g != null)
                {
                    pos = _CreateTextPointerFromGlyphs(g, point);
                }
                else if (e is Image)
                {
                    Image im = (Image)e;
                    FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, im), 0);
                    pos = _CreateTextPointer(fixedp, LogicalDirection.Forward);
                }
                else if (e is Path)
                {
                    Path p = (Path)e;
                    if (p.Fill is ImageBrush)
                    {
                        FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, p), 0);
                        pos = _CreateTextPointer(fixedp, LogicalDirection.Forward);
                    }
                }
            }

            if (snapToText && pos == null)
            {
                pos = _SnapToText(point);
                Debug.Assert(pos != null);
            }


            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetTextPositionFromPoint P{0}, STT={1}, CP={2}", point, snapToText, pos == null ? "null" : ((FixedTextPointer)pos).ToString()));
            return pos;
        }
        // Create a text position from description of a fixed position. 
        // This is primarily called from HitTesting code
        private ITextPointer _CreateTextPointerFromGlyphs(Glyphs g, Point point)
        {
            GeneralTransform transform = this.VisualRoot.TransformToDescendant(g);
            if (transform != null)
            {
                transform.TryTransform(point, out point);
            }

            int charIndex;
            LogicalDirection edge;
            _GlyphRunHitTest(g, point.X, out charIndex, out edge);
            FixedPosition fixedp = new FixedPosition(this.FixedPage.CreateFixedNode(this.PageIndex, g), charIndex);
            return _CreateTextPointer(fixedp, edge);
        }
        //--------------------------------------------------------------------
        // FixedPosition --> ITextPointer
        //---------------------------------------------------------------------

        // Create a text position from description of a fixed position. 
        // This is primarily called from HitTesting code
        private ITextPointer _CreateTextPointer(FixedPosition fixedPosition, LogicalDirection edge)
        {
            // Create a FlowPosition to represent this fixed position
            FlowPosition flowHit = Container.FixedTextBuilder.CreateFlowPosition(fixedPosition);
            if (flowHit != null)
            {
                DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("_CreatetTextPointer {0}:{1}", fixedPosition.ToString(), flowHit.ToString()));

                // Create a TextPointer from the flow position
                return new FixedTextPointer(true, edge, flowHit);
            }
            return null;
        }
Example #20
0
        private ITextPointer _SnapToText(Point point)
        {
            ITextPointer itp = null;

            FixedNode[] fixedNodes = Container.FixedTextBuilder.GetLine(this.PageIndex, point);
            if (fixedNodes != null && fixedNodes.Length > 0)
            {
                double    closestDistance = Double.MaxValue;
                double    xoffset         = 0;
                Glyphs    closestGlyphs   = null;
                FixedNode closestNode     = fixedNodes[0];

                foreach (FixedNode node in fixedNodes)
                {
                    Glyphs           startGlyphs   = this.FixedPage.GetGlyphsElement(node);
                    GeneralTransform tranToGlyphs  = this.FixedPage.TransformToDescendant(startGlyphs);
                    Point            transformedPt = point;
                    if (tranToGlyphs != null)
                    {
                        tranToGlyphs.TryTransform(transformedPt, out transformedPt);
                    }

                    GlyphRun run           = startGlyphs.ToGlyphRun();
                    Rect     alignmentRect = run.ComputeAlignmentBox();
                    alignmentRect.Offset(startGlyphs.OriginX, startGlyphs.OriginY);

                    double horizontalDistance = Math.Max(0, (transformedPt.X > alignmentRect.X) ? (transformedPt.X - alignmentRect.Right) : (alignmentRect.X - transformedPt.X));
                    double verticalDistance   = Math.Max(0, (transformedPt.Y > alignmentRect.Y) ? (transformedPt.Y - alignmentRect.Bottom) : (alignmentRect.Y - transformedPt.Y));
                    double manhattanDistance  = horizontalDistance + verticalDistance;

                    if (closestGlyphs == null || manhattanDistance < closestDistance)
                    {
                        closestDistance = manhattanDistance;
                        closestGlyphs   = startGlyphs;
                        closestNode     = node;
                        xoffset         = transformedPt.X;
                    }
                }

                int index;
                LogicalDirection dir;
                _GlyphRunHitTest(closestGlyphs, xoffset, out index, out dir);

                FixedPosition fixedp = new FixedPosition(closestNode, index);
                itp = _CreateTextPointer(fixedp, dir);
                Debug.Assert(itp != null);
            }
            else
            {
                //
                // That condition is only possible when there is no line in the page
                //
                if (point.Y < this.FixedPage.Height / 2)
                {
                    itp = ((ITextPointer)this.Start).CreatePointer(LogicalDirection.Forward);
                    itp.MoveToInsertionPosition(LogicalDirection.Forward);
                }
                else
                {
                    itp = ((ITextPointer)this.End).CreatePointer(LogicalDirection.Backward);
                    itp.MoveToInsertionPosition(LogicalDirection.Backward);
                }
            }
            return(itp);
        }
        /// <summary>
        /// <see cref="DynamicDocumentPaginator.GetObjectPosition"/>
        /// </summary>
        /// <exception cref="ArgumentNullException">element is NULL.</exception>
        internal ContentPosition GetObjectPosition(Object o)
        {
            if (o == null)
            {
                throw new ArgumentNullException("o");
            }
            
            DependencyObject element = o as DependencyObject;

            if (element == null)
            {
                throw new ArgumentException(SR.Get(SRID.FixedDocumentExpectsDependencyObject));
            }
            DocumentsTrace.FixedFormat.IDF.Trace(string.Format("IDF.GetContentPositionForElement({0})", element));
            // Make sure that the call is in the right context.
//             Dispatcher.VerifyAccess();


            // walk up the logical parent chain to find the containing page
            FixedPage fixedPage = null;
            int pageIndex = -1;
            if (element != this)
            {
                DependencyObject el = element;
                while (el != null)
                {
                    fixedPage = el as FixedPage;

                    if (fixedPage != null)
                    {
                        pageIndex = GetIndexOfPage(fixedPage);
                        if (pageIndex >= 0)
                        {
                            break;
                        }
                        el = fixedPage.Parent;
                    }
                    else
                    {
                        el = LogicalTreeHelper.GetParent(el);
                    }
                }
            }
            else if (this.Pages.Count > 0)
            {
                // if FixedDocument is requested, return ContentPosition for the first page.
                pageIndex = 0;
            }

            // get FixedTextPointer for element or page index
            FixedTextPointer fixedTextPointer = null;
            if (pageIndex >= 0)
            {
                FixedPosition fixedPosition;
                FlowPosition flowPosition=null;
                System.Windows.Shapes.Path p = element as System.Windows.Shapes.Path;
                if (element is Glyphs || element is Image || (p != null &&  p.Fill is ImageBrush))
                {
                    fixedPosition = new FixedPosition(fixedPage.CreateFixedNode(pageIndex, (UIElement)element), 0);
                    flowPosition = FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition);
                }
                if (flowPosition == null)
                {
                    flowPosition = FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(pageIndex);
                }
                fixedTextPointer = new FixedTextPointer(true, LogicalDirection.Forward, flowPosition);
            }

            return (fixedTextPointer != null) ? fixedTextPointer : ContentPosition.Missing;
        }
Example #22
0
        private ITextPointer _GetTextPosition(FixedNode node, int charIndex) 
        {
            FixedPosition fixedPosition = new FixedPosition(node, charIndex); 
 
            // Create a FlowPosition to represent this fixed position
            FlowPosition flowHit = _panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); 
            if (flowHit != null)
            {
                // Create a TextPointer from the flow position
                return new FixedTextPointer(false, LogicalDirection.Forward, flowHit); 
            }
            return null; 
        } 
        //--------------------------------------------------------------------
        // FlowPosition --> FixedPosition
        //---------------------------------------------------------------------

        // Helper function to overcome the limitation in FixedTextBuilder.GetFixedPosition 
        // Making sure we are asking a position that is either a Run or an EmbeddedElement. 
        private bool _GetFixedPosition(FixedTextPointer ftp, out FixedPosition fixedp)
        {
            LogicalDirection textdir = ftp.LogicalDirection;
            TextPointerContext symbolType = ((ITextPointer)ftp).GetPointerContext(textdir);

            if (ftp.FlowPosition.IsBoundary || symbolType == TextPointerContext.None)
            {
                return _GetFirstFixedPosition(ftp, out fixedp);
            }

            if (symbolType == TextPointerContext.ElementStart || symbolType == TextPointerContext.ElementEnd)
            {
                //Try to find the first valid insertion position if exists
                switch (symbolType)
                {
                case TextPointerContext.ElementStart:
                    textdir = LogicalDirection.Forward;
                    break;
                case TextPointerContext.ElementEnd:
                    textdir = LogicalDirection.Backward;
                    break;
                }

                FixedTextPointer nav = new FixedTextPointer(true, textdir, (FlowPosition)ftp.FlowPosition.Clone());

                _SkipFormattingTags(nav);

                symbolType = ((ITextPointer)nav).GetPointerContext(textdir);
                if (symbolType != TextPointerContext.Text && symbolType != TextPointerContext.EmbeddedElement)
                {
                    //Try moving to the next insertion position
                    if (((ITextPointer)nav).MoveToNextInsertionPosition(textdir) &&
                        this.Container.GetPageNumber(nav) == this.PageIndex)
                    {
                        return Container.FixedTextBuilder.GetFixedPosition(nav.FlowPosition, textdir, out fixedp);
                    }
                    else
                    {
                        fixedp = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
                        return false;
                    }
                }
                else
                {
                    ftp = nav;
                }
            }

            Debug.Assert(symbolType == TextPointerContext.Text || symbolType == TextPointerContext.EmbeddedElement);
            return Container.FixedTextBuilder.GetFixedPosition(ftp.FlowPosition, textdir, out fixedp);
        }
        //Find the first valid insertion position after or before the boundary node
        private bool _GetFirstFixedPosition(FixedTextPointer ftp, out FixedPosition fixedP)
        {
            LogicalDirection dir = LogicalDirection.Forward;
            if (ftp.FlowPosition.FlowNode.Fp != 0)
            {
                //End boundary
                dir = LogicalDirection.Backward;
            }
            FlowPosition flowP = (FlowPosition) ftp.FlowPosition.Clone();
            //Get the first node that comes before or after the boundary node(probably a start or end node)
            flowP.Move(dir);

            FixedTextPointer nav = new FixedTextPointer(true, dir, flowP);
            if (flowP.IsStart || flowP.IsEnd)
            {
                ((ITextPointer)nav).MoveToNextInsertionPosition(dir);
            }
            if (this.Container.GetPageNumber(nav) == this.PageIndex)
            {
                return Container.FixedTextBuilder.GetFixedPosition(nav.FlowPosition, dir, out fixedP);
            }
            else
            {
                //This position is on another page.
                fixedP = new FixedPosition(this.Container.FixedTextBuilder.FixedFlowMap.FixedStartEdge, 0);
                return false;
            }
        }
Example #25
0
        // If return false, nothing has been modified, which implies out of page boundary
        // The input of suggestedX is in the VisualRoot's cooridnate system
        private bool _GetNextLineGlyphs(ref FixedPosition fixedp, ref LogicalDirection edge, double suggestedX, LogicalDirection scanDir)
        {
            int  count     = 1;
            int  pageIndex = fixedp.Page;
            bool moved     = false;

            FixedNode[] fixedNodes = Container.FixedTextBuilder.GetNextLine(fixedp.Node, (scanDir == LogicalDirection.Forward), ref count);

            if (fixedNodes != null && fixedNodes.Length > 0)
            {
                FixedPage page = Container.FixedDocument.SyncGetPage(pageIndex, false);
                // This line contains multiple Glyhs. Scan backward
                // util we hit the first one whose OriginX is smaller
                // then suggestedX;
                if (Double.IsInfinity(suggestedX))
                {
                    suggestedX = 0;
                }
                Point topOfPage   = new Point(suggestedX, 0);
                Point secondPoint = new Point(suggestedX, 1000);

                FixedNode hitNode         = fixedNodes[0];
                Glyphs    hitGlyphs       = null;
                double    closestDistance = Double.MaxValue;
                double    xoffset         = 0;

                for (int i = fixedNodes.Length - 1; i >= 0; i--)
                {
                    FixedNode node = fixedNodes[i];
                    Glyphs    g    = page.GetGlyphsElement(node);
                    if (g != null)
                    {
                        GeneralTransform transform = page.TransformToDescendant(g);
                        Point            pt1       = topOfPage;
                        Point            pt2       = secondPoint;
                        if (transform != null)
                        {
                            transform.TryTransform(pt1, out pt1);
                            transform.TryTransform(pt2, out pt2);
                        }
                        double invSlope = (pt2.X - pt1.X) / (pt2.Y - pt1.Y);
                        double xoff, distance;

                        GlyphRun run = g.ToGlyphRun();
                        Rect     box = run.ComputeAlignmentBox();
                        box.Offset(g.OriginX, g.OriginY);

                        if (invSlope > 1000 || invSlope < -1000)
                        {
                            // special case for vertical text
                            xoff     = 0;
                            distance = (pt1.Y > box.Y) ? (pt1.Y - box.Bottom) : (box.Y - pt1.Y);
                        }
                        else
                        {
                            double centerY = (box.Top + box.Bottom) / 2;
                            xoff     = pt1.X + invSlope * (centerY - pt1.Y);
                            distance = (xoff > box.X) ? (xoff - box.Right) : (box.X - xoff);
                        }

                        if (distance < closestDistance)
                        {
                            closestDistance = distance;
                            xoffset         = xoff;
                            hitNode         = node;
                            hitGlyphs       = g;

                            if (distance <= 0)
                            {
                                break;
                            }
                        }
                    }
                }

                Debug.Assert(hitGlyphs != null);

                int charIdx;
                _GlyphRunHitTest(hitGlyphs, xoffset, out charIdx, out edge);

                fixedp = new FixedPosition(hitNode, charIdx);
                moved  = true;
            }

            return(moved);
        }
        // Token: 0x06002CC1 RID: 11457 RVA: 0x000C9D38 File Offset: 0x000C7F38
        internal ContentPosition GetObjectPosition(object o)
        {
            if (o == null)
            {
                throw new ArgumentNullException("o");
            }
            DependencyObject dependencyObject = o as DependencyObject;

            if (dependencyObject == null)
            {
                throw new ArgumentException(SR.Get("FixedDocumentExpectsDependencyObject"));
            }
            FixedPage fixedPage = null;
            int       num       = -1;

            if (dependencyObject != this)
            {
                DependencyObject dependencyObject2 = dependencyObject;
                while (dependencyObject2 != null)
                {
                    fixedPage = (dependencyObject2 as FixedPage);
                    if (fixedPage != null)
                    {
                        num = this.GetIndexOfPage(fixedPage);
                        if (num >= 0)
                        {
                            break;
                        }
                        dependencyObject2 = fixedPage.Parent;
                    }
                    else
                    {
                        dependencyObject2 = LogicalTreeHelper.GetParent(dependencyObject2);
                    }
                }
            }
            else if (this.Pages.Count > 0)
            {
                num = 0;
            }
            FixedTextPointer fixedTextPointer = null;

            if (num >= 0)
            {
                FlowPosition flowPosition       = null;
                System.Windows.Shapes.Path path = dependencyObject as System.Windows.Shapes.Path;
                if (dependencyObject is Glyphs || dependencyObject is Image || (path != null && path.Fill is ImageBrush))
                {
                    FixedPosition fixedPosition = new FixedPosition(fixedPage.CreateFixedNode(num, (UIElement)dependencyObject), 0);
                    flowPosition = this.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition);
                }
                if (flowPosition == null)
                {
                    flowPosition = this.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(num);
                }
                fixedTextPointer = new FixedTextPointer(true, LogicalDirection.Forward, flowPosition);
            }
            if (fixedTextPointer == null)
            {
                return(ContentPosition.Missing);
            }
            return(fixedTextPointer);
        }