Exemplo n.º 1
0
        private void PaintLineBackgroundAndExcludeSelectedTextFromClipRegion(DeviceContext deviceContext, PaintOptions paintOptions,
            ScriptLine* scriptLine, ScriptParagraph* scriptParagraph,
            int scriptRunIndex, int scriptRunCount, int* visualToLogicalMap,
            int xStartPosition, int xEndPosition,
            Rectangle layoutRect, int selectedCharIndex, int selectedCharCount)
        {
            IntPtr brush = DeviceContext.GetStockObject(NativeConstants.DC_BRUSH);
            deviceContext.SetDCBrushColor(paintOptions.SelectedBackgroundColor);

            int yCurrentBaseline = scriptLine->Y + scriptLine->Ascent;
            int xCurrentPosition = scriptLine->X;
            for (int i = 0; i < scriptRunCount; i++)
            {
                int logicalScriptRunIndex = visualToLogicalMap[currentLayoutRightToLeft ? scriptRunCount - i - 1 : i];
                ScriptRun* scriptRun = scriptParagraph->ScriptRuns + logicalScriptRunIndex + scriptRunIndex;

                int measuredWidth;
                switch (scriptRun->RunKind)
                {
                    case RunKind.Text:
                    {
                        int glyphIndexInParagraph, glyphCount;
                        int truncatedLeadingCharsCount = logicalScriptRunIndex == 0
                            ? scriptLine->TruncatedLeadingCharsCount
                            : 0;
                        int truncatedTrailingCharsCount = logicalScriptRunIndex == scriptRunCount - 1
                            ? scriptLine->TruncatedTrailingCharsCount
                            : 0;
                        measuredWidth = MeasureTextScriptRun(scriptParagraph, scriptRun,
                            truncatedLeadingCharsCount, truncatedTrailingCharsCount,
                            out glyphIndexInParagraph, out glyphCount);

                        if (xCurrentPosition + measuredWidth > xStartPosition)
                        {
                            int scriptRunCharIndex = scriptParagraph->CharIndex + scriptRun->CharIndexInParagraph;
                            int leadingCharIndex = scriptRunCharIndex + truncatedLeadingCharsCount;
                            int trailingCharIndex = scriptRunCharIndex + scriptRun->CharCount -
                                truncatedTrailingCharsCount;
                            if (trailingCharIndex >= selectedCharIndex &&
                                leadingCharIndex <= selectedCharIndex + selectedCharCount)
                            {
                                int relativePositionOfSelection;
                                if (leadingCharIndex >= selectedCharIndex)
                                {
                                    relativePositionOfSelection = 0;
                                }
                                else
                                {
                                    relativePositionOfSelection = MeasureTextScriptRun(scriptParagraph, scriptRun,
                                        truncatedLeadingCharsCount,
                                        truncatedTrailingCharsCount + trailingCharIndex - selectedCharIndex,
                                        out glyphIndexInParagraph, out glyphCount);
                                }

                                int measuredWidthOfSelection;
                                if (trailingCharIndex <= selectedCharIndex + selectedCharCount)
                                {
                                    measuredWidthOfSelection = measuredWidth - relativePositionOfSelection;
                                }
                                else
                                {
                                    measuredWidthOfSelection = MeasureTextScriptRun(scriptParagraph, scriptRun,
                                        truncatedLeadingCharsCount + Math.Max(selectedCharIndex - leadingCharIndex, 0),
                                        truncatedTrailingCharsCount + trailingCharIndex - selectedCharIndex -
                                            selectedCharCount,
                                        out glyphIndexInParagraph, out glyphCount);
                                }

                                int x = currentLayoutRightToLeft
                                    ? layoutRect.Right - xCurrentPosition - measuredWidth
                                    : layoutRect.Left + xCurrentPosition;
                                int y = layoutRect.Top + yCurrentBaseline - scriptRun->Ascent;

                                if (scriptRun->ScriptAnalysis.fRTL)
                                    x += measuredWidth - relativePositionOfSelection - measuredWidthOfSelection;
                                else
                                    x += relativePositionOfSelection;

                                Rectangle selectedRect = new Rectangle(x, y, measuredWidthOfSelection, scriptRun->Height);
                                deviceContext.FillRect(selectedRect, brush);
                                deviceContext.ExcludeClipRect(selectedRect);
                            }
                        }
                        break;
                    }

                    case RunKind.Object:
                    case RunKind.Tab:
                    {
                        measuredWidth = scriptRun->RunKind == RunKind.Object
                            ? MeasureObjectScriptRun(scriptRun)
                            : MeasureTabScriptRun(scriptRun,
                                GetParagraphStyleAssumingItHasAtLeastOneRun(scriptParagraph),
                                xCurrentPosition, false);

                        if (xCurrentPosition + measuredWidth > xStartPosition)
                        {
                            int leadingCharIndex = scriptParagraph->CharIndex + scriptRun->CharIndexInParagraph;
                            int trailingCharIndex = leadingCharIndex + 1;
                            if (trailingCharIndex >= selectedCharIndex &&
                                leadingCharIndex <= selectedCharIndex + selectedCharCount)
                            {
                                int x = currentLayoutRightToLeft
                                    ? layoutRect.Right - xCurrentPosition - measuredWidth
                                    : layoutRect.Left + xCurrentPosition;
                                int y = layoutRect.Top + yCurrentBaseline - scriptRun->Ascent;

                                Rectangle selectedRect = new Rectangle(x, y, measuredWidth, scriptRun->Height);
                                deviceContext.FillRect(selectedRect, brush);
                                // Don't exclude clip rect for objects and tabs.
                                //deviceContext.ExcludeClipRect(selectedRect);
                            }
                        }
                        break;
                    }

                    default:
                        throw new NotSupportedException();
                }

                xCurrentPosition += measuredWidth;

                if (xCurrentPosition >= xEndPosition)
                    break; // can't fit any more runs within the clip rectangle
            }
        }
