Skip to content

Commit

Permalink
Merge pull request #1549 from Jonarw/skiamultiline
Browse files Browse the repository at this point in the history
Add support for multi-line text to SkiaRenderContext (#1538)
  • Loading branch information
Jonarw committed May 8, 2020
2 parents 1bdf6b4 + 598ba6b commit 65d2f88
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file.
- WindowsForms ExampleBrowser can display transposed versions of examples (#1535)
- Example for Issue #1545 showing the use of different line endings
- Support for unix line endings in OxyPlot.ImageSharp, OxyPlot.Svg, and OxyPlot.Pdf (#1545)
- Multi-Line Text support to SkiaRenderContext (#1538)

### Changed
- Legends model (#644)
Expand Down
26 changes: 26 additions & 0 deletions Source/Examples/ExampleLibrary/Examples/RenderingCapabilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,32 @@ public static PlotModel DrawTextAlignmentRotation()
return model;
}

/// <summary>
/// Shows multi-line alignment capabilities for the DrawText method.
/// </summary>
/// <returns>A plot model.</returns>
[Example("DrawText - Multi-line Alignment/Rotation")]
public static PlotModel DrawMultilineTextAlignmentRotation()
{
var model = new PlotModel();
model.Annotations.Add(new DelegateAnnotation(rc =>
{
for (var ha = HorizontalAlignment.Left; ha <= HorizontalAlignment.Right; ha++)
{
for (var va = VerticalAlignment.Top; va <= VerticalAlignment.Bottom; va++)
{
var origin = new ScreenPoint(((int)ha + 2) * 170, ((int)va + 2) * 170);
rc.FillCircle(origin, 3, OxyColors.Blue, EdgeRenderingMode.Adaptive);
for (var rotation = 0; rotation < 360; rotation += 90)
{
rc.DrawText(origin, $"R{rotation:000}\n{ha}\n{va}", OxyColors.Black, fontSize: 20d, rotation: rotation, horizontalAlignment: ha, verticalAlignment: va);
}
}
}
}));
return model;
}

/// <summary>
/// Shows color capabilities for the DrawText method.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<Copyright>OxyPlot contributors</Copyright>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Platforms>AnyCPU;x86;x64</Platforms>
<LangVersion>8</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)|$(Platform)'=='net461|AnyCPU'">
<PlatformTarget>x86</PlatformTarget>
Expand Down
10 changes: 10 additions & 0 deletions Source/OxyPlot.SkiaSharp.Tests/SvgExporterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

namespace OxyPlot.SkiaSharp.Tests
{
using ExampleLibrary;
using NUnit.Framework;
using OxyPlot.SkiaSharp;
using System.IO;
Expand All @@ -24,6 +25,15 @@ public void Export_SomeExamplesInExampleLibrary_CheckThatAllFilesExist()
ExportTest.Export_FirstExampleOfEachExampleGroup_CheckThatAllFilesExist(exporter, directory, ".svg");
}

[Test]
public void TestMultilineAlignment()
{
var exporter = new SvgExporter { Width = 1000, Height = 750 };
var model = RenderingCapabilities.DrawMultilineTextAlignmentRotation();
using var stream = File.Create(Path.Combine(this.outputDirectory, "Multiline-Alignment.svg"));
exporter.Export(model, stream);
}

[OneTimeSetUp]
public void Setup()
{
Expand Down
61 changes: 35 additions & 26 deletions Source/OxyPlot.SkiaSharp/SkiaRenderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,44 +365,51 @@ public void DrawRectangles(IList<OxyRect> rectangles, OxyColor fill, OxyColor st
var x = this.Convert(p.X);
var y = this.Convert(p.Y);

var metrics = paint.FontMetrics;
var lines = StringHelper.SplitLines(text);
var lineHeight = paint.GetFontMetrics(out var metrics);

var deltaY = verticalAlignment switch
{
VerticalAlignment.Top => -metrics.Ascent,
VerticalAlignment.Middle => -(metrics.Ascent + metrics.Descent) / 2,
VerticalAlignment.Bottom => -metrics.Descent,
VerticalAlignment.Middle => -(metrics.Ascent + metrics.Descent + lineHeight * (lines.Length - 1)) / 2,
VerticalAlignment.Bottom => -metrics.Descent - lineHeight * (lines.Length - 1),
_ => throw new ArgumentOutOfRangeException(nameof(verticalAlignment))
};

using var _ = new SKAutoCanvasRestore(this.SkCanvas);
this.SkCanvas.Translate(x, y);
this.SkCanvas.RotateDegrees((float)rotation);

if (this.UseTextShaping)
foreach (var line in lines)
{
var width = this.MeasureText(text, shaper, paint);
var deltaX = horizontalAlignment switch
if (this.UseTextShaping)
{
HorizontalAlignment.Left => 0,
HorizontalAlignment.Center => -width / 2,
HorizontalAlignment.Right => -width,
_ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment))
};

this.paint.TextAlign = SKTextAlign.Left;
this.SkCanvas.DrawShapedText(shaper, text, deltaX, deltaY, paint);
}
else
{
paint.TextAlign = horizontalAlignment switch
var width = this.MeasureText(line, shaper, paint);
var deltaX = horizontalAlignment switch
{
HorizontalAlignment.Left => 0,
HorizontalAlignment.Center => -width / 2,
HorizontalAlignment.Right => -width,
_ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment))
};

this.paint.TextAlign = SKTextAlign.Left;
this.SkCanvas.DrawShapedText(shaper, line, deltaX, deltaY, paint);
}
else
{
HorizontalAlignment.Left => SKTextAlign.Left,
HorizontalAlignment.Center => SKTextAlign.Center,
HorizontalAlignment.Right => SKTextAlign.Right,
_ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment))
};
paint.TextAlign = horizontalAlignment switch
{
HorizontalAlignment.Left => SKTextAlign.Left,
HorizontalAlignment.Center => SKTextAlign.Center,
HorizontalAlignment.Right => SKTextAlign.Right,
_ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment))
};

this.SkCanvas.DrawText(text, 0, deltaY, paint);
this.SkCanvas.DrawText(line, 0, deltaY, paint);
}

deltaY += lineHeight;
}
}

Expand All @@ -414,9 +421,11 @@ public OxySize MeasureText(string text, string fontFamily = null, double fontSiz
return new OxySize(0, 0);
}

var lines = StringHelper.SplitLines(text);
var paint = this.GetTextPaint(fontFamily, fontSize, fontWeight, out var shaper);
var width = this.MeasureText(text, shaper, paint);
var height = paint.GetFontMetrics(out _);
var height = paint.GetFontMetrics(out _) * lines.Length;
var width = lines.Max(line => this.MeasureText(line, shaper, paint));

return new OxySize(this.ConvertBack(width), this.ConvertBack(height));
}

Expand Down

0 comments on commit 65d2f88

Please sign in to comment.