Example #1
0
        static void Main(string[] args)
        {
            // The unsafe code block permits the use of pointer types and pointer operations
            unsafe
            {
                var array = new int[] { 5, 6, 7 };

                // The fixed statement pins an object to an address in the heap.  Otherwise, it may get moved around.
                fixed(int *ap = array)
                {
                    // Loop through an array using a pointer to the array index addresses
                    for (var i = 0; i < array.Length; i++)
                    {
                        Assert(ap[i] == i + 5);
                    }
                }
            }

            // Demonstrate working with structs & pointers & the pointer-to-member operator
            unsafe
            {
                var me = new Run {
                    Miles = 4.0, Minutes = 29, Seconds = 0
                };
                Run *p = &me;
                Assert(p->Minutes + p->Seconds == 29);
            }
        }
Example #2
0
        private Run *GetRunAtCharacterIndex(int index, out int runIndex)
        {
            int        paragraphIndex;
            Paragraph *paragraph = GetParagraphAtCharacterIndex(index, out paragraphIndex);

            if (paragraph != null)
            {
                int remainingOffset = index - paragraph->CharIndex;

                Run *startRun = GetRunZero() + paragraph->RunIndex;
                Run *endRun   = startRun + paragraph->RunCount;
                for (Run *run = startRun; run != endRun; run++)
                {
                    remainingOffset -= run->CharCount;

                    if (remainingOffset < 0)
                    {
                        runIndex = (int)(run - startRun);
                        return(run);
                    }
                }
            }

            runIndex = -1;
            return(null);
        }
Example #3
0
        private Run *ValidateCharacterIndexAndGetRun(int index)
        {
            ValidateCharacterIndex(index);

            int  runIndex;
            Run *run = GetRunAtCharacterIndex(index, out runIndex);

            Debug.Assert(run != null, "We should have found a run at the character index since the index was within the bounds of the document.");
            return(run);
        }
Example #4
0
        public void Initialize(Run *run, SCRIPT_ANALYSIS *scriptAnalysis, int charIndexInParagraph, int charCount)
        {
            this.run = *run;
            if (this.run.RunKind == RunKind.Text)
            {
                this.run.CharCount = charCount;
            }

            CharIndexInParagraph = charIndexInParagraph;
            ScriptAnalysis       = *scriptAnalysis;
        }
Example #5
0
        private void InternalStartTextRun(int styleIndex)
        {
            int runIndex = runBuffer.Count;

            runBuffer.GrowBy(1);

            currentRun = GetRunZero() + runIndex;
            currentRun->InitializeTextRun(styleIndex);

            currentParagraph->RunCount += 1;
        }
Example #6
0
        private void InternalStartParagraph()
        {
            Debug.Assert(currentRun != null || currentParagraph == null,
                         "At least one run should be added to the current paragraph before a new one is started.");

            int paragraphIndex = paragraphBuffer.Count;

            paragraphBuffer.GrowBy(1);

            currentParagraph = GetParagraphZero() + paragraphIndex;
            currentParagraph->Initialize(charBuffer.Count, 0, runBuffer.Count, 0);

            currentRun = null;
        }
Example #7
0
        private void InternalClear()
        {
            currentParagraph = null;
            currentRun       = null;

            styleTable.Clear();
            objectTable.Clear();
            annotationTables.Clear();
            styleIndexStack.Clear();

            charBuffer.Clear();
            paragraphBuffer.Clear();
            runBuffer.Clear();

            InternalBeginStyle(Style.Default);
            InternalStartParagraph();
        }
Example #8
0
        private void InternalAppendTabRun(int styleIndex)
        {
            int runIndex = runBuffer.Count;

            runBuffer.GrowBy(1);

            int charIndex = charBuffer.Count;

            charBuffer.GrowBy(1);

            currentRun = GetRunZero() + runIndex;
            currentRun->InitializeTabRun(styleIndex);

            char *chars = GetCharZero() + charIndex;

            *chars = '\t';

            currentParagraph->RunCount  += 1;
            currentParagraph->CharCount += 1;
        }