Exemplo n.º 2
0
        private void PaintLineForeground(DeviceContext deviceContext, PaintOptions paintOptions,
            ScriptLine* scriptLine, ScriptParagraph* scriptParagraph,
            int scriptRunIndex, int scriptRunCount, int* visualToLogicalMap,
            int xStartPosition, int xEndPosition,
            Rectangle layoutRect, bool isSelected, bool skipObjects)
        {
            int yCurrentBaseline = scriptLine->Y + scriptLine->Ascent;
            int xCurrentPosition = scriptLine->X;
            for (int i = 0; i < scriptRunCount; i++)
            {
                int logicalScriptRunIndex = visualToLogicalMap[currentLayoutRightToLeft ? scriptRunCount - i - 1 : i];
                ScriptRun* scriptRun = scriptParagraph->ScriptRuns + logicalScriptRunIndex + scriptRunIndex;

                int measuredWidth;
                switch (scriptRun->RunKind)
                {
                    case RunKind.Text:
                    {
                        Style style = document.LookupStyle(scriptRun->StyleIndex);
                        ScriptMetrics scriptMetrics = deviceContext.SelectFont(style.Font);

                        int glyphIndexInParagraph, glyphCount;
                        measuredWidth = MeasureTextScriptRun(scriptParagraph, scriptRun,
                            logicalScriptRunIndex == 0 ? scriptLine->TruncatedLeadingCharsCount : 0,
                            logicalScriptRunIndex == scriptRunCount - 1 ? scriptLine->TruncatedTrailingCharsCount : 0,
                            out glyphIndexInParagraph, out glyphCount);

                        if (glyphCount > 0 && xCurrentPosition + measuredWidth > xStartPosition)
                        {
                            int x = currentLayoutRightToLeft
                                ? layoutRect.Right - xCurrentPosition - measuredWidth
                                : layoutRect.Left + xCurrentPosition;
                            int y = layoutRect.Top + yCurrentBaseline - scriptRun->Ascent;

                            deviceContext.SetTextColor(isSelected ? paintOptions.SelectedTextColor : style.Color);
                            ScriptTextOut(deviceContext.HDC, ref scriptMetrics.ScriptCache, x, y,
                                ExtTextOutOptions.NONE, null, &scriptRun->ScriptAnalysis,
                                scriptParagraph->Glyphs + glyphIndexInParagraph,
                                glyphCount,
                                scriptParagraph->GlyphAdvanceWidths + glyphIndexInParagraph,
                                null,
                                scriptParagraph->GlyphOffsets + glyphIndexInParagraph);
                        }
                        break;
                    }

                    case RunKind.Object:
                    {
                        measuredWidth = MeasureObjectScriptRun(scriptRun);

                        if (!skipObjects && xCurrentPosition + measuredWidth > xStartPosition)
                        {
                            int embeddedObjectCharIndex = scriptRun->CharIndexInParagraph + scriptParagraph->CharIndex;
                            EmbeddedObjectHost embeddedObjectHost;
                            if (embeddedObjectHosts.TryGetValue(embeddedObjectCharIndex, out embeddedObjectHost))
                            {
                                if (embeddedObjectHost.RequiresPaint)
                                {
                                    using (Graphics g = Graphics.FromHdc(deviceContext.HDC))
                                    {
                                        Rectangle bounds = GetDrawingBoundsOfEmbeddedObject(embeddedObjectHost, layoutRect.Location);
                                        embeddedObjectHost.Paint(g, paintOptions, bounds, currentLayoutRightToLeft);
                                    }
                                }
                            }
                        }
                        break;
                    }

                    case RunKind.Tab:
                    {
                        measuredWidth = MeasureTabScriptRun(scriptRun,
                            GetParagraphStyleAssumingItHasAtLeastOneRun(scriptParagraph),
                            xCurrentPosition, false);
                        break;
                    }

                    default:
                        throw new NotSupportedException();
                }

                xCurrentPosition += measuredWidth;

                if (xCurrentPosition >= xEndPosition)
                    break; // can't fit any more runs within the clip rectangle
            }
        }
