/// <inheritdoc/> public override void AppendTo(ShapedStringBuilder builder, UltravioletFontFace fontFace, Int32 start, Int32 length, Int32 sourceIndexOffset = 0) { Contract.Require(builder, nameof(builder)); Contract.Require(fontFace, nameof(fontFace)); Contract.EnsureRange(start >= 0 && start < rawstr.Length, nameof(start)); Contract.EnsureRange(length >= 0 && start + length <= rawstr.Length, nameof(length)); Contract.EnsureNotDisposed(this, Disposed); unsafe { Shape(fontFace, out var glyphInfo, out var glyphPosition, out var glyphCount); var end = start + length; for (var i = 0; i < glyphCount; i++) { var cluster = (Int32)glyphInfo->cluster; if (cluster >= start) { if (cluster >= end) { break; } CreateShapedChar(glyphInfo, glyphPosition, sourceIndexOffset + cluster, out var sc); builder.Append(sc); } glyphInfo++; glyphPosition++; } } }
public void ShapedStringBuilder_ExpandsWhenCapacityIsExceeded() { var sstrb = new ShapedStringBuilder(); GivenAnUltravioletApplicationWithNoWindow() .WithPlugin(new FreeTypeFontPlugin()) .WithContent(content => { var font = content.Load <UltravioletFont>("Fonts/FiraSans"); using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet)) { textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append("Hello, world!"); sstrb.Append(textShaper, font); textShaper.Clear(); textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append(" Goodbye, world!"); sstrb.Append(textShaper, font); } }) .RunForOneFrame(); TheResultingValue(sstrb.Capacity).ShouldBe(36); TheResultingValue(sstrb.Length).ShouldBe(29); }
public void FreeTypeFont_MeasuresShapedStringBuildersCorrectly() { var freetypeFont = default(FreeTypeFont); var size = Size2.Zero; GivenAnUltravioletApplication() .WithPlugin(new FreeTypeFontPlugin()) .WithContent(content => { freetypeFont = content.Load <FreeTypeFont>("Fonts/FiraSans"); using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet)) { textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append("Hello, world!"); var str = new ShapedStringBuilder(); str.Append(textShaper, freetypeFont.Regular); size = freetypeFont.Regular.MeasureShapedString(str); } }) .RunForOneFrame(); TheResultingValue(size.Width).ShouldBe(92); TheResultingValue(size.Height).ShouldBe(20); }
public void ShapedStringBuilder_CannotBeManuallyShrunkSmallerThanLength() { Assert.Throws <ArgumentOutOfRangeException>(() => { var sstrb = new ShapedStringBuilder(); sstrb.Append(new ShapedChar(), 8); sstrb.Capacity = 4; }); }
public void ShapedStringBuilder_CanCreateShapedString() { var sstrb = new ShapedStringBuilder(); var sstr = default(ShapedString); GivenAnUltravioletApplicationWithNoWindow() .WithPlugin(new FreeTypeFontPlugin()) .WithContent(content => { var font = content.Load <UltravioletFont>("Fonts/FiraSans"); using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet)) { textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append("Hello, world!"); sstrb.Append(textShaper, font); sstr = sstrb.ToShapedString(font, "en", TextScript.Latin, TextDirection.LeftToRight); } }) .RunForOneFrame(); var chars = new ShapedChar[sstr.Length]; sstr.CopyTo(0, chars, 0, sstr.Length); var glyphIndices = chars.Select(x => x.GlyphIndex).ToArray(); TheResultingCollection(glyphIndices) .ShouldBeExactly(111, 412, 514, 514, 555, 2122, 3, 696, 555, 609, 514, 393, 2125); var advances = chars.Select(x => x.Advance).ToArray(); TheResultingCollection(advances) .ShouldBeExactly(11, 9, 5, 5, 9, 4, 4, 11, 9, 6, 5, 10, 4); var offsets_x = chars.Select(x => x.OffsetX).ToArray(); TheResultingCollection(offsets_x) .ShouldContainTheSpecifiedNumberOfItems(13) .ShouldContainItemsSatisfyingTheCondition(x => x == 0); var offsets_y = chars.Select(x => x.OffsetY).ToArray(); TheResultingCollection(offsets_y) .ShouldContainTheSpecifiedNumberOfItems(13) .ShouldContainItemsSatisfyingTheCondition(x => x == 0); }
public void ShapedStringBuilder_IsAppendedFromShaper_WhenSpecifyingSubstring() { var sstrb = new ShapedStringBuilder(); GivenAnUltravioletApplicationWithNoWindow() .WithPlugin(new FreeTypeFontPlugin()) .WithContent(content => { var font = content.Load <UltravioletFont>("Fonts/FiraSans"); using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet)) { textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append("Hello, world!"); textShaper.AppendTo(sstrb, font.Regular, 7, 5); } }) .RunForOneFrame(); TheResultingValue(sstrb.Length).ShouldBe(5); }
public void ShapedStringBuilder_CanSpecifyInitialValueAndCapacityInConstructor() { var sstrb = default(ShapedStringBuilder); GivenAnUltravioletApplicationWithNoWindow() .WithPlugin(new FreeTypeFontPlugin()) .WithContent(content => { var font = content.Load <UltravioletFont>("Fonts/FiraSans"); using (var textShaper = new HarfBuzzTextShaper(content.Ultraviolet)) { textShaper.SetUnicodeProperties(TextDirection.LeftToRight, TextScript.Latin, "en"); textShaper.Append("Hello, world!"); sstrb = new ShapedStringBuilder(textShaper.CreateShapedString(font), 128); } }) .RunForOneFrame(); TheResultingValue(sstrb.Capacity).ShouldBe(128); TheResultingValue(sstrb.Length).ShouldBe(13); }
/// <inheritdoc/> public override Size2 MeasureShapedGlyph(ShapedStringBuilder text, Int32 ix, Boolean rtl = false) => throw new NotSupportedException();
/// <inheritdoc/> public override Size2 MeasureShapedString(ShapedStringBuilder text, Int32 start, Int32 count, Boolean rtl = false) => throw new NotSupportedException();
/// <inheritdoc/> public override void AppendTo(ShapedStringBuilder builder, UltravioletFontFace fontFace, Int32 sourceIndexOffset = 0) => AppendTo(builder, fontFace, 0, rawstr.Length, sourceIndexOffset);
/// <summary> /// Measures the specified glyph in a shaped string, taking kerning into account. /// </summary> /// <param name="text">The shaped text that contains the glyph to measure.</param> /// <param name="ix">The index of the glyph to measure.</param> /// <param name="rtl">A value indicating whether to reverse the order in which glyphs are accessed.</param> /// <returns>The size of the specified glyph.</returns> public abstract Size2 MeasureShapedGlyph(ShapedStringBuilder text, Int32 ix, Boolean rtl = false);
/// <summary> /// Measures the size of the specified substring of shaped text when rendered using this font. /// </summary> /// <param name="text">The shaped text to measure.</param> /// <param name="start">The index of the first character of the substring to measure.</param> /// <param name="count">The number of characters in the substring to measure.</param> /// <param name="rtl">A value indicating whether to reverse the order in which glyphs are accessed.</param> /// <returns>The size of the specified substring of shaped text when rendered using this font.</returns> public abstract Size2 MeasureShapedString(ShapedStringBuilder text, Int32 start, Int32 count, Boolean rtl = false);