Example #9
0
        private void InternalAppendObject(int styleIndex, EmbeddedObject obj)
        {
            int objectIndex = objectTable.AssignIndex(obj);

            int runIndex = runBuffer.Count;

            runBuffer.GrowBy(1);

            int charIndex = charBuffer.Count;

            charBuffer.GrowBy(1);

            currentRun = GetRunZero() + runIndex;
            currentRun->InitializeObjectRun(styleIndex, objectIndex);

            char *chars = GetCharZero() + charIndex;

            *chars = ObjectRunPlaceholderChar;

            currentParagraph->RunCount  += 1;
            currentParagraph->CharCount += 1;
        }
Example #10
0
        public unsafe void AppendText_WhenRunIsExtremelyLong_SplitsRun(int length)
        {
            var document = new SplashDocument();
            var content  = new string(' ', length);

            document.AppendText(content);

            Assert.Multiple(() =>
            {
                // Check char content.
                Assert.AreEqual(content, document.ToString());

                // Check paragraph table.
                Assert.AreEqual(1, document.ParagraphCount);
                Paragraph *paragraphs = document.GetParagraphZero();

                int expectedRuns = (length + SplashDocument.MaxCharsPerRun - 1) / SplashDocument.MaxCharsPerRun;
                Assert.AreEqual(0, paragraphs[0].CharIndex);
                Assert.AreEqual(length, paragraphs[0].CharCount);
                Assert.AreEqual(0, paragraphs[0].RunIndex);
                Assert.AreEqual(expectedRuns, paragraphs[0].RunCount);

                // Check run table.
                Assert.AreEqual(expectedRuns, document.RunCount);
                Run *runs = document.GetRunZero();

                for (int i = 0; i < expectedRuns; i++)
                {
                    Assert.AreEqual(RunKind.Text, runs[i].RunKind);
                    Assert.AreEqual(Math.Min(length, SplashDocument.MaxCharsPerRun), runs[i].CharCount);
                    Assert.AreEqual(0, runs[i].StyleIndex);

                    length -= SplashDocument.MaxCharsPerRun;
                }
            });
        }
Example #11
0
        /// <summary>
        /// Gets the embedded object at the specified character index, or null if none.
        /// </summary>
        /// <param name="index">The character index.</param>
        /// <returns>The embedded object, or null if none.</returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="index"/> is
        /// outside of the bounds of the document.</exception>
        public EmbeddedObject GetObjectAtIndex(int index)
        {
            Run *run = ValidateCharacterIndexAndGetRun(index);

            return(run->RunKind == RunKind.Object ? LookupObject(run->ObjectIndex) : null);
        }
Example #12
0
        /// <summary>
        /// Gets the style of the text at the specified character index.
        /// </summary>
        /// <param name="index">The character index.</param>
        /// <returns>The style.</returns>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="index"/> is
        /// outside of the bounds of the document.</exception>
        public Style GetStyleAtIndex(int index)
        {
            Run *run = ValidateCharacterIndexAndGetRun(index);

            return(LookupStyle(run->StyleIndex));
        }
