diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 6f7dd4bcf8..6358a8c9d9 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -164,7 +164,6 @@ - diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 05ab49ed79..028df729a5 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -99,6 +99,7 @@ namespace Avalonia.Controls /// static TextBlock() { + ClipToBoundsProperty.OverrideDefaultValue(true); AffectsRender(ForegroundProperty); AffectsRender(FontWeightProperty); AffectsRender(FontSizeProperty); @@ -355,7 +356,8 @@ namespace Avalonia.Controls FontSize, FontStyle, TextAlignment, - FontWeight); + FontWeight, + TextWrapping); result.Constraint = constraint; return result; } diff --git a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj index 681f53f8fc..151ad0997e 100644 --- a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj +++ b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj @@ -1,4 +1,4 @@ - + @@ -68,6 +68,7 @@ + diff --git a/src/Avalonia.SceneGraph/Media/FormattedText.cs b/src/Avalonia.SceneGraph/Media/FormattedText.cs index af065d2f86..1169a56343 100644 --- a/src/Avalonia.SceneGraph/Media/FormattedText.cs +++ b/src/Avalonia.SceneGraph/Media/FormattedText.cs @@ -21,13 +21,15 @@ namespace Avalonia.Media /// The font style. /// The text alignment. /// The font weight. + /// The text wrapping mode. public FormattedText( string text, string fontFamilyName, double fontSize, - FontStyle fontStyle, - TextAlignment textAlignment, - FontWeight fontWeight) + FontStyle fontStyle = FontStyle.Normal, + TextAlignment textAlignment = TextAlignment.Left, + FontWeight fontWeight = FontWeight.Normal, + TextWrapping wrapping = TextWrapping.Wrap) { Contract.Requires(text != null); Contract.Requires(fontFamilyName != null); @@ -39,6 +41,7 @@ namespace Avalonia.Media FontStyle = fontStyle; FontWeight = fontWeight; TextAlignment = textAlignment; + Wrapping = wrapping; var platform = AvaloniaLocator.Current.GetService(); @@ -53,7 +56,8 @@ namespace Avalonia.Media fontSize, fontStyle, textAlignment, - fontWeight); + fontWeight, + wrapping); } /// @@ -76,63 +80,42 @@ namespace Avalonia.Media /// /// Gets the font family. /// - public string FontFamilyName - { - get; - private set; - } + public string FontFamilyName { get; } /// /// Gets the font size. /// - public double FontSize - { - get; - private set; - } + public double FontSize { get; } /// /// Gets the font style. /// - public FontStyle FontStyle - { - get; - private set; - } + public FontStyle FontStyle { get; } /// /// Gets the font weight. /// - public FontWeight FontWeight - { - get; - private set; - } + public FontWeight FontWeight { get; } /// /// Gets the text. /// - public string Text - { - get; - private set; - } + public string Text { get; } /// /// Gets platform-specific platform implementation. /// - public IFormattedTextImpl PlatformImpl - { - get; } + public IFormattedTextImpl PlatformImpl { get; } /// /// Gets the text alignment. /// - public TextAlignment TextAlignment - { - get; - private set; - } + public TextAlignment TextAlignment { get; } + + /// + /// Gets the text wrapping. + /// + public TextWrapping Wrapping { get; } /// /// Disposes of unmanaged resources associated with the formatted text. diff --git a/src/Avalonia.Controls/TextWrapping.cs b/src/Avalonia.SceneGraph/Media/TextWrapping.cs similarity index 81% rename from src/Avalonia.Controls/TextWrapping.cs rename to src/Avalonia.SceneGraph/Media/TextWrapping.cs index e1047414a9..7d50e10799 100644 --- a/src/Avalonia.Controls/TextWrapping.cs +++ b/src/Avalonia.SceneGraph/Media/TextWrapping.cs @@ -1,10 +1,10 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. -namespace Avalonia.Controls +namespace Avalonia.Media { /// - /// Controls the wrapping mode in a . + /// Controls the wrapping mode of text. /// public enum TextWrapping { diff --git a/src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs b/src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs index 4d40957a60..6beb787aab 100644 --- a/src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs +++ b/src/Avalonia.SceneGraph/Platform/IPlatformRenderInterface.cs @@ -20,6 +20,7 @@ namespace Avalonia.Platform /// The font style. /// The text alignment. /// The font weight. + /// The text wrapping mode. /// An . IFormattedTextImpl CreateFormattedText( string text, @@ -27,7 +28,8 @@ namespace Avalonia.Platform double fontSize, FontStyle fontStyle, TextAlignment textAlignment, - FontWeight fontWeight); + FontWeight fontWeight, + TextWrapping wrapping); /// /// Creates a stream geometry implementation. diff --git a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs index cd18b0f152..3157feb369 100644 --- a/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs +++ b/src/Avalonia.SceneGraph/Rendering/RendererMixin.cs @@ -62,7 +62,8 @@ namespace Avalonia.Rendering var txt = new FormattedText("Frame #" + s_frameNum + " FPS: " + s_fps, "Arial", 18, FontStyle.Normal, TextAlignment.Left, - FontWeight.Normal)) + FontWeight.Normal, + TextWrapping.NoWrap)) { ctx.FillRectangle(Brushes.White, new Rect(pt, txt.Measure())); ctx.DrawText(Brushes.Black, pt, txt); diff --git a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs b/src/Gtk/Avalonia.Cairo/CairoPlatform.cs index 8092764c1b..5b85e6c68f 100644 --- a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs +++ b/src/Gtk/Avalonia.Cairo/CairoPlatform.cs @@ -44,7 +44,8 @@ namespace Avalonia.Cairo double fontSize, FontStyle fontStyle, TextAlignment textAlignment, - Avalonia.Media.FontWeight fontWeight) + Avalonia.Media.FontWeight fontWeight, + TextWrapping wrapping) { return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight); } diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index da256f07b8..ec61aea552 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -18,7 +18,7 @@ namespace Avalonia.Skia } public IFormattedTextImpl CreateFormattedText(string text, string fontFamilyName, double fontSize, FontStyle fontStyle, - TextAlignment textAlignment, FontWeight fontWeight) + TextAlignment textAlignment, FontWeight fontWeight, TextWrapping wrapping) { return FormattedTextImpl.Create(text, fontFamilyName, fontSize, fontStyle, textAlignment, fontWeight); } diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs index ae2b5d314d..ff0bebd359 100644 --- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs +++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs @@ -49,9 +49,10 @@ namespace Avalonia.Direct2D1 double fontSize, FontStyle fontStyle, TextAlignment textAlignment, - FontWeight fontWeight) + FontWeight fontWeight, + TextWrapping wrapping) { - return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight); + return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight, wrapping); } public IRenderTarget CreateRenderer(IPlatformHandle handle) diff --git a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs index 5e77d4399c..45d06b5e27 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs @@ -18,7 +18,8 @@ namespace Avalonia.Direct2D1.Media double fontSize, FontStyle fontStyle, TextAlignment textAlignment, - FontWeight fontWeight) + FontWeight fontWeight, + TextWrapping wrapping) { var factory = AvaloniaLocator.Current.GetService(); @@ -29,6 +30,9 @@ namespace Avalonia.Direct2D1.Media (DWrite.FontStyle)fontStyle, (float)fontSize)) { + format.WordWrapping = wrapping == TextWrapping.Wrap ? + DWrite.WordWrapping.Wrap : DWrite.WordWrapping.NoWrap; + TextLayout = new DWrite.TextLayout( factory, text ?? string.Empty, diff --git a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj index f09c0d08e6..fbc639e335 100644 --- a/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj +++ b/tests/Avalonia.RenderTests/Avalonia.Direct2D1.RenderTests.csproj @@ -1,4 +1,4 @@ - + Debug @@ -73,6 +73,7 @@ + diff --git a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs new file mode 100644 index 0000000000..5b1d76cd0f --- /dev/null +++ b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs @@ -0,0 +1,47 @@ +// Copyright (c) The Avalonia Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using Avalonia.Controls; +using Avalonia.Layout; +using Avalonia.Media; +using Xunit; + +#if AVALONIA_CAIRO +namespace Avalonia.Cairo.RenderTests.Controls +#elif AVALONIA_SKIA +namespace Avalonia.Skia.RenderTests +#else +namespace Avalonia.Direct2D1.RenderTests.Controls +#endif +{ + public class TextBlockTests : TestBase + { + public TextBlockTests() + : base(@"Controls\TextBlock") + { + } + + [Fact] + public void Wrapping_NoWrap() + { + Decorator target = new Decorator + { + Padding = new Thickness(8), + Width = 200, + Height = 200, + Child = new TextBlock + { + Background = Brushes.Red, + FontSize = 12, + Foreground = Brushes.Black, + Text = "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit", + VerticalAlignment = VerticalAlignment.Top, + TextWrapping = TextWrapping.NoWrap, + } + }; + + RenderToFile(target); + CompareImages(); + } + } +} diff --git a/tests/Avalonia.RenderTests/TestBase.cs b/tests/Avalonia.RenderTests/TestBase.cs index 9f23f81e9a..9bf1b9ae0a 100644 --- a/tests/Avalonia.RenderTests/TestBase.cs +++ b/tests/Avalonia.RenderTests/TestBase.cs @@ -58,6 +58,11 @@ namespace Avalonia.Direct2D1.RenderTests protected void RenderToFile(Control target, [CallerMemberName] string testName = "") { + if (!Directory.Exists(OutputPath)) + { + Directory.CreateDirectory(OutputPath); + } + string path = Path.Combine(OutputPath, testName + ".out.png"); using (RenderTargetBitmap bitmap = new RenderTargetBitmap( diff --git a/tests/Avalonia.UnitTests/TestServices.cs b/tests/Avalonia.UnitTests/TestServices.cs index a3f13af8a5..db0f600a0a 100644 --- a/tests/Avalonia.UnitTests/TestServices.cs +++ b/tests/Avalonia.UnitTests/TestServices.cs @@ -143,7 +143,8 @@ namespace Avalonia.UnitTests It.IsAny(), It.IsAny(), It.IsAny(), - It.IsAny()) == Mock.Of() && + It.IsAny(), + It.IsAny()) == Mock.Of() && x.CreateStreamGeometry() == Mock.Of( y => y.Open() == Mock.Of())); } diff --git a/tests/TestFiles/Direct2D1/Controls/TextBlock/Wrapping_NoWrap.expected.png b/tests/TestFiles/Direct2D1/Controls/TextBlock/Wrapping_NoWrap.expected.png new file mode 100644 index 0000000000..2296e02d68 Binary files /dev/null and b/tests/TestFiles/Direct2D1/Controls/TextBlock/Wrapping_NoWrap.expected.png differ