forked from oxyplot/oxyplot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve OxyPlot.SvgRenderContext text rendering (oxyplot#1531)
- Loading branch information
1 parent
b2ff4f6
commit cbc086d
Showing
5 changed files
with
297 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
// -------------------------------------------------------------------------------------------------------------------- | ||
// <copyright file="SvgExporterTests.cs" company="OxyPlot"> | ||
// Copyright (c) 2020 OxyPlot contributors | ||
// </copyright> | ||
// -------------------------------------------------------------------------------------------------------------------- | ||
|
||
namespace OxyPlot.ImageSharp.Tests | ||
{ | ||
using System; | ||
using System.IO; | ||
using NUnit.Framework; | ||
|
||
using OxyPlot.Series; | ||
using OxyPlot.ImageSharp; | ||
using OxyPlot.Annotations; | ||
|
||
[TestFixture] | ||
public class SvgExporterTests | ||
{ | ||
private const string SVG_FOLDER = "SVG"; | ||
private string outputDirectory; | ||
|
||
[OneTimeSetUp] | ||
public void Setup() | ||
{ | ||
this.outputDirectory = Path.Combine(TestContext.CurrentContext.WorkDirectory, SVG_FOLDER); | ||
Directory.CreateDirectory(this.outputDirectory); | ||
} | ||
|
||
[Test] | ||
public void Export_SomeExamplesInExampleLibrary_CheckThatAllFilesExist() | ||
{ | ||
var exporter = new SvgExporter(1000, 750); | ||
var directory = Path.Combine(this.outputDirectory, "ExampleLibrary"); | ||
ExportTest.Export_FirstExampleOfEachExampleGroup_CheckThatAllFilesExist(exporter, directory, ".svg"); | ||
} | ||
|
||
[Test] | ||
public void ExportToStream() | ||
{ | ||
var plotModel = CreateTestModel1(); | ||
var exporter = new SvgExporter(1000, 750); | ||
var stream = new MemoryStream(); | ||
exporter.Export(plotModel, stream); | ||
|
||
Assert.IsTrue(stream.Length > 0); | ||
} | ||
|
||
[Test] | ||
public void ExportToFile() | ||
{ | ||
var plotModel = CreateTestModel1(); | ||
var fileName = Path.Combine(this.outputDirectory, "Plot1.svg"); | ||
SvgExporter.Export(plotModel, fileName, 1000, 750); | ||
|
||
Assert.IsTrue(File.Exists(fileName)); | ||
} | ||
|
||
[Test] | ||
public void ExportWithDifferentBackground() | ||
{ | ||
var plotModel = CreateTestModel1(); | ||
plotModel.Background = OxyColors.Yellow; | ||
var fileName = Path.Combine(this.outputDirectory, "Background_Yellow.svg"); | ||
var exporter = new SvgExporter(1000, 750); | ||
using (var stream = File.OpenWrite(fileName)) | ||
{ | ||
exporter.Export(plotModel, stream); | ||
} | ||
|
||
Assert.IsTrue(File.Exists(fileName)); | ||
} | ||
|
||
[Test] | ||
[TestCase(0.75)] | ||
[TestCase(1)] | ||
[TestCase(1.2)] | ||
[TestCase(2)] | ||
[TestCase(3.1415)] | ||
public void ExportWithResolution(double factor) | ||
{ | ||
var resolution = (int)(96 * factor); | ||
var plotModel = CreateTestModel1(); | ||
var directory = Path.Combine(this.outputDirectory, "Resolution"); | ||
Directory.CreateDirectory(directory); | ||
|
||
var fileName = Path.Combine(directory, $"Resolution{resolution}.svg"); | ||
var exporter = new SvgExporter((int)(400 * factor), (int)(300 * factor), resolution); | ||
|
||
using (var stream = File.OpenWrite(fileName)) | ||
{ | ||
exporter.Export(plotModel, stream); | ||
} | ||
|
||
Assert.IsTrue(File.Exists(fileName)); | ||
} | ||
|
||
[Test] | ||
[TestCase(true)] | ||
[TestCase(false)] | ||
public void PlotBackgroundImageTest(bool interpolate) | ||
{ | ||
// this is a test of the DrawImage function; don't add pointless backgrounds to your plots | ||
|
||
var plotModel = CreateTestModel1(); | ||
|
||
var pixelData = new OxyColor[5, 5]; | ||
for (int i = 0; i < pixelData.GetLength(0); i++) | ||
{ | ||
for (int j = 0; j < pixelData.GetLength(1); j++) | ||
{ | ||
pixelData[i, j] = OxyColor.FromArgb(255, 128, (byte)((i * 255) / pixelData.GetLength(0)), (byte)((j * 255) / pixelData.GetLength(1))); | ||
} | ||
} | ||
|
||
var oxyImage = OxyImage.Create(pixelData, ImageFormat.Png); | ||
var imageAnnotation = new ImageAnnotation() | ||
{ | ||
ImageSource = oxyImage, | ||
X = new PlotLength(-0.0, PlotLengthUnit.RelativeToPlotArea), | ||
Y = new PlotLength(-0.0, PlotLengthUnit.RelativeToPlotArea), | ||
Width = new PlotLength(1.0, PlotLengthUnit.RelativeToPlotArea), | ||
Height = new PlotLength(1.0, PlotLengthUnit.RelativeToPlotArea), | ||
HorizontalAlignment = HorizontalAlignment.Left, | ||
VerticalAlignment = VerticalAlignment.Top, | ||
Interpolate = interpolate | ||
}; | ||
plotModel.Annotations.Add(imageAnnotation); | ||
|
||
var fileName = Path.Combine(this.outputDirectory, $"PlotBackground{(interpolate ? "Interpolated" : "Pixelated")}.svg"); | ||
var exporter = new SvgExporter(1000, 750); | ||
using (var stream = File.OpenWrite(fileName)) | ||
{ | ||
exporter.Export(plotModel, stream); | ||
} | ||
|
||
Assert.IsTrue(File.Exists(fileName)); | ||
} | ||
|
||
[Test] | ||
[TestCase(true)] | ||
[TestCase(false)] | ||
public void LargeImageTest(bool interpolate) | ||
{ | ||
// this is a test of the DrawImage function; don't add pointless backgrounds to your plots | ||
|
||
var plotModel = CreateTestModel1(); | ||
|
||
var pixelData = new OxyColor[5, 5]; | ||
for (int i = 0; i < pixelData.GetLength(0); i++) | ||
{ | ||
for (int j = 0; j < pixelData.GetLength(1); j++) | ||
{ | ||
pixelData[i, j] = OxyColor.FromArgb(255, 128, (byte)((i * 255) / pixelData.GetLength(0)), (byte)((j * 255) / pixelData.GetLength(1))); | ||
} | ||
} | ||
|
||
var oxyImage = OxyImage.Create(pixelData, ImageFormat.Png); | ||
var imageAnnotation = new ImageAnnotation() | ||
{ | ||
ImageSource = oxyImage, | ||
X = new PlotLength(-1, PlotLengthUnit.RelativeToViewport), | ||
Y = new PlotLength(-1, PlotLengthUnit.RelativeToViewport), | ||
Width = new PlotLength(3, PlotLengthUnit.RelativeToViewport), | ||
Height = new PlotLength(3, PlotLengthUnit.RelativeToViewport), | ||
HorizontalAlignment = HorizontalAlignment.Left, | ||
VerticalAlignment = VerticalAlignment.Top, | ||
Interpolate = interpolate | ||
}; | ||
plotModel.Annotations.Add(imageAnnotation); | ||
|
||
var fileName = Path.Combine(this.outputDirectory, $"LargeImage{(interpolate ? "Interpolated" : "Pixelated")}.svg"); | ||
var exporter = new SvgExporter(1000, 750); | ||
using (var stream = File.OpenWrite(fileName)) | ||
{ | ||
exporter.Export(plotModel, stream); | ||
} | ||
|
||
Assert.IsTrue(File.Exists(fileName)); | ||
} | ||
|
||
private static PlotModel CreateTestModel1() | ||
{ | ||
var model = new PlotModel { Title = "Test 1" }; | ||
model.Series.Add(new FunctionSeries(Math.Sin, 0, Math.PI * 8, 200, "sin(x)")); | ||
return model; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// -------------------------------------------------------------------------------------------------------------------- | ||
// <copyright file="SvgExporter.cs" company="OxyPlot"> | ||
// Copyright (c) 2014 OxyPlot contributors | ||
// </copyright> | ||
// <summary> | ||
// Provides functionality to export plots to scalable vector graphics using <see cref="Graphics" /> for text measuring. | ||
// </summary> | ||
// -------------------------------------------------------------------------------------------------------------------- | ||
|
||
namespace OxyPlot.ImageSharp | ||
{ | ||
using System; | ||
using System.IO; | ||
|
||
/// <summary> | ||
/// Provides functionality to export plots to scalable vector graphics using ImageSharp for text measuring. | ||
/// </summary> | ||
public class SvgExporter : OxyPlot.SvgExporter, IDisposable | ||
{ | ||
/// <summary> | ||
/// The render context. | ||
/// </summary> | ||
private ImageRenderContext irc; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SvgExporter" /> class. | ||
/// </summary> | ||
public SvgExporter(double width, double height, double resolution = 96) | ||
{ | ||
this.Width = width; | ||
this.Height = height; | ||
this.irc = new ImageRenderContext(1, 1, OxyColors.Undefined, resolution); | ||
this.TextMeasurer = irc; | ||
} | ||
|
||
/// <summary> | ||
/// Exports the specified <see cref="PlotModel" /> to the specified file. | ||
/// </summary> | ||
/// <param name="model">The model.</param> | ||
/// <param name="fileName">The file name.</param> | ||
/// <param name="width">The width.</param> | ||
/// <param name="height">The height.</param> | ||
/// <param name="resolution">The resolution in dpi (defaults to 96dpi).</param> | ||
public static void Export(IPlotModel model, string fileName, int width, int height, double resolution = 96) | ||
{ | ||
var exporter = new SvgExporter(width, height, resolution); | ||
using (var stream = File.Create(fileName)) | ||
{ | ||
exporter.Export(model, stream); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | ||
/// </summary> | ||
public void Dispose() | ||
{ | ||
this.irc.Dispose(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.