2019-09-15 16:21:56 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.Drawing.Drawing2D;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
|
|
|
|
namespace Base
|
|
|
|
|
{
|
2019-10-05 17:49:56 +02:00
|
|
|
|
public sealed class GraphicsWrapper : IDisposable
|
2019-09-15 16:21:56 +02:00
|
|
|
|
{
|
2019-09-26 20:44:45 +02:00
|
|
|
|
BufferedGraphics _g;
|
2019-09-26 22:24:45 +02:00
|
|
|
|
Color backColor;
|
|
|
|
|
Rectangle targetSize;
|
2019-09-26 20:44:45 +02:00
|
|
|
|
public readonly Graphics g;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Wrap the Graphics object with these excellent High-Quality functions
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="g">The Graphics-object to wrap</param>
|
2019-10-05 16:12:18 +02:00
|
|
|
|
/// <param name="backColor">Color used when filling</param>
|
2019-09-26 20:44:45 +02:00
|
|
|
|
/// <param name="targetSize">The size of the device the Graphics are drawn to</param>
|
2019-10-05 16:12:18 +02:00
|
|
|
|
/// <param name="isLowQuality">Whether the quality should be ugly</param>
|
|
|
|
|
public GraphicsWrapper(Graphics g, Color backColor, Rectangle targetSize, bool isLowQuality = false)
|
2019-09-26 20:44:45 +02:00
|
|
|
|
{
|
|
|
|
|
_g = BufferedGraphicsManager.Current.Allocate(g ?? throw new ArgumentNullException(nameof(g)), targetSize);
|
|
|
|
|
this.g = _g.Graphics;
|
2019-09-26 22:24:45 +02:00
|
|
|
|
this.backColor = backColor;
|
|
|
|
|
this.targetSize = targetSize;
|
2019-10-05 16:12:18 +02:00
|
|
|
|
this.g.SmoothingMode = isLowQuality ? SmoothingMode.None : SmoothingMode.HighQuality;
|
|
|
|
|
this.g.InterpolationMode = isLowQuality ? InterpolationMode.Low : InterpolationMode.HighQualityBicubic;
|
|
|
|
|
this.g.CompositingMode = isLowQuality ? CompositingMode.SourceCopy : CompositingMode.SourceOver;
|
|
|
|
|
this.g.CompositingQuality = isLowQuality ? CompositingQuality.HighSpeed : CompositingQuality.HighQuality;
|
|
|
|
|
this.g.PixelOffsetMode = isLowQuality ? PixelOffsetMode.None : PixelOffsetMode.HighQuality;
|
2019-09-26 20:44:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-19 18:51:31 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draw a string with the given size
|
|
|
|
|
/// </summary>
|
2019-10-07 17:26:55 +02:00
|
|
|
|
/// <param name="text">The string to draw</param>
|
2019-09-19 18:51:31 +02:00
|
|
|
|
/// <param name="size">The font size of the string</param>
|
|
|
|
|
/// <param name="location">The location to draw the string at</param>
|
|
|
|
|
/// <param name="brush">The brush to draw the string with</param>
|
2019-10-07 17:26:55 +02:00
|
|
|
|
/// <param name="centered">Set to true if you want to draw the string around instead of left-down from the location</param>
|
|
|
|
|
public void DrawSizedString(string text, int size, PointF location, Brush brush, bool transform = true, bool centered = false)
|
2019-09-15 16:21:56 +02:00
|
|
|
|
{
|
|
|
|
|
SmoothingMode tmpS = g.SmoothingMode;
|
|
|
|
|
InterpolationMode tmpI = g.InterpolationMode;
|
2019-10-05 16:12:18 +02:00
|
|
|
|
CompositingMode tmpM = g.CompositingMode;
|
|
|
|
|
CompositingQuality tmpQ = g.CompositingQuality;
|
2019-09-15 16:21:56 +02:00
|
|
|
|
PixelOffsetMode tmpP = g.PixelOffsetMode;
|
|
|
|
|
g.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
|
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
2019-10-05 16:12:18 +02:00
|
|
|
|
g.CompositingMode = CompositingMode.SourceOver;
|
|
|
|
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
2019-09-15 16:21:56 +02:00
|
|
|
|
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
2019-10-05 16:12:18 +02:00
|
|
|
|
Font f = new Font("Tahoma", size);
|
2019-10-07 17:26:55 +02:00
|
|
|
|
SizeF s = g.MeasureString(text, f);
|
|
|
|
|
RectangleF r = new RectangleF(centered ? new PointF(location.X - s.Width / 2, location.Y - s.Height / 2) : location, s);
|
2019-09-26 22:24:45 +02:00
|
|
|
|
if (transform)
|
2019-10-07 17:26:55 +02:00
|
|
|
|
r = w2s(r);
|
|
|
|
|
g.DrawString(text, f, brush, r);
|
2019-09-15 16:21:56 +02:00
|
|
|
|
g.PixelOffsetMode = tmpP;
|
2019-10-05 16:12:18 +02:00
|
|
|
|
g.CompositingQuality = tmpQ;
|
|
|
|
|
g.CompositingMode = tmpM;
|
2019-09-15 16:21:56 +02:00
|
|
|
|
g.InterpolationMode = tmpI;
|
|
|
|
|
g.SmoothingMode = tmpS;
|
|
|
|
|
}
|
2019-09-26 20:44:45 +02:00
|
|
|
|
|
2019-09-26 22:24:45 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws a rectangle
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="rectangle">Use the PointF/SizeF Constructor as it is much more logical</param>
|
|
|
|
|
/// <param name="color">The color of the rectangle</param>
|
|
|
|
|
/// <param name="centered">Whether the rectangle should be drawn centered rather than down-left</param>
|
|
|
|
|
/// <param name="filled">Whether the rectangle should be filled</param>
|
|
|
|
|
/// <param name="unfilledLineSize">The size of the lines used when not filling</param>
|
2019-10-06 17:13:10 +02:00
|
|
|
|
public void DrawRectangle(RectangleF rectangle, Color color, bool centered = true, bool transform = true, bool filled = true, float unfilledLineSize = 1)
|
2019-09-26 22:24:45 +02:00
|
|
|
|
{
|
2019-10-07 17:26:55 +02:00
|
|
|
|
SizeF s = rectangle.Size;
|
|
|
|
|
PointF location = rectangle.Location;
|
|
|
|
|
RectangleF r = new RectangleF(centered ? new PointF(location.X - s.Width / 2, location.Y - s.Height / 2) : location, s);
|
2019-09-26 22:24:45 +02:00
|
|
|
|
if (transform)
|
|
|
|
|
r = w2s(r);
|
|
|
|
|
Brush b = new SolidBrush(color);
|
|
|
|
|
if (filled)
|
|
|
|
|
g.FillRectangle(b, r);
|
|
|
|
|
else
|
|
|
|
|
g.DrawRectangle(new Pen(b, unfilledLineSize), new Rectangle(Misc.f2i(r.X), Misc.f2i(r.Y), Misc.f2i(r.Width), Misc.f2i(r.Height)));
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-27 08:59:21 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws a rectangle
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="rectangle">The rectangle to be drawn</param>
|
|
|
|
|
/// <param name="color">The color of the rectangle</param>
|
|
|
|
|
/// <param name="filled">Whether the rectangle should be filled</param>
|
|
|
|
|
/// <param name="unfilledLineSize">The size of the lines used when not filling</param>
|
2019-10-06 17:13:10 +02:00
|
|
|
|
public void DrawRectangle(Rect rectangle, Color color, bool filled = true, float unfilledLineSize = 1) => DrawRectangle(rectangle.toRectangleF(), color, false, true, filled, unfilledLineSize);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws an ellipse
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="rectangle">Use the PointF/SizeF Constructor as it is much more logical</param>
|
|
|
|
|
/// <param name="color">The color of the ellipse</param>
|
|
|
|
|
/// <param name="centered">Whether the ellipse should be drawn centered rather than down-left</param>
|
|
|
|
|
/// <param name="filled">Whether the ellipse should be filled</param>
|
|
|
|
|
/// <param name="unfilledLineSize">The size of the lines used when not filling</param>
|
|
|
|
|
public void DrawEllipse(RectangleF rectangle, Color color, bool centered = true, bool transform = true, bool filled = true, float unfilledLineSize = 1)
|
|
|
|
|
{
|
|
|
|
|
RectangleF r = rectangle;
|
|
|
|
|
if (transform)
|
|
|
|
|
r = w2s(r);
|
|
|
|
|
Brush b = new SolidBrush(color);
|
|
|
|
|
if (centered)
|
|
|
|
|
{
|
|
|
|
|
r = new RectangleF(new PointF(r.X - r.Width / 2, r.Y - r.Height / 2), r.Size);
|
|
|
|
|
}
|
|
|
|
|
if (filled)
|
|
|
|
|
g.FillEllipse(b, r);
|
|
|
|
|
else
|
|
|
|
|
g.DrawEllipse(new Pen(b, unfilledLineSize), new Rectangle(Misc.f2i(r.X), Misc.f2i(r.Y), Misc.f2i(r.Width), Misc.f2i(r.Height)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draws a ellipse
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="rectangle">The rectangle to draw the ellipse in</param>
|
|
|
|
|
/// <param name="color">The color of the ellipse</param>
|
|
|
|
|
/// <param name="filled">Whether the ellipse should be filled</param>
|
|
|
|
|
/// <param name="unfilledLineSize">The size of the lines used when not filling</param>
|
|
|
|
|
public void DrawEllipse(Rect rectangle, Color color, bool filled = true, float unfilledLineSize = 1) => DrawEllipse(rectangle.toRectangleF(), color, false, true, filled, unfilledLineSize);
|
2019-09-27 08:59:21 +02:00
|
|
|
|
|
2019-10-05 16:12:18 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draw a line connecting the vectors
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="p1">Start of the line</param>
|
|
|
|
|
/// <param name="p2">End of the line</param>
|
|
|
|
|
/// <param name="color">Color to be used</param>
|
|
|
|
|
/// <param name="width">Width of the line in pixels</param>
|
|
|
|
|
public void DrawLine(Vector2 p1, Vector2 p2, Color color, float width, bool transform = true) => DrawLine(p1.toPointF(), p2.toPointF(), color, width, transform);
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Draw a line connecting the points
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="p1">Start of the line</param>
|
|
|
|
|
/// <param name="p2">End of the line</param>
|
|
|
|
|
/// <param name="color">Color to be used</param>
|
|
|
|
|
/// <param name="width">Width of the line in pixels</param>
|
|
|
|
|
public void DrawLine(PointF p1, PointF p2, Color color, float width, bool transform = true) => g.DrawLine(new Pen(color, width), transform ? w2s(p1) : p1, transform ? w2s(p2) : p2);
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Clear the screen with the color provided when creating
|
|
|
|
|
/// </summary>
|
2019-09-26 22:24:45 +02:00
|
|
|
|
public void Clear() => g.Clear(backColor);
|
|
|
|
|
|
2019-10-05 16:12:18 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Render and dispose
|
|
|
|
|
/// </summary>
|
2019-10-05 17:49:56 +02:00
|
|
|
|
public void Dispose()
|
2019-09-26 20:44:45 +02:00
|
|
|
|
{
|
|
|
|
|
g.Flush();
|
|
|
|
|
_g.Render();
|
|
|
|
|
g.Dispose();
|
|
|
|
|
_g.Dispose();
|
|
|
|
|
}
|
2019-09-26 22:24:45 +02:00
|
|
|
|
|
2019-10-07 17:26:55 +02:00
|
|
|
|
public RectangleF w2s(RectangleF from) => new RectangleF(w2s(new PointF(from.Left, from.Bottom)), from.Size);
|
2019-09-26 22:24:45 +02:00
|
|
|
|
public PointF w2s(PointF from) => new PointF(from.X, targetSize.Height - from.Y);
|
2019-09-15 16:21:56 +02:00
|
|
|
|
}
|
|
|
|
|
}
|