Example #13
0
        public unsafe void AppendStuff()
        {
            var style1 = new StyleBuilder()
            {
                Color = Color.Red
            }.ToStyle();
            var style2 = new StyleBuilder()
            {
                LeftMargin = 10, RightMargin = 10
            }.ToStyle();
            var style3 = new StyleBuilder()
            {
                Font = SystemFonts.SmallCaptionFont, Color = Color.Blue
            }.ToStyle();
            var embeddedObject = new EmbeddedImage(new Bitmap(16, 16));

            var document = new SplashDocument();
            var changedParagraphIndices = new List <int>();

            document.ParagraphChanged += (sender, e) => changedParagraphIndices.Add(e.ParagraphIndex);

            using (document.BeginStyle(style1))
                document.AppendText("Some text, lalala.\nMore text.");

            using (document.BeginStyle(style2))
            {
                document.AppendText("Tab\t.\n");

                document.AppendText("\0\r"); // these control characters will be discarded

                using (document.BeginStyle(style3))
                {
                    document.AppendLine();
                    document.AppendText(""); // to verify that no change event is raised for empty text
                }

                document.AppendText("(");
                document.AppendObject(embeddedObject);
                document.AppendText(")");
            }

            Assert.Multiple(() =>
            {
                // Check char content.
                Assert.AreEqual("Some text, lalala.\nMore text.Tab\t.\n\n( )", document.ToString());

                // Check style table.
                Assert.AreEqual(4, document.StyleCount);
                Assert.AreEqual(Style.Default, document.LookupStyle(0));
                Assert.AreEqual(style1, document.LookupStyle(1));
                Assert.AreEqual(style2, document.LookupStyle(2));
                Assert.AreEqual(style3, document.LookupStyle(3));

                // Check object table.
                Assert.AreEqual(1, document.ObjectCount);
                Assert.AreEqual(embeddedObject, document.LookupObject(0));

                // Check paragraph table.
                Assert.AreEqual(4, document.ParagraphCount);
                Paragraph *paragraphs = document.GetParagraphZero();

                Assert.AreEqual(0, paragraphs[0].CharIndex); // "Some text, lalala.\n"
                Assert.AreEqual(19, paragraphs[0].CharCount);
                Assert.AreEqual(0, paragraphs[0].RunIndex);
                Assert.AreEqual(1, paragraphs[0].RunCount);

                Assert.AreEqual(19, paragraphs[1].CharIndex); // "More text.Tab\t.\n"
                Assert.AreEqual(16, paragraphs[1].CharCount);
                Assert.AreEqual(1, paragraphs[1].RunIndex);
                Assert.AreEqual(4, paragraphs[1].RunCount);

                Assert.AreEqual(35, paragraphs[2].CharIndex); // "\n"
                Assert.AreEqual(1, paragraphs[2].CharCount);
                Assert.AreEqual(5, paragraphs[2].RunIndex);
                Assert.AreEqual(1, paragraphs[2].RunCount);

                Assert.AreEqual(36, paragraphs[3].CharIndex); // "( )"
                Assert.AreEqual(3, paragraphs[3].CharCount);
                Assert.AreEqual(6, paragraphs[3].RunIndex);
                Assert.AreEqual(3, paragraphs[3].RunCount);

                // Check run table.
                Assert.AreEqual(9, document.RunCount);
                Run *runs = document.GetRunZero();

                Assert.AreEqual(RunKind.Text, runs[0].RunKind); // "Some text, lalala.\n"
                Assert.AreEqual(19, runs[0].CharCount);
                Assert.AreEqual(1, runs[0].StyleIndex);

                Assert.AreEqual(RunKind.Text, runs[1].RunKind); // "More text."
                Assert.AreEqual(10, runs[1].CharCount);
                Assert.AreEqual(1, runs[1].StyleIndex);

                Assert.AreEqual(RunKind.Text, runs[2].RunKind); // "Tab"
                Assert.AreEqual(3, runs[2].CharCount);
                Assert.AreEqual(2, runs[2].StyleIndex);

                Assert.AreEqual(RunKind.Tab, runs[3].RunKind); // "\t"
                Assert.AreEqual(1, runs[3].CharCount);
                Assert.AreEqual(2, runs[3].StyleIndex);

                Assert.AreEqual(RunKind.Text, runs[4].RunKind); // ".\n"
                Assert.AreEqual(2, runs[4].CharCount);
                Assert.AreEqual(2, runs[4].StyleIndex);

                Assert.AreEqual(RunKind.Text, runs[5].RunKind); // "\n"
                Assert.AreEqual(1, runs[5].CharCount);
                Assert.AreEqual(3, runs[5].StyleIndex);

                Assert.AreEqual(RunKind.Text, runs[6].RunKind); // "("
                Assert.AreEqual(1, runs[6].CharCount);
                Assert.AreEqual(2, runs[6].StyleIndex);

                Assert.AreEqual(RunKind.Object, runs[7].RunKind); // "("
                Assert.AreEqual(1, runs[7].CharCount);
                Assert.AreEqual(2, runs[7].StyleIndex);
                Assert.AreEqual(0, runs[7].ObjectIndex);

                Assert.AreEqual(RunKind.Text, runs[8].RunKind); // ")"
                Assert.AreEqual(1, runs[8].CharCount);
                Assert.AreEqual(2, runs[8].StyleIndex);

                // Check that paragraph changed notifications were raised as needed.
                Assert.AreElementsEqual(new[] { 0, 1, 2, 2, 3, 3, 3 }, changedParagraphIndices);
            });
        }