Example #1
0
        /// <summary>
        /// Creates an empty SplashView.
        /// </summary>
        public SplashView()
        {
            document = new SplashDocument();

            layout = new SplashLayout(document, this);
            paintOptions = new PaintOptions();

            SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw
                | ControlStyles.Selectable | ControlStyles.UserMouse
                | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);

            base.BackColor = paintOptions.BackgroundColor;
            Padding = new Padding(5);

            AttachLayoutEvents();
            InitializeContextMenu();
        }
Example #2
0
        /// <summary>
        /// Creates an empty SplashView.
        /// </summary>
        public SplashView()
        {
            document = new SplashDocument();

            layout       = new SplashLayout(document, this);
            paintOptions = new PaintOptions();

            SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw
                     | ControlStyles.Selectable | ControlStyles.UserMouse
                     | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);

            base.BackColor = paintOptions.BackgroundColor;
            Padding        = new Padding(5);

            AttachLayoutEvents();
            InitializeContextMenu();
        }
Example #3
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
            }
        }
Example #4
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
            }
        }
Example #5
0
        private void PaintRegion(DeviceContext deviceContext, Rectangle layoutRect, Rectangle clipRect,
            IntPtr clipRegion, PaintOptions paintOptions, int selectedCharIndex, int selectedCharCount)
        {
            int yStartPosition = clipRect.Top - layoutRect.Top;
            int yEndPosition = clipRect.Bottom - layoutRect.Top;
            int firstScriptLineIndex;
            ScriptLine* scriptLine = GetScriptLineAtYPositionOrNullIfNone(yStartPosition, out firstScriptLineIndex);
            if (scriptLine == null)
                return;

            ScriptLine* endScriptLine = GetScriptLineZero() + scriptLineBuffer.Count;

            int xStartPosition, xEndPosition;
            if (currentLayoutRightToLeft)
            {
                xStartPosition = layoutRect.Right - clipRect.Right;
                xEndPosition = layoutRect.Right - clipRect.Left;
            }
            else
            {
                xStartPosition = clipRect.Left - layoutRect.Left;
                xEndPosition = clipRect.Right - layoutRect.Left;
            }

            // Note: Selection may extend beyond the range of the layout if improper index and count
            //       values were provided.  This is ok since we only care about the intersection of the
            //       selected range with actual range of characters on the lines.
            if (selectedCharCount < 0)
            {
                selectedCharIndex += selectedCharCount;
                selectedCharCount = -selectedCharCount;
            }

            deviceContext.SetBkMode(NativeConstants.TRANSPARENT);

            for (; scriptLine != endScriptLine && scriptLine->Y < yEndPosition; scriptLine++)
            {
                int scriptRunCount = scriptLine->ScriptRunCount;
                if (scriptRunCount != 0)
                {
                    ScriptParagraph* scriptParagraph = GetScriptParagraph(deviceContext, scriptLine->ParagraphIndex);
                    int scriptRunIndex = scriptLine->ScriptRunIndex;
                    int* visualToLogicalMap = GetTempVisualToLogicalMap(scriptParagraph->ScriptRuns + scriptRunIndex,
                        scriptRunCount);

                    if (selectedCharCount == 0
                        || selectedCharIndex >= scriptParagraph->CharIndex
                                + scriptParagraph->ScriptRuns[scriptRunIndex + scriptRunCount - 1].EndCharIndexInParagraph
                                - scriptLine->TruncatedTrailingCharsCount
                        || selectedCharIndex + selectedCharCount < scriptParagraph->CharIndex
                                + scriptParagraph->ScriptRuns[scriptRunIndex].CharIndexInParagraph
                                + scriptLine->TruncatedLeadingCharsCount)
                    {
                        deviceContext.SelectClipRegion(clipRegion);

                        // No selection.  Just paint the line as usual.
                        PaintLineForeground(deviceContext, paintOptions,
                            scriptLine, scriptParagraph, scriptRunIndex, scriptRunCount, visualToLogicalMap,
                            xStartPosition, xEndPosition,
                            layoutRect, false, false);
                    }
                    else
                    {
                        deviceContext.SelectClipRegion(clipRegion);

                        // Paint background.
                        PaintLineBackgroundAndExcludeSelectedTextFromClipRegion(deviceContext, paintOptions,
                            scriptLine, scriptParagraph, scriptRunIndex, scriptRunCount, visualToLogicalMap,
                            xStartPosition, xEndPosition,
                            layoutRect, selectedCharIndex, selectedCharCount);

                        // Paint all text and objects except in selected areas.
                        PaintLineForeground(deviceContext, paintOptions,
                            scriptLine, scriptParagraph, scriptRunIndex, scriptRunCount, visualToLogicalMap,
                            xStartPosition, xEndPosition,
                            layoutRect, false, false);

                        // Invert the clip region.
                        IntPtr lineRegion = DeviceContext.CreateRectRegion(clipRect);
                        deviceContext.XorClipRegion(lineRegion);
                        DeviceContext.DeleteObject(lineRegion);

                        // Paint all text in selected areas.
                        PaintLineForeground(deviceContext, paintOptions,
                            scriptLine, scriptParagraph, scriptRunIndex, scriptRunCount, visualToLogicalMap,
                            xStartPosition, xEndPosition,
                            layoutRect, true, true);
                    }
                }
            }
        }
