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); } }
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); }
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); }
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; }
private void InternalStartTextRun(int styleIndex) { int runIndex = runBuffer.Count; runBuffer.GrowBy(1); currentRun = GetRunZero() + runIndex; currentRun->InitializeTextRun(styleIndex); currentParagraph->RunCount += 1; }
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; }
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(); }
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; }
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; }
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; } }); }
/// <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); }
/// <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)); }
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); }); }