Exemplo n.º 3
0
        private void FinishScriptLineLayout(ScriptLine* scriptLine, ScriptParagraph* scriptParagraph,
            bool mustLayoutObjects)
        {
            int ascent = MinimumScriptLineHeight;
            int descent = 0;
            ScriptRun* startScriptRun = scriptParagraph->ScriptRuns + scriptLine->ScriptRunIndex;
            ScriptRun* endScriptRun = startScriptRun + scriptLine->ScriptRunCount;
            for (ScriptRun* scriptRun = startScriptRun; scriptRun != endScriptRun; scriptRun++)
            {
                int scriptRunDescentAndMargin = scriptRun->Descent + scriptRun->BottomMargin;
                int scriptRunAscentAndMargin = scriptRun->Ascent + scriptRun->TopMargin;

                if (scriptRunAscentAndMargin > ascent)
                    ascent = scriptRunAscentAndMargin;
                if (scriptRunDescentAndMargin > descent)
                    descent = scriptRunDescentAndMargin;
            }

            int height = ascent + descent;
            scriptLine->Height = height;
            scriptLine->Descent = descent;

            if (mustLayoutObjects)
            {
                int xCurrentPosition = scriptLine->X;
                int scriptRunIndex = scriptLine->ScriptRunIndex;
                int scriptRunCount = scriptLine->ScriptRunCount;
                int* visualToLogicalMap = GetTempVisualToLogicalMap(
                    scriptParagraph->ScriptRuns + scriptRunIndex,
                    scriptRunCount);

                for (int i = 0; i < scriptRunCount; i++)
                {
                    int logicalScriptRunIndex =
                        visualToLogicalMap[currentLayoutRightToLeft ? scriptRunCount - i - 1 : i];
                    ScriptRun* scriptRun = scriptParagraph->ScriptRuns + logicalScriptRunIndex + scriptRunIndex;

                    int measuredWidth;
                    switch (scriptRun->RunKind)
                    {
                        case RunKind.Text:
                        {
                            int glyphIndexInParagraph, glyphCount;
                            int truncatedLeadingCharsCount = logicalScriptRunIndex == 0
                                ? scriptLine->TruncatedLeadingCharsCount
                                : 0;
                            int truncatedTrailingCharsCount = logicalScriptRunIndex == scriptRunCount - 1
                                ? scriptLine->TruncatedTrailingCharsCount
                                : 0;
                            measuredWidth = MeasureTextScriptRun(scriptParagraph, scriptRun,
                                truncatedLeadingCharsCount, truncatedTrailingCharsCount,
                                out glyphIndexInParagraph, out glyphCount);
                            break;
                        }

                        case RunKind.Object:
                        {
                            measuredWidth = scriptRun->ABC.TotalWidth;

                            EmbeddedObjectHost embeddedObjectHost;
                            int charIndex = scriptRun->CharIndexInParagraph + scriptParagraph->CharIndex;
                            if (embeddedObjectHosts.TryGetValue(charIndex, out embeddedObjectHost))
                            {
                                embeddedObjectHost.LayoutBounds = new Rectangle(
                                    xCurrentPosition + scriptRun->ABC.abcA,
                                    scriptLine->Y + scriptLine->Ascent - scriptRun->Ascent,
                                    scriptRun->ABC.abcB,
                                    scriptRun->Height);

                                pendingEmbeddedObjectHostsToShow.Enqueue(embeddedObjectHost);
                            }
                            break;
                        }

                        case RunKind.Tab:
                        {
                            measuredWidth = scriptRun->ABC.abcB;
                            break;
                        }

                        default:
                            throw new NotSupportedException();
                    }

                    xCurrentPosition += measuredWidth;
                }
            }
        }