Пример #1
0
        internal ITextPointer GetTextPositionFromDistance(int dcpLine, double distance) 
        {
            // Query paragraph details 
            int urDistance = TextDpi.ToTextDpi(distance); 
            PTS.FSTEXTDETAILS textDetails;
            PTS.Validate(PTS.FsQueryTextDetails(PtsContext.Context, _paraHandle.Value, out textDetails)); 

            if(ThisFlowDirection != PageFlowDirection)
            {
                urDistance = _pageContext.PageRect.du - urDistance; 
            }
 
            int lineWidth = 0; 
            bool firstLine = (dcpLine == 0);
            int dcpLim = 0; 
            IntPtr breakRecLine = IntPtr.Zero;

            // There are 3 different types of text paragraphs:
            // (a) full with simple lines 
            // (b) full with composite lines - when figures/floaters are present
            // (c) cached - when using ParaChache 
            if (textDetails.fsktd == PTS.FSKTEXTDETAILS.fsktdFull) 
            {
                if (textDetails.u.full.cLines > 0) 
                {
                    if (!PTS.ToBoolean(textDetails.u.full.fLinesComposite))
                    {
                        // (a) full with simple lines 
                        PTS.FSLINEDESCRIPTIONSINGLE [] arrayLineDesc;
                        PtsHelper.LineListSimpleFromTextPara(PtsContext, _paraHandle.Value, ref textDetails.u.full, out arrayLineDesc); 
 
                        // Get lines information
                        int index; 
                        for (index = 0; index < arrayLineDesc.Length; index++)
                        {
                            PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[index];
                            if (dcpLine == lineDesc.dcpFirst) 
                            {
                                lineWidth = lineDesc.dur; 
                                urDistance -= lineDesc.urStart; 

                                // Store dcpLim to check if line lengths are in [....] 
                                dcpLim = lineDesc.dcpLim;

                                breakRecLine = lineDesc.pfsbreakreclineclient;
 
                                break;
                            } 
                        } 
                    }
                    else 
                    {
                        // (b) full with composite lines - when figures/floaters are present
                        PTS.FSLINEDESCRIPTIONCOMPOSITE [] arrayLineDesc;
                        PtsHelper.LineListCompositeFromTextPara(PtsContext, _paraHandle.Value, ref textDetails.u.full, out arrayLineDesc); 

                        // Get lines information 
                        int index; 
                        for (index = 0; index < arrayLineDesc.Length; index++)
                        { 
                            PTS.FSLINEDESCRIPTIONCOMPOSITE lineDesc = arrayLineDesc[index];
                            if (lineDesc.cElements == 0) continue;

                            // Get list of line elements. 
                            PTS.FSLINEELEMENT [] arrayLineElement;
                            PtsHelper.LineElementListFromCompositeLine(PtsContext, ref lineDesc, out arrayLineElement); 
 
                            int elIndex;
                            for (elIndex = 0; elIndex < arrayLineElement.Length; elIndex++) 
                            {
                                PTS.FSLINEELEMENT element = arrayLineElement[elIndex];

                                if (element.dcpFirst == dcpLine) 
                                {
                                    lineWidth = element.dur; 
                                    urDistance -= element.urStart; 

                                    // Store dcpLim to check if line lengths are in [....] 
                                    dcpLim = element.dcpLim;

                                    breakRecLine = element.pfsbreakreclineclient;
 
                                    break;
                                } 
                            } 
                            if (elIndex < arrayLineElement.Length)
                            { 
                                firstLine = (index == 0);
                                break;
                            }
                        } 
                    }
                } 
            } 
            else
            { 
                // (c) cached - when using ParaChache
                Debug.Assert(textDetails.fsktd == PTS.FSKTEXTDETAILS.fsktdCached);
                Debug.Assert(false, "Should not get here. ParaCache is not currently used.");
            } 

            // Recreate text line 
            Line.FormattingContext ctx = new Line.FormattingContext(false, true, true, TextParagraph.TextRunCache); 
            Line line = new Line(Paragraph.StructuralCache.TextFormatterHost, this, Paragraph.ParagraphStartCharacterPosition);
 
            if(IsOptimalParagraph)
            {
                ctx.LineFormatLengthTarget = dcpLim - dcpLine;
            } 

            TextParagraph.FormatLineCore(line, breakRecLine, ctx, dcpLine, lineWidth, firstLine, dcpLine); 
 
            // Assert that number of characters in Text line is the same as our expected length
            Invariant.Assert(line.SafeLength == dcpLim - dcpLine, "Line length is out of [....]"); 

            CharacterHit charHit = line.GetTextPositionFromDistance(urDistance);
            int cpPosition = charHit.FirstCharacterIndex + charHit.TrailingLength;
            int dcpLastAttachedObject = TextParagraph.GetLastDcpAttachedObjectBeforeLine(dcpLine); 
            if(cpPosition < dcpLastAttachedObject)
            { 
                cpPosition = dcpLastAttachedObject; 
            }
 
            StaticTextPointer pos = TextContainerHelper.GetStaticTextPointerFromCP(Paragraph.StructuralCache.TextContainer, cpPosition + Paragraph.ParagraphStartCharacterPosition);
            LogicalDirection logicalDirection = (charHit.TrailingLength > 0) ? LogicalDirection.Backward : LogicalDirection.Forward;
            line.Dispose();
 
            return pos.CreateDynamicTextPointer(logicalDirection);
        }