diff --git a/Source/OxyPlot.ImageSharp/ImageRenderContext.cs b/Source/OxyPlot.ImageSharp/ImageRenderContext.cs
index 1eec62f59..9d3b6f5da 100644
--- a/Source/OxyPlot.ImageSharp/ImageRenderContext.cs
+++ b/Source/OxyPlot.ImageSharp/ImageRenderContext.cs
@@ -27,11 +27,6 @@ namespace OxyPlot.ImageSharp
///
public class ImageRenderContext : RenderContextBase, IDisposable, ITextMeasurer
{
- ///
- /// Gets or sets the used by this instance.
- ///
- public TextArranger TextArranger { get; set; }
-
///
/// The default font to use when a request font cannot be found.
///
@@ -91,6 +86,11 @@ public ImageRenderContext(int width, int height, OxyColor background, double dpi
this.TextArranger = new TextArranger(this);
}
+ ///
+ /// Gets or sets the used by this instance.
+ ///
+ public TextArranger TextArranger { get; set; }
+
///
/// Gets the DPI scaling factor. A value of 1 corresponds to 96 DPI (dots per inch).
///
diff --git a/Source/OxyPlot.ImageSharp/SvgExporter.cs b/Source/OxyPlot.ImageSharp/SvgExporter.cs
index 48e167c70..b7a559ec7 100644
--- a/Source/OxyPlot.ImageSharp/SvgExporter.cs
+++ b/Source/OxyPlot.ImageSharp/SvgExporter.cs
@@ -25,12 +25,15 @@ public class SvgExporter : OxyPlot.SvgExporter, IDisposable
///
/// Initializes a new instance of the class.
///
+ /// The width.
+ /// The height.
+ /// The resolution in dots per inch.
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;
+ this.TextMeasurer = this.irc;
}
///
diff --git a/Source/OxyPlot.SkiaSharp/SkiaRenderContext.cs b/Source/OxyPlot.SkiaSharp/SkiaRenderContext.cs
index 5c70bb6bb..9f6b679fd 100644
--- a/Source/OxyPlot.SkiaSharp/SkiaRenderContext.cs
+++ b/Source/OxyPlot.SkiaSharp/SkiaRenderContext.cs
@@ -6,14 +6,12 @@
namespace OxyPlot.SkiaSharp
{
- using global::SkiaSharp;
- using global::SkiaSharp.HarfBuzz;
- using HarfBuzzSharp;
- using OxyPlot.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
- using System.Security.Cryptography;
+ using global::SkiaSharp;
+ using global::SkiaSharp.HarfBuzz;
+ using OxyPlot.Rendering;
///
/// Implements based on SkiaSharp.
@@ -30,7 +28,7 @@ public class SkiaRenderContext : IRenderContext, IDisposable, ITextMeasurer
///
public SkiaRenderContext()
{
- TextArranger = new TextArranger(this);
+ this.TextArranger = new TextArranger(this);
}
///
@@ -243,7 +241,7 @@ public void DrawPolygon(
double[] dashArray = null,
LineJoin lineJoin = LineJoin.Miter)
{
- if (!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0) || points.Count < 2)
+ if ((!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0)) || points.Count < 2)
{
return;
}
@@ -276,7 +274,7 @@ public void DrawPolygons(
double[] dashArray = null,
LineJoin lineJoin = LineJoin.Miter)
{
- if (!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0) || polygons.Count == 0)
+ if ((!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0)) || polygons.Count == 0)
{
return;
}
@@ -333,7 +331,7 @@ public void DrawRectangle(OxyRect rectangle, OxyColor fill, OxyColor stroke, dou
///
public void DrawRectangles(IList rectangles, OxyColor fill, OxyColor stroke, double thickness, EdgeRenderingMode edgeRenderingMode)
{
- if (!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0) || rectangles.Count == 0)
+ if ((!fill.IsVisible() && !(stroke.IsVisible() || thickness <= 0)) || rectangles.Count == 0)
{
return;
}
@@ -381,7 +379,7 @@ public void DrawText(
var x = this.Convert(p.X);
var y = this.Convert(p.Y);
- using var _ = new SKAutoCanvasRestore(this.SkCanvas);
+ using var canvasRestore = new SKAutoCanvasRestore(this.SkCanvas);
this.SkCanvas.Translate(x, y);
this.SkCanvas.RotateDegrees((float)rotation);
@@ -398,7 +396,7 @@ public void DrawText(
HorizontalAlignment.Left => SKTextAlign.Left,
HorizontalAlignment.Center => SKTextAlign.Center,
HorizontalAlignment.Right => SKTextAlign.Right,
- _ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment))
+ _ => throw new ArgumentOutOfRangeException(nameof(horizontalAlignment)),
};
}
@@ -455,7 +453,7 @@ public void SetToolTip(string text)
///
public FontMetrics GetFontMetrics(string fontFamily, double fontSize, double fontWeight)
{
- var lineSpacing = paint.GetFontMetrics(out var metrics);
+ var lineSpacing = this.paint.GetFontMetrics(out var metrics);
var ascender = this.ConvertBack(Math.Abs(metrics.Ascent));
var descender = this.ConvertBack(Math.Abs(metrics.Descent));
var leading = this.ConvertBack(Math.Abs(metrics.Leading));
@@ -791,7 +789,7 @@ private SKPaint GetLinePaint(OxyColor strokeColor, double strokeThickness, EdgeR
LineJoin.Miter => SKStrokeJoin.Miter,
LineJoin.Round => SKStrokeJoin.Round,
LineJoin.Bevel => SKStrokeJoin.Bevel,
- _ => throw new ArgumentOutOfRangeException(nameof(lineJoin))
+ _ => throw new ArgumentOutOfRangeException(nameof(lineJoin)),
};
return paint;
@@ -952,12 +950,12 @@ public FontDescriptor(string fontFamily, double fontWeight)
}
///
- /// The font family.
+ /// Gets the font family.
///
public string FontFamily { get; }
///
- /// The font weight.
+ /// Gets the font weight.
///
public double FontWeight { get; }
@@ -971,8 +969,8 @@ public override bool Equals(object obj)
public override int GetHashCode()
{
var hashCode = -1030903623;
- hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(this.FontFamily);
- hashCode = hashCode * -1521134295 + this.FontWeight.GetHashCode();
+ hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.FontFamily);
+ hashCode = (hashCode * -1521134295) + this.FontWeight.GetHashCode();
return hashCode;
}
}
diff --git a/Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs b/Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs
index ee98d3f6d..268d71dd6 100644
--- a/Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs
+++ b/Source/OxyPlot.WindowsForms/GraphicsRenderContext.cs
@@ -30,11 +30,6 @@ namespace OxyPlot.WindowsForms
///
public class GraphicsRenderContext : RenderContextBase, IDisposable, ITextMeasurer
{
- ///
- /// Gets or sets the for this instance.
- ///
- public TextArranger TextArranger { get; set; }
-
///
/// The font size factor.
///
@@ -87,6 +82,11 @@ public GraphicsRenderContext(Graphics graphics = null)
this.TextArranger = new TextArranger(this);
}
+ ///
+ /// Gets or sets the for this instance.
+ ///
+ public TextArranger TextArranger { get; set; }
+
///
/// Sets the graphics target.
///
@@ -113,7 +113,7 @@ public override void DrawEllipse(OxyRect rect, OxyColor fill, OxyColor stroke, d
{
return;
}
-
+
var pen = this.GetCachedPen(stroke, thickness);
this.g.DrawEllipse(pen, (float)rect.Left, (float)rect.Top, (float)rect.Width, (float)rect.Height);
}
@@ -231,7 +231,6 @@ public override void DrawText(
this.g.TranslateTransform((float)p.X, (float)p.Y);
- //var layoutRectangle = new RectangleF(0, 0, size.Width, size.Height);
if (Math.Abs(rotation) > double.Epsilon)
{
this.g.RotateTransform((float)rotation);
diff --git a/Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj b/Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj
index fcd6337e4..6762f1830 100644
--- a/Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj
+++ b/Source/OxyPlot.WindowsForms/OxyPlot.WindowsForms.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/Source/OxyPlot.Wpf/OxyPlot.Wpf.csproj b/Source/OxyPlot.Wpf/OxyPlot.Wpf.csproj
index 824f2f2c1..d08b8c14c 100644
--- a/Source/OxyPlot.Wpf/OxyPlot.Wpf.csproj
+++ b/Source/OxyPlot.Wpf/OxyPlot.Wpf.csproj
@@ -27,7 +27,13 @@
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
diff --git a/Source/OxyPlot/Pdf/PdfRenderContext.cs b/Source/OxyPlot/Pdf/PdfRenderContext.cs
index eaf4dade9..0379b3e51 100644
--- a/Source/OxyPlot/Pdf/PdfRenderContext.cs
+++ b/Source/OxyPlot/Pdf/PdfRenderContext.cs
@@ -9,22 +9,17 @@
namespace OxyPlot
{
- using OxyPlot.Rendering;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+ using OxyPlot.Rendering;
///
/// Implements an producing PDF documents by .
///
public class PdfRenderContext : RenderContextBase, ITextMeasurer
{
- ///
- /// Gets or sets the for this instance.
- ///
- public TextArranger TextArranger { get; set; }
-
///
/// The current document.
///
@@ -56,6 +51,11 @@ public PdfRenderContext(double width, double height, OxyColor background)
this.TextArranger = new TextArranger(this);
}
+ ///
+ /// Gets or sets the for this instance.
+ ///
+ public TextArranger TextArranger { get; set; }
+
///
/// Saves the output to the specified stream.
///
diff --git a/Source/OxyPlot/Rendering/SimpleTextTrimmer.cs b/Source/OxyPlot/Rendering/SimpleTextTrimmer.cs
index 861303cf5..5f374dbe4 100644
--- a/Source/OxyPlot/Rendering/SimpleTextTrimmer.cs
+++ b/Source/OxyPlot/Rendering/SimpleTextTrimmer.cs
@@ -7,13 +7,13 @@
//
// --------------------------------------------------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using System.Text.RegularExpressions;
-
namespace OxyPlot.Rendering
{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq.Expressions;
+ using System.Text.RegularExpressions;
+
///
/// A simple trimmer that doesn't use glyph information.
///
@@ -34,95 +34,63 @@ public class SimpleTextTrimmer : ITextTrimmer
///
public SimpleTextTrimmer()
{
- TrimToWord = false;
- Ellipsis = AsciiEllipsis;
- UseEllipsis = false;
+ this.TrimToWord = false;
+ this.Ellipsis = AsciiEllipsis;
+ this.AppendEllipsis = false;
}
///
- /// Gets or sets whether text should be trimmed to word boundaries.
+ /// Gets or sets a value indicating whether text should be trimmed to word boundaries.
///
public bool TrimToWord { get; set; }
///
- /// Gets or sets a value to append to any trimmed text when is true.
+ /// Gets or sets a value to append to any trimmed text when is true.
///
public string Ellipsis { get; set; }
///
- /// Gets or sets whether the value in should be appended to any trimmed text.
+ /// Gets or sets a value indicating whether an ellipsis should be appended to any trimmed text.
///
- public bool UseEllipsis { get; set; }
+ public bool AppendEllipsis { get; set; }
- ///
- public string Trim(ITextMeasurer textMeasurer, string line, double width, string fontFamily, double fontSize, double fontWeight)
+ ///
+ /// Gets a list of indexes that correspond to the first c after a character in the single line of text given.
+ ///
+ /// The text.
+ /// The list of character boundaries.
+ public static IList GetCharacterBoundaries(string text)
{
- var ellipsis = this.UseEllipsis ? this.Ellipsis : null;
+ var res = new List();
- if (this.TrimToWord)
- {
- var boundaries = GetWordBoundaries(line);
- return TrimAtBoundaries(textMeasurer, line, width, fontFamily, fontSize, fontWeight, ellipsis, boundaries);
- }
- else
+ // handle surrogate pairs explicitly
+ var matches = Regex.Matches(text, @"([\uD800-\uDBFF}][\uDC00-\uDFFF]|[^\s])\p{M}*", RegexOptions.Singleline);
+ for (int i = 0; i < matches.Count; i++)
{
- var boundaries = GetCharacterBoundaries(line);
- return TrimAtBoundaries(textMeasurer, line, width, fontFamily, fontSize, fontWeight, ellipsis, boundaries);
+ var m = matches[i];
+ res.Add(m.Index + m.Length);
}
+
+ return res;
}
///
- /// Performs common boundary condition checks. Returns true if the should be returned immediately in lieu of other trimming.
+ /// Gets a list of indexes that correspond to the first char after a word in the single line of text given.
///
- /// The to use.
- /// The line of text to trim.
- /// The width in which the text must fix.
- /// The font family.
- /// The font size in 1/96ths of an inch.
- /// The font weight.
- /// The ellipsis, if any, to append to the end of the text.
- /// The resulting text if a boundary condition was observed, otherwise null.
- /// true if a boundary condition was met, otherwise false.
- public static bool BoundaryCheck(ITextMeasurer textMeasurer, string line, double width, string fontFamily, double fontSize, double fontWeight, string ellipsis, out string boundaryResult)
+ /// The text.
+ /// The list of word boundaries.
+ public static IList GetWordBoundaries(string text)
{
- if (textMeasurer == null)
- {
- throw new ArgumentNullException(nameof(textMeasurer));
- }
-
- if (line == null)
- {
- throw new ArgumentNullException(nameof(line));
- }
-
- if (width <= 0)
- {
- // nothing will fit
- boundaryResult = string.Empty;
- return true;
- }
-
- var lineWidth = textMeasurer.MeasureTextWidth(line, fontFamily, fontSize, fontWeight);
- if (lineWidth <= width)
- {
- // do nothing
- boundaryResult = line;
- return true;
- }
+ var res = new List();
- if (ellipsis != null)
+ var matches = Regex.Matches(text, @"[^\s]+", RegexOptions.Singleline);
+ for (int i = 0; i < matches.Count; i++)
{
- var ellipsisWidth = textMeasurer.MeasureTextWidth(ellipsis, fontFamily, fontSize, fontWeight);
- if (ellipsisWidth <= width)
- {
- // ellipsis won't fit
- boundaryResult = string.Empty;
- return true;
- }
+ var m = matches[i];
+ res.Add(m.Index + m.Length);
}
- boundaryResult = null;
- return false;
+ return res;
}
///
@@ -151,7 +119,7 @@ public static string TrimAtBoundaries(ITextMeasurer textMeasurer, string line, d
while (e > s)
{
- var m = s + (e - s + 1) / 2;
+ var m = s + ((e - s + 1) / 2);
var lineWidth = textMeasurer.MeasureTextWidth(line.Substring(0, boundaries[m]) + ellipsis, fontFamily, fontSize, fontWeight);
if (lineWidth > width)
@@ -175,43 +143,75 @@ public static string TrimAtBoundaries(ITextMeasurer textMeasurer, string line, d
}
}
- ///
- /// Gets a list of indexes that correspond to the first c after a character in the single line of text given.
- ///
- /// The text.
- /// The list of character boundaries.
- public static IList GetCharacterBoundaries(string text)
+ ///
+ public string Trim(ITextMeasurer textMeasurer, string line, double width, string fontFamily, double fontSize, double fontWeight)
{
- var res = new List();
+ var ellipsis = this.AppendEllipsis ? this.Ellipsis : null;
- // handle surrogate pairs explicitly
- var matches = Regex.Matches(text, @"([\uD800-\uDBFF}][\uDC00-\uDFFF]|[^\s])\p{M}*", RegexOptions.Singleline);
- for (int i = 0; i < matches.Count; i++)
+ if (this.TrimToWord)
{
- var m = matches[i];
- res.Add(m.Index + m.Length);
+ var boundaries = GetWordBoundaries(line);
+ return TrimAtBoundaries(textMeasurer, line, width, fontFamily, fontSize, fontWeight, ellipsis, boundaries);
+ }
+ else
+ {
+ var boundaries = GetCharacterBoundaries(line);
+ return TrimAtBoundaries(textMeasurer, line, width, fontFamily, fontSize, fontWeight, ellipsis, boundaries);
}
-
- return res;
}
///
- /// Gets a list of indexes that correspond to the first char after a word in the single line of text given.
+ /// Performs common boundary condition checks. Returns true if the should be returned immediately in lieu of other trimming.
///
- /// The text.
- /// The list of word boundaries.
- public static IList GetWordBoundaries(string text)
+ /// The to use.
+ /// The line of text to trim.
+ /// The width in which the text must fix.
+ /// The font family.
+ /// The font size in 1/96ths of an inch.
+ /// The font weight.
+ /// The ellipsis, if any, to append to the end of the text.
+ /// The resulting text if a boundary condition was observed, otherwise null.
+ /// true if a boundary condition was met, otherwise false.
+ private static bool BoundaryCheck(ITextMeasurer textMeasurer, string line, double width, string fontFamily, double fontSize, double fontWeight, string ellipsis, out string boundaryResult)
{
- var res = new List();
+ if (textMeasurer == null)
+ {
+ throw new ArgumentNullException(nameof(textMeasurer));
+ }
- var matches = Regex.Matches(text, @"[^\s]+", RegexOptions.Singleline);
- for (int i = 0; i < matches.Count; i++)
+ if (line == null)
{
- var m = matches[i];
- res.Add(m.Index + m.Length);
+ throw new ArgumentNullException(nameof(line));
}
- return res;
+ if (width <= 0)
+ {
+ // nothing will fit
+ boundaryResult = string.Empty;
+ return true;
+ }
+
+ var lineWidth = textMeasurer.MeasureTextWidth(line, fontFamily, fontSize, fontWeight);
+ if (lineWidth <= width)
+ {
+ // do nothing
+ boundaryResult = line;
+ return true;
+ }
+
+ if (ellipsis != null)
+ {
+ var ellipsisWidth = textMeasurer.MeasureTextWidth(ellipsis, fontFamily, fontSize, fontWeight);
+ if (ellipsisWidth <= width)
+ {
+ // ellipsis won't fit
+ boundaryResult = string.Empty;
+ return true;
+ }
+ }
+
+ boundaryResult = null;
+ return false;
}
}
}
diff --git a/Source/OxyPlot/Rendering/TextArranger.cs b/Source/OxyPlot/Rendering/TextArranger.cs
index df7c2930b..ea3ed05f7 100644
--- a/Source/OxyPlot/Rendering/TextArranger.cs
+++ b/Source/OxyPlot/Rendering/TextArranger.cs
@@ -7,12 +7,12 @@
//
// --------------------------------------------------------------------------------------------------------------------
-using System;
-using System.Linq;
-using System.Xml.Linq;
-
namespace OxyPlot.Rendering
{
+ using System;
+ using System.Linq;
+ using System.Xml.Linq;
+
///
/// Arranges text.
///
@@ -21,12 +21,13 @@ public class TextArranger
///
/// Initializes a new instance of the class.
///
+ /// The to be used by this instance.
public TextArranger(ITextMeasurer textMeasurer)
{
- TextMeasurer = textMeasurer ?? throw new ArgumentNullException(nameof(textMeasurer));
+ this.TextMeasurer = textMeasurer ?? throw new ArgumentNullException(nameof(textMeasurer));
- TextTrimmer = new SimpleTextTrimmer(); // match WPF
- SquashToBounds = false; // match WPF
+ this.TextTrimmer = new SimpleTextTrimmer(); // match WPF
+ this.SquashTrimmedTextBounds = false; // match WPF
}
///
@@ -40,10 +41,9 @@ public TextArranger(ITextMeasurer textMeasurer)
public ITextTrimmer TextTrimmer { get; set; }
///
- /// Gets or sets whether to squash the bounds of trimmed text.
- /// TODO: give this a better name and description.
+ /// Gets or sets a value indicating whether to squash the bounds of trimmed text to the size the text.
///
- public bool SquashToBounds { get; set; }
+ public bool SquashTrimmedTextBounds { get; set; }
///
/// Splits the text into multiple lines, and indicates where they should be rendered given the given target alignment.
@@ -99,7 +99,7 @@ public void ArrangeText(
{
bounds = new OxySize(Math.Ceiling(Math.Min(bounds.Width, maxSize.Value.Width)), Math.Ceiling(Math.Min(bounds.Height, maxSize.Value.Height)));
}
-
+
// split into lines
lines = StringHelper.SplitLines(text);
@@ -109,7 +109,7 @@ public void ArrangeText(
var clippedLineCount = 1 + (int)((bounds.Height - lineHeight) / (lineHeight + leading));
lines = lines.Take(clippedLineCount).ToArray();
- if (this.SquashToBounds)
+ if (this.SquashTrimmedTextBounds)
{
bounds = new OxySize(bounds.Width, ((lineHeight + leading) * lines.Length) - leading);
}
@@ -123,7 +123,7 @@ public void ArrangeText(
lines[i] = this.TextTrimmer.Trim(this.TextMeasurer, lines[i], bounds.Width, fontFamily, fontSize, fontWeight);
}
- if (this.SquashToBounds)
+ if (this.SquashTrimmedTextBounds)
{
bounds = new OxySize(lines.Max(l => this.TextMeasurer.MeasureTextWidth(l, fontFamily, fontSize, fontWeight)), bounds.Height);
}
@@ -166,7 +166,7 @@ public void ArrangeText(
linePositions = new ScreenPoint[lines.Length];
for (int i = 0; i < lines.Length; i++)
{
- var line = lines[i];
+ var line = lines[i];
var lineWidth = this.TextMeasurer.MeasureTextWidth(line, fontFamily, fontSize, fontWeight);
var offsetLineWidth = new ScreenVector(cos * lineWidth, sin * lineWidth);
@@ -208,7 +208,7 @@ public OxySize MeasureText(
var leading = metrics.Leading;
var lineCount = lines.Length;
- var height = (lineHeight + leading) * lineCount - leading;
+ var height = ((lineHeight + leading) * lineCount) - leading;
return new OxySize(width, height);
}
diff --git a/Source/OxyPlot/Svg/SvgRenderContext.cs b/Source/OxyPlot/Svg/SvgRenderContext.cs
index 83cc56f45..0b9043f3b 100644
--- a/Source/OxyPlot/Svg/SvgRenderContext.cs
+++ b/Source/OxyPlot/Svg/SvgRenderContext.cs
@@ -9,10 +9,10 @@
namespace OxyPlot
{
- using OxyPlot.Rendering;
using System;
using System.Collections.Generic;
using System.IO;
+ using OxyPlot.Rendering;
///
/// Provides a render context for scalable vector graphics output.
@@ -234,7 +234,7 @@ public override void DrawImage(
}
///
- /// Releases unmanaged and - optionally - managed resources
+ /// Releases unmanaged and - optionally - managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)