Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,66 @@ public async Task When_FontFamily_Changed(string font)
Assert.AreNotEqual(originalSize, SUT.DesiredSize);
}

[TestMethod]
[PlatformCondition(ConditionMode.Include, RuntimeTestPlatforms.Skia)]
public async Task When_TextBlock_With_Unpaired_Surrogate_Renders()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap, Uno.UI"))
{
Assert.Inconclusive();
}

var text = "LTR \uD800 RTL שלום";
var sut = new TextBlock
{
Text = text,
TextWrapping = TextWrapping.Wrap
};
sut.TextHighlighters.Add(new TextHighlighter
{
Ranges =
{
new TextRange { StartIndex = 0, Length = text.Length }
}
});

var root = new Border
{
Width = 240,
Height = 120,
Child = sut
};

await UITestHelper.Load(root);
await UITestHelper.ScreenShot(root);
}

[TestMethod]
[PlatformCondition(ConditionMode.Include, RuntimeTestPlatforms.Skia)]
public async Task When_TextBlock_With_Unpaired_Surrogate_And_No_Highlighter_Renders()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap, Uno.UI"))
{
Assert.Inconclusive();
}

var sut = new TextBlock
{
Text = "LTR \uD800 RTL שלום",
TextWrapping = TextWrapping.Wrap
};

var root = new Border
{
Width = 240,
Height = 120,
Child = sut
};

await UITestHelper.Load(root);
await UITestHelper.ScreenShot(root);
}

[TestMethod]
#if !__ANDROID__
[Ignore("Android-only test for AndroidAssets backward compatibility")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Documents;
using Microsoft.UI.Xaml.Controls;
using System.Drawing;
using Microsoft.UI.Xaml.Media;
using Windows.Foundation;

namespace Uno.UI.Tests.Windows_UI_XAML_Controls.TextBlockTests
{
Expand Down Expand Up @@ -51,6 +51,55 @@ public void When_Changing_Foreground_Property()
}
#endif

[TestMethod]
public void When_Text_Has_Unpaired_Surrogate_Does_Not_Throw()
{
var tb = new TextBlock
{
Text = "A\uD800B\uDC00"
};

tb.Measure(new Size(300, 80));
}

[TestMethod]
public void When_Text_Has_Unpaired_Surrogate_With_Highlighter_Does_Not_Throw()
{
var tb = new TextBlock
{
Text = "A\uD800B\uDC00"
};

tb.TextHighlighters.Add(new TextHighlighter
{
Ranges =
{
new TextRange { StartIndex = 0, Length = tb.Text.Length }
}
});

tb.Measure(new Size(300, 80));
}

[TestMethod]
public void When_Highlighter_Range_Exceeds_Text_Does_Not_Throw()
{
var tb = new TextBlock
{
Text = "abc"
};

tb.TextHighlighters.Add(new TextHighlighter
{
Ranges =
{
new TextRange { StartIndex = 0, Length = 999 }
}
});

tb.Measure(new Size(300, 80));
}

[TestMethod]
public void When_LineBreak_SurroundingWhiteSpace()
{
Expand Down
34 changes: 21 additions & 13 deletions src/Uno.UI/UI/Xaml/Documents/UnicodeText.ICU.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,24 +176,32 @@ public static T GetMethod<T>()
public static unsafe DisposableStruct<IntPtr> CreateBiDiAndSetPara(string text, int start, int end, byte paraLevel, out IntPtr bidi, byte[]? embeddingLevels = null)
{
bidi = GetMethod<ubidi_open>()();
fixed (char* textPtr = &text.GetPinnableReference())
try
{
int setParaErrorCode;
if (embeddingLevels is not null)
fixed (char* textPtr = &text.GetPinnableReference())
{
fixed (byte* embeddingLevelsPtr = embeddingLevels)
int setParaErrorCode;
if (embeddingLevels is not null)
{
GetMethod<ubidi_setPara>()(bidi, (IntPtr)(textPtr + start), end - start, paraLevel, (IntPtr)embeddingLevelsPtr, out setParaErrorCode);
fixed (byte* embeddingLevelsPtr = embeddingLevels)
{
GetMethod<ubidi_setPara>()(bidi, (IntPtr)(textPtr + start), end - start, paraLevel, (IntPtr)embeddingLevelsPtr, out setParaErrorCode);
}
}
else
{
GetMethod<ubidi_setPara>()(bidi, (IntPtr)(textPtr + start), end - start, paraLevel, IntPtr.Zero, out setParaErrorCode);
}
if (setParaErrorCode > 0)
{
throw new InvalidOperationException($"{nameof(ubidi_setPara)} failed with error code {setParaErrorCode}");
}
}
else
{
GetMethod<ubidi_setPara>()(bidi, (IntPtr)(textPtr + start), end - start, paraLevel, IntPtr.Zero, out setParaErrorCode);
}
if (setParaErrorCode > 0)
{
throw new InvalidOperationException($"{nameof(ubidi_setPara)} failed with error code {setParaErrorCode}");
}
}
catch
{
GetMethod<ubidi_close>()(bidi);
throw;
}
return new DisposableStruct<IntPtr>(static bidi => GetMethod<ubidi_close>()(bidi), bidi);
}
Expand Down
Loading
Loading