Example #6
0
        /// <summary>
        /// Paints a region of text.
        /// </summary>
        /// <remarks>
        /// Be sure to update the layout before calling this method.
        /// </remarks>
        /// <param name="graphics">The graphics context.</param>
        /// <param name="layoutOrigin">The origin of the document layout area in the parent control.</param>
        /// <param name="clipRect">The clip rectangle of the region to paint in the device context.</param>
        /// <param name="paintOptions">The paint options.</param>
        /// <param name="selectedCharIndex">The index of the first selected character.  Ignored if
        /// the number of selected characters is 0.</param>
        /// <param name="selectedCharCount">The number of selected characters or 0 if none.
        /// May be negative if the selection is reversed.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="graphics"/> or
        /// <paramref name="paintOptions"/> is null.</exception>
        public void Paint(Graphics graphics, Point layoutOrigin, Rectangle clipRect, PaintOptions paintOptions,
            int selectedCharIndex, int selectedCharCount)
        {
            if (graphics == null)
                throw new ArgumentNullException("graphics");
            if (paintOptions == null)
                throw new ArgumentNullException("paintOptions");

            recursionGuard.Do(() =>
            {
                Rectangle layoutRect = new Rectangle(layoutOrigin.X, layoutOrigin.Y, currentLayoutWidth,
                    currentLayoutHeight);
                Rectangle clippedLayoutRect = layoutRect;
                clippedLayoutRect.Intersect(clipRect);

                GraphicsState state = graphics.Save();
                try
                {
                    using (DeviceContext deviceContext = DeviceContext.CreateFromGraphics(graphics, scriptMetricsCache))
                    {
                        IntPtr clipRegion = DeviceContext.CreateRectRegion(clippedLayoutRect);
                        try
                        {
                            PaintRegion(deviceContext, layoutRect, clippedLayoutRect, clipRegion,
                                paintOptions, selectedCharIndex, selectedCharCount);
                        }
                        finally
                        {
                            DeviceContext.DeleteObject(clipRegion);
                        }
                    }
                }
                finally
                {
                    graphics.Restore(state);
                }
            });
        }
 public void Paint(Graphics g, PaintOptions paintOptions, Rectangle bounds, bool rightToLeft)
 {
 }
Example #8
0
 public void Paint(Graphics g, PaintOptions paintOptions, Rectangle bounds, bool rightToLeft)
 {
     g.DrawImage(embeddedImage.Image, bounds);
 }
Example #9
0
 public void Paint(Graphics g, PaintOptions paintOptions, Rectangle bounds, bool rightToLeft)
 {
 }
Example #10
0
 public void Paint(Graphics g, PaintOptions paintOptions, Rectangle bounds, bool rightToLeft)
 {
     g.DrawImage(embeddedImage.Image, bounds);
 }