DotNet 4.8.1 build of DotNetBar
This commit is contained in:
@@ -0,0 +1,565 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Text;
|
||||
using DevComponents.DotNetBar.Charts.Style;
|
||||
|
||||
namespace DevComponents.DotNetBar.Charts
|
||||
{
|
||||
internal class PointMarker : IDisposable
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
private List<BitmapEntry> _Bitmaps = new List<BitmapEntry>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetMarkerBitmap
|
||||
|
||||
public Bitmap GetMarkerBitmap(Graphics g, PointMarkerType markerType, int markerPoints,
|
||||
Size size, int markerRotation, Background background, Color borderColor, int borderWidth)
|
||||
{
|
||||
if (markerType == PointMarkerType.None || markerType == PointMarkerType.NotSet)
|
||||
return (null);
|
||||
|
||||
if (markerType == PointMarkerType.Cross ||
|
||||
background == null || background.IsEmpty)
|
||||
{
|
||||
if (borderColor.IsEmpty)
|
||||
borderColor = Color.Black;
|
||||
}
|
||||
|
||||
// Add margin to permit better antialiasing of image
|
||||
|
||||
size.Width++;
|
||||
size.Height++;
|
||||
|
||||
Bitmap bitmap = null;
|
||||
|
||||
bitmap = FindBitmap(markerType, markerPoints,
|
||||
size, markerRotation, background, borderColor, borderWidth);
|
||||
|
||||
if (bitmap == null)
|
||||
{
|
||||
size.Width = Math.Max(size.Width, 3);
|
||||
size.Height = Math.Max(size.Height, 3);
|
||||
|
||||
Rectangle r = new Rectangle(Point.Empty, size);
|
||||
|
||||
using (GraphicsPath path =
|
||||
GetMarkerPath(markerType, markerPoints, markerRotation, r, borderWidth))
|
||||
{
|
||||
if (path != null)
|
||||
{
|
||||
bitmap = new Bitmap(size.Width, size.Height, g);
|
||||
|
||||
using (Graphics gBmp = Graphics.FromImage(bitmap))
|
||||
{
|
||||
gBmp.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
|
||||
FillMarkerPath(gBmp, path, r, markerType, background, borderColor, borderWidth);
|
||||
|
||||
if (markerRotation != 0 && markerRotation != -1)
|
||||
{
|
||||
Bitmap bitmap2 = RotatePic(bitmap, markerRotation);
|
||||
|
||||
bitmap.Dispose();
|
||||
|
||||
bitmap = bitmap2;
|
||||
}
|
||||
|
||||
_Bitmaps.Add(new BitmapEntry(markerType, size, markerPoints,
|
||||
markerRotation, background, borderColor, borderWidth, bitmap));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (bitmap);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FindBitmap
|
||||
|
||||
public Bitmap FindBitmap(PointMarkerType markerType, int markerPoints,
|
||||
Size size, int markerRotation, Background background, Color borderColor, int borderWidth)
|
||||
{
|
||||
foreach (BitmapEntry entry in _Bitmaps)
|
||||
{
|
||||
if (entry.MarkerType == markerType &&
|
||||
entry.MarkerPoints == markerPoints &&
|
||||
entry.MarkerRotation == markerRotation &&
|
||||
entry.MarkerSize.Equals(size) &&
|
||||
entry.BorderWidth == borderWidth &&
|
||||
entry.BorderColor.Equals(borderColor) &&
|
||||
entry.Background.IsEqualTo(background))
|
||||
{
|
||||
return (entry.Bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetMarkerPath
|
||||
|
||||
internal GraphicsPath GetMarkerPath( PointMarkerType markerType,
|
||||
int markerPoints, int markerRotation, Rectangle r, int borderWidth)
|
||||
{
|
||||
r.Inflate(-borderWidth, -borderWidth);
|
||||
|
||||
if (r.Width > 0 && r.Height > 0)
|
||||
{
|
||||
switch (markerType)
|
||||
{
|
||||
case PointMarkerType.Ellipse:
|
||||
return (GetCirclePath(r));
|
||||
|
||||
case PointMarkerType.Cross:
|
||||
return (GetCrossPath(r, markerPoints));
|
||||
|
||||
case PointMarkerType.Diamond:
|
||||
return (GetDiamondPath(r));
|
||||
|
||||
case PointMarkerType.Rectangle:
|
||||
return (GetRectanglePath(r));
|
||||
|
||||
case PointMarkerType.Star:
|
||||
return (GetStarPath(r, markerPoints));
|
||||
|
||||
case PointMarkerType.Triangle:
|
||||
return (GetTrianglePath(r));
|
||||
|
||||
default:
|
||||
return (GetPolygonPath(r, markerPoints));
|
||||
}
|
||||
}
|
||||
|
||||
return (null);
|
||||
}
|
||||
|
||||
#region GetCirclePath
|
||||
|
||||
private GraphicsPath GetCirclePath(Rectangle r)
|
||||
{
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
path.AddEllipse(r);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetCrossPath
|
||||
|
||||
private GraphicsPath GetCrossPath(Rectangle r, int points)
|
||||
{
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
PointF[] pts = new PointF[2 * points];
|
||||
|
||||
double rx1 = r.Width / 2;
|
||||
double ry1 = r.Height / 2;
|
||||
|
||||
if (rx1 < 2)
|
||||
rx1 = 2;
|
||||
|
||||
if (ry1 < 2)
|
||||
ry1 = 2;
|
||||
|
||||
double cx = r.X + rx1;
|
||||
double cy = r.Y + ry1;
|
||||
|
||||
double theta = MathHelper.ToRadians(270);
|
||||
double dtheta = Math.PI / points;
|
||||
|
||||
for (int i = 0; i < 2 * points; i += 2)
|
||||
{
|
||||
pts[i] = new PointF(
|
||||
(float)(cx + rx1 * Math.Cos(theta)),
|
||||
(float)(cy + ry1 * Math.Sin(theta)));
|
||||
|
||||
pts[i + 1] = new PointF((float)cx, (float)cy);
|
||||
|
||||
theta += (dtheta * 2);
|
||||
}
|
||||
|
||||
path.AddPolygon(pts);
|
||||
|
||||
path.CloseAllFigures();
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetDiamondPath
|
||||
|
||||
private GraphicsPath GetDiamondPath(Rectangle r)
|
||||
{
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
int dx = r.Width / 2;
|
||||
int dy = r.Height / 2;
|
||||
|
||||
int mx = r.X + dx;
|
||||
int my = r.Y + dy;
|
||||
|
||||
Point[] pts =
|
||||
{
|
||||
new Point(mx, my - dy),
|
||||
new Point(mx + dx, my),
|
||||
new Point(mx, my + dy),
|
||||
new Point(mx - dx, my),
|
||||
};
|
||||
|
||||
path.AddPolygon(pts);
|
||||
|
||||
path.CloseAllFigures();
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetPolygonPath
|
||||
|
||||
private GraphicsPath GetPolygonPath(Rectangle r, int sides)
|
||||
{
|
||||
if (sides <= 4)
|
||||
return (GetRectanglePath(r));
|
||||
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
int radius = Math.Min(r.Width, r.Height);
|
||||
|
||||
float dx = (float)radius / 2;
|
||||
float radians = (float)MathHelper.ToRadians(270);
|
||||
float delta = (float)MathHelper.ToRadians((float)360 / sides);
|
||||
|
||||
Point[] pts = new Point[sides];
|
||||
|
||||
for (int i = 0; i < sides; i++)
|
||||
{
|
||||
pts[i] = new Point(
|
||||
(int)(dx * Math.Cos(radians) + dx + r.X),
|
||||
(int)(dx * Math.Sin(radians) + dx + r.Y));
|
||||
|
||||
radians += delta;
|
||||
}
|
||||
|
||||
path.AddPolygon(pts);
|
||||
|
||||
path.CloseAllFigures();
|
||||
|
||||
if (r.Width != r.Height)
|
||||
{
|
||||
PointF[] dp =
|
||||
{
|
||||
new PointF(0, 0),
|
||||
new PointF(r.Width, 0),
|
||||
new PointF(0, r.Height),
|
||||
};
|
||||
|
||||
path.Warp(dp, new RectangleF(0, 0, radius, radius));
|
||||
}
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetRectanglePath
|
||||
|
||||
private GraphicsPath GetRectanglePath(Rectangle r)
|
||||
{
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
path.AddRectangle(r);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetStarPath
|
||||
|
||||
private GraphicsPath GetStarPath(Rectangle r, int points)
|
||||
{
|
||||
if (points < 2)
|
||||
points = 2;
|
||||
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
PointF[] pts = new PointF[2 * points];
|
||||
|
||||
double rx1 = r.Width / 2;
|
||||
double ry1 = r.Height / 2;
|
||||
|
||||
if (rx1 < 2)
|
||||
rx1 = 2;
|
||||
|
||||
if (ry1 < 2)
|
||||
ry1 = 2;
|
||||
|
||||
double rx2 = rx1 / 2;
|
||||
double ry2 = ry1 / 2;
|
||||
|
||||
double cx = r.X + rx1;
|
||||
double cy = r.Y + ry1;
|
||||
|
||||
double theta = MathHelper.ToRadians(270);
|
||||
double dtheta = Math.PI / points;
|
||||
|
||||
for (int i = 0; i < 2 * points; i += 2)
|
||||
{
|
||||
pts[i] = new PointF(
|
||||
(float)(cx + rx1 * Math.Cos(theta)),
|
||||
(float)(cy + ry1 * Math.Sin(theta)));
|
||||
|
||||
theta += dtheta;
|
||||
|
||||
pts[i + 1] = new PointF(
|
||||
(float)(cx + rx2 * Math.Cos(theta)),
|
||||
(float)(cy + ry2 * Math.Sin(theta)));
|
||||
|
||||
theta += dtheta;
|
||||
}
|
||||
|
||||
path.AddPolygon(pts);
|
||||
|
||||
path.CloseAllFigures();
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetTrianglePath
|
||||
|
||||
private GraphicsPath GetTrianglePath(Rectangle r)
|
||||
{
|
||||
// Equal height and width will not be adjusted to make
|
||||
// an equalaterial triangle - thus rotation will skew image.
|
||||
|
||||
GraphicsPath path = new GraphicsPath();
|
||||
|
||||
int dx = r.Width / 2;
|
||||
int dy = r.Height / 2;
|
||||
|
||||
Point[] pts = {
|
||||
new Point(r.X + dx, r.Y),
|
||||
new Point(r.X , r.Y + dy * 2),
|
||||
new Point(r.X + dx * 2, r.Y + dy * 2),
|
||||
};
|
||||
|
||||
path.AddPolygon(pts);
|
||||
|
||||
path.CloseAllFigures();
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region FillMarkerPath
|
||||
|
||||
internal void FillMarkerPath(Graphics g, GraphicsPath path, Rectangle r,
|
||||
PointMarkerType markerType, Background background, Color borderColor, int borderWidth)
|
||||
{
|
||||
if (markerType != PointMarkerType.Cross)
|
||||
{
|
||||
BackFillType fillType = GetMarkerFillType(markerType, background);
|
||||
|
||||
using (Brush br = background.GetBrush(r, -1, fillType))
|
||||
g.FillPath(br, path);
|
||||
}
|
||||
|
||||
if (borderColor.IsEmpty == false && borderWidth > 0)
|
||||
{
|
||||
using (Pen pen = new Pen(borderColor, borderWidth))
|
||||
g.DrawPath(pen, path);
|
||||
}
|
||||
}
|
||||
|
||||
#region GetMarkerFillType
|
||||
|
||||
private BackFillType GetMarkerFillType(PointMarkerType markerType, Background background)
|
||||
{
|
||||
if (background.Color2.IsEmpty == true)
|
||||
return (BackFillType.None);
|
||||
|
||||
if (background.BackFillType == BackFillType.Auto)
|
||||
{
|
||||
switch (markerType)
|
||||
{
|
||||
case PointMarkerType.Ellipse:
|
||||
case PointMarkerType.Star:
|
||||
return (BackFillType.Center);
|
||||
|
||||
default:
|
||||
return (BackFillType.VerticalCenter);
|
||||
}
|
||||
}
|
||||
|
||||
return (background.BackFillType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region RotatePic
|
||||
|
||||
private Bitmap RotatePic(Bitmap obmp, float angle)
|
||||
{
|
||||
float rad = (float)MathHelper.ToRadians(angle);
|
||||
|
||||
double fW = Math.Abs((Math.Cos(rad) * obmp.Width)) + Math.Abs((Math.Sin(rad) * obmp.Height));
|
||||
double fH = Math.Abs((Math.Sin(rad) * obmp.Width)) + Math.Abs((Math.Cos(rad) * obmp.Height));
|
||||
|
||||
Bitmap nbmp = new Bitmap((int)Math.Ceiling(fW), (int)Math.Ceiling(fH));
|
||||
|
||||
using (Graphics g = Graphics.FromImage(nbmp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
|
||||
float hw = nbmp.Width / 2f;
|
||||
float hh = nbmp.Height / 2f;
|
||||
|
||||
Matrix m = g.Transform;
|
||||
|
||||
m.RotateAt(angle, new PointF(hw, hh), MatrixOrder.Append);
|
||||
|
||||
g.Transform = m;
|
||||
|
||||
g.DrawImage(obmp, new PointF((float)((nbmp.Width - obmp.Width) / 2), (float)((nbmp.Height - obmp.Height) / 2)));
|
||||
}
|
||||
|
||||
return nbmp;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clear
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (BitmapEntry entry in _Bitmaps)
|
||||
{
|
||||
entry.Background.Dispose();
|
||||
entry.Bitmap.Dispose();
|
||||
}
|
||||
|
||||
_Bitmaps.Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BitmapEntry
|
||||
|
||||
private class BitmapEntry
|
||||
{
|
||||
public PointMarkerType MarkerType;
|
||||
public Size MarkerSize;
|
||||
public int MarkerPoints;
|
||||
public int MarkerRotation;
|
||||
|
||||
public Background Background;
|
||||
public Color BorderColor;
|
||||
public int BorderWidth;
|
||||
|
||||
public Bitmap Bitmap;
|
||||
|
||||
public BitmapEntry(PointMarkerType markerType, Size markerSize, int markerPoints,
|
||||
int markerRotation, Background background, Color borderColor, int borderWidth, Bitmap bitmap)
|
||||
{
|
||||
MarkerType = markerType;
|
||||
MarkerSize = markerSize;
|
||||
MarkerPoints = markerPoints;
|
||||
MarkerRotation = markerRotation;
|
||||
|
||||
Background = background.Copy();
|
||||
BorderColor = borderColor;
|
||||
BorderWidth = borderWidth;
|
||||
|
||||
Bitmap = bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region enums
|
||||
|
||||
#region PointMarkerType
|
||||
|
||||
public enum PointMarkerType
|
||||
{
|
||||
/// <summary>
|
||||
/// Type not set.
|
||||
/// </summary>
|
||||
NotSet = -1,
|
||||
|
||||
/// <summary>
|
||||
/// No Marker
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Cross
|
||||
/// </summary>
|
||||
Cross,
|
||||
|
||||
/// <summary>
|
||||
/// Diamond
|
||||
/// </summary>
|
||||
Diamond,
|
||||
|
||||
/// <summary>
|
||||
/// Ellipse
|
||||
/// </summary>
|
||||
Ellipse,
|
||||
|
||||
/// <summary>
|
||||
/// Polygon (Pentagon, Hexagon, etc)
|
||||
/// </summary>
|
||||
Polygon,
|
||||
|
||||
/// <summary>
|
||||
/// Rectangle
|
||||
/// </summary>
|
||||
Rectangle,
|
||||
|
||||
/// <summary>
|
||||
/// Star
|
||||
/// </summary>
|
||||
Star,
|
||||
|
||||
/// <summary>
|
||||
/// Triangle
|
||||
/// </summary>
|
||||
Triangle,
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
Reference in New Issue
Block a user