internal static TextLineRun CreateRunForText(StringRange stringRange, TextRun textRun, double widthLeft, bool emergencyWrap, bool breakOnTabs) { var run = new TextLineRun { StringRange = stringRange, TextRun = textRun, Length = textRun.Length }; var formattedText = new FormattedText { Text = stringRange.ToString(), Typeface = new Typeface(run.Typeface, run.FontSize) }; run._formattedText = formattedText; var size = formattedText.Measure(); run._formattedTextSize = size; run.Width = size.Width; run.SetGlyphWidths(); return(run); }
public void TextEmbeddedObject_Should_Have_Valid_Baseline() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); int runWidth = 50; TextLine textLine = Mock.Of <TextLine>( t => t.WidthIncludingTrailingWhitespace == runWidth); SpecialCharacterTextRun f = new SpecialCharacterTextRun( new FormattedTextElement("BEL", 1) { TextLine = textLine }, CreateDefaultTextProperties()); Mock <TextSource> ts = new Mock <TextSource>(); ts.Setup(s => s.GetTextRun(It.IsAny <int>())).Returns(f); TextLineRun run = TextLineRun.Create(ts.Object, 0, 0, 1, CreateDefaultParagraphProperties()); Assert.AreEqual(MockGlyphTypeface.GlyphAscent, run.Baseline); }
public void Tab_Line_Run_Should_Have_Same_Width_As_Indentation_Size() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s1 = new SimpleTextSource( "\ta", CreateDefaultTextProperties()); SimpleTextSource s2 = new SimpleTextSource( " a", CreateDefaultTextProperties()); var textParagraphProperties = new TextParagraphProperties() { DefaultIncrementalTab = 4 * MockGlyphTypeface.GlyphAdvance, Indent = 4 }; TextLineRun run1 = TextLineRun.Create(s1, 0, 0, 32000, textParagraphProperties); TextLineRun run2 = TextLineRun.Create(s2, 0, 0, 32000, textParagraphProperties); Assert.AreEqual( run1.GetDistanceFromCharacter(1), run2.GetDistanceFromCharacter(4)); }
public void Spaces_Plus_Tab_Line_Run_Should_Have_Correct_Glyph_Widths() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( " \t ", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, 32000, paragraphProperties); double[] expectedLengths = new double[] { 0, MockGlyphTypeface.GlyphAdvance * 1, MockGlyphTypeface.GlyphAdvance * 1 + paragraphProperties.DefaultIncrementalTab, MockGlyphTypeface.GlyphAdvance * 2 + paragraphProperties.DefaultIncrementalTab }; for (int i = 0; i < 4; i++) { Assert.AreEqual(expectedLengths[i], run.GetDistanceFromCharacter(i)); } }
private static TextLineRun CreateTextLineRun(StringRange stringRange, TextRun textRun, int length, TextParagraphProperties paragraphProperties) { var run = new TextLineRun { StringRange = stringRange, TextRun = textRun, Length = length }; var tf = run.Typeface; var formattedText = new FormattedText { Text = stringRange.ToString(run.Length), Typeface = new Typeface(tf.FontFamily, tf.Style, tf.Weight), FontSize = run.FontSize }; run._formattedText = formattedText; var size = formattedText.Bounds.Size; run._formattedTextSize = size; run.Width = size.Width; run._glyphWidths = new GlyphWidths( run.StringRange, run.Typeface.GlyphTypeface, run.FontSize, paragraphProperties.DefaultIncrementalTab); return(run); }
internal static TextLineRun CreateRunForText(StringRange stringRange, TextRun textRun, double widthLeft, bool emergencyWrap, bool breakOnTabs) { var run = new TextLineRun { StringRange = stringRange, TextRun = textRun, Length = textRun.Length }; var tf = run.Typeface; var formattedText = new FormattedText { Text = stringRange.ToString(), Typeface = new Typeface(tf.FontFamily, tf.Style, tf.Weight), FontSize = run.FontSize }; run._formattedText = formattedText; var size = formattedText.Bounds.Size; run._formattedTextSize = size; run.Width = size.Width; run._glyphWidths = new GlyphWidths( run.StringRange, run.Typeface.GlyphTypeface, run.FontSize); return(run); }
internal static TextLineImpl Create(TextParagraphProperties paragraphProperties, int firstIndex, double availableWidth, TextSource textSource) { var index = firstIndex; var visibleLength = 0; var widthLeft = paragraphProperties.TextWrapping == TextWrapping.Wrap && availableWidth > 0 ? availableWidth : double.MaxValue; widthLeft -= paragraphProperties.Margin.Left + paragraphProperties.Margin.Right; if (widthLeft < paragraphProperties.DefaultTextRunProperties.FontSize) { widthLeft = paragraphProperties.DefaultTextRunProperties.FontSize; } TextLineRun prevRun = null; var run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); if (!run.IsEnd && run.Width <= widthLeft) { index += run.Length; widthLeft -= run.Width; prevRun = run; run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); } var trailing = new TrailingInfo(); var runs = new List <TextLineRun>(2); if (prevRun != null) { visibleLength += AddRunReturnVisibleLength(runs, prevRun); } if (visibleLength >= MaxCharactersPerLine) { throw new NotSupportedException("Too many characters per line"); } while (true) { visibleLength += AddRunReturnVisibleLength(runs, run); index += run.Length; widthLeft -= run.Width; if (run.IsEnd || widthLeft <= 0) { if (!run.IsEnd && widthLeft <= 0) { //The text needs to be wrapped CalculateLineBreak(runs); } trailing.SpaceWidth = 0; UpdateTrailingInfo(runs, trailing); return(new TextLineImpl(paragraphProperties, firstIndex, runs, trailing)); } run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); } }
internal static TextLineRun CreateRunForText(StringRange stringRange, TextRun textRun, double widthLeft, bool emergencyWrap, bool breakOnTabs) { var tf = textRun.Properties.Typeface; var formattedText = new FormattedText { Text = stringRange.ToString(), Typeface = new Typeface(tf.FontFamily, tf.Style, tf.Weight), FontSize = textRun.Properties.FontSize }; double x = 0; int offset = 0; int lastWhitespaceIndex = -1; //Measure the width of the text that would fit in the space left while (x <= widthLeft && offset < textRun.Length) { x += formattedText.HitTestTextPosition(offset).Width; if (x <= widthLeft) { if (char.IsWhiteSpace(stringRange[offset])) { lastWhitespaceIndex = offset; } offset++; } } //Wrap at the last letter if there was no whitespace in the run if (lastWhitespaceIndex == -1 && x > widthLeft) { lastWhitespaceIndex = offset; } var run = new TextLineRun { StringRange = stringRange, TextRun = textRun, Length = textRun.Length, LastWhitespaceIndex = lastWhitespaceIndex }; run._formattedText = formattedText; var size = formattedText.Bounds.Size; run._formattedTextSize = size; run.Width = size.Width; run.SetGlyphWidths(); return(run); }
private static TextLineRun PerformTextWrapping(TextLineRun run, double widthLeft, TextParagraphProperties paragraphProperties) { (int firstIndex, int trailingLength)characterHit = run.GetCharacterFromDistance(widthLeft); int lenForTextWrapping = FindPositionForTextWrapping(run.StringRange, characterHit.firstIndex); return(CreateTextLineRun( run.StringRange.WithLength(lenForTextWrapping), run.TextRun, lenForTextWrapping, paragraphProperties)); }
private static int AddRunReturnVisibleLength(List <TextLineRun> runs, TextLineRun run) { if (run.Length > 0) { runs.Add(run); if (!run.IsEnd) { return(run.Length); } } return(0); }
private static TextLineRun CreateRunForTab(TextRun textRun, TextParagraphProperties paragraphProperties) { var tabRun = new TextCharacters(TabString, textRun.Properties); var stringRange = tabRun.StringRange; var run = new TextLineRun(1, tabRun) { IsTab = true, StringRange = stringRange, Width = paragraphProperties.DefaultIncrementalTab }; run._glyphWidths = new double[] { run.Width }; return(run); }
public void Text_Line_Run_Should_Update_StringRange_When_Word_Wrap() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl())); SimpleTextSource s = new SimpleTextSource( "0123456789 0123456789", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, MockGlyphTypeface.GlyphAdvance * 13, paragraphProperties); Assert.AreEqual("0123456789 ", run.StringRange.ToString()); }
private static TextLineRun CreateRunForTab(TextRun textRun) { var spaceRun = new TextCharacters(" ", textRun.Properties); var stringRange = spaceRun.StringRange; var run = new TextLineRun(1, spaceRun) { IsTab = true, StringRange = stringRange, // TODO: get from para props Width = 40 }; run.SetGlyphWidths(); return(run); }
public void Text_Line_Run_Should_Perform_Character_Line_Wrapping_When_Space_Not_Found() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( "0123456789", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, MockGlyphTypeface.GlyphAdvance * 3, paragraphProperties); Assert.AreEqual(3, run.Length); }
public void Simple_Run_Should_Have_Valid_Baseline() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( "a\ta", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, 1, paragraphProperties); Assert.AreEqual(MockGlyphTypeface.GlyphAscent, run.Baseline); }
public void Tab_Line_Run_Should_Have_Fixed_Glyph_Width() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( "\t", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, 1, paragraphProperties); Assert.AreEqual(paragraphProperties.DefaultIncrementalTab, run.GetDistanceFromCharacter(1)); }
internal static TextLineImpl Create(TextParagraphProperties paragraphProperties, int firstIndex, int paragraphLength, TextSource textSource) { var index = firstIndex; var visibleLength = 0; var widthLeft = paragraphLength > 0 ? paragraphLength : int.MaxValue; TextLineRun prevRun = null; var run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); if (!run.IsEnd && run.Width <= widthLeft) { index += run.Length; widthLeft -= run.Width; prevRun = run; run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); } var trailing = new TrailingInfo(); var runs = new List <TextLineRun>(2); if (prevRun != null) { visibleLength += AddRunReturnVisibleLength(runs, prevRun); } if (visibleLength >= MaxCharactersPerLine) { throw new NotSupportedException("Too many characters per line"); } while (run.IsEnd || run.Width <= widthLeft) { visibleLength += AddRunReturnVisibleLength(runs, run); index += run.Length; widthLeft -= run.Width; if (run.IsEnd) { trailing.SpaceWidth = 0; UpdateTrailingInfo(runs, trailing); return(new TextLineImpl(paragraphProperties, firstIndex, runs, trailing)); } run = TextLineRun.Create(textSource, index, firstIndex, widthLeft); } return(null); }
public void Text_Line_Run_Should_Not_Wrap_Line_When_There_Is_Enough_Available_Space() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( "0123456789", CreateDefaultTextProperties()); var paragraphProperties = CreateDefaultParagraphProperties(); TextLineRun run = TextLineRun.Create(s, 0, 0, 32000, paragraphProperties); Assert.AreEqual(10, run.Length); }
private TextLineImpl(TextParagraphProperties paragraphProperties, int firstIndex, List <TextLineRun> runs, TrailingInfo trailing) { var top = 0.0; var height = 0.0; var index = 0; _runs = new TextLineRun[runs.Count]; foreach (var run in runs) { _runs[index++] = run; if (run.Length <= 0) { continue; } if (run.IsEnd) { trailing.Count += run.Length; } else { top = Math.Max(top, run.Height - run.Baseline); height = Math.Max(height, run.Height); Baseline = Math.Max(Baseline, run.Baseline); } Length += run.Length; WidthIncludingTrailingWhitespace += run.Width; } Height = Math.Max(height, Baseline + top); if (Height <= 0) { Height = TextLineRun.GetDefaultLineHeight(paragraphProperties.DefaultTextRunProperties.FontMetrics); Baseline = TextLineRun.GetDefaultBaseline(paragraphProperties.DefaultTextRunProperties.FontMetrics); } FirstIndex = firstIndex; TrailingWhitespaceLength = trailing.Count; Width = WidthIncludingTrailingWhitespace - trailing.SpaceWidth; }
internal static TextLineRun CreateRunForText( StringRange stringRange, TextRun textRun, double widthLeft, TextParagraphProperties paragraphProperties) { TextLineRun run = CreateTextLineRun(stringRange, textRun, textRun.Length, paragraphProperties); if (run.Width <= widthLeft) { return(run); } TextLineRun wrapped = PerformTextWrapping(run, widthLeft, paragraphProperties); wrapped.Width = run.Width; return(wrapped); }
public void Text_Line_Run_Should_Have_Valid_Glyph_Widths() { using var app = UnitTestApplication.Start(new TestServices().With( renderInterface: new MockPlatformRenderInterface(), fontManagerImpl: new MockFontManagerImpl(), formattedTextImpl: Mock.Of <IFormattedTextImpl>())); SimpleTextSource s = new SimpleTextSource( "0123", CreateDefaultTextProperties()); TextLineRun run = TextLineRun.Create(s, 0, 0, 32000, CreateDefaultParagraphProperties()); Assert.AreEqual(MockGlyphTypeface.GlyphAdvance * 0, run.GetDistanceFromCharacter(0)); Assert.AreEqual(MockGlyphTypeface.GlyphAdvance * 1, run.GetDistanceFromCharacter(1)); Assert.AreEqual(MockGlyphTypeface.GlyphAdvance * 2, run.GetDistanceFromCharacter(2)); Assert.AreEqual(MockGlyphTypeface.GlyphAdvance * 3, run.GetDistanceFromCharacter(3)); }
internal static TextLineImpl Create(TextParagraphProperties paragraphProperties, int firstIndex, int paragraphLength, TextSource textSource) { var index = firstIndex; var visibleLength = 0; var widthLeft = paragraphProperties.TextWrapping == TextWrapping.Wrap && paragraphLength > 0 ? paragraphLength : double.MaxValue; TextLineRun prevRun = null; var run = TextLineRun.Create(textSource, index, firstIndex, widthLeft, paragraphProperties); if (!run.IsEnd && run.Width <= widthLeft) { index += run.Length; widthLeft -= run.Width; prevRun = run; run = TextLineRun.Create(textSource, index, firstIndex, widthLeft, paragraphProperties); } var trailing = new TrailingInfo(); var runs = new List <TextLineRun>(2); if (prevRun != null) { visibleLength += AddRunReturnVisibleLength(runs, prevRun); } while (true) { visibleLength += AddRunReturnVisibleLength(runs, run); index += run.Length; widthLeft -= run.Width; if (run.IsEnd || widthLeft <= 0) { trailing.SpaceWidth = 0; UpdateTrailingInfo(runs, trailing); return(new TextLineImpl(paragraphProperties, firstIndex, runs, trailing)); } run = TextLineRun.Create(textSource, index, firstIndex, widthLeft, paragraphProperties); if (run.Width > widthLeft) { return(new TextLineImpl(paragraphProperties, firstIndex, runs, trailing)); } } }