using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; using RealTimeGraphX.EventArguments; using RealTimeGraphX.WPF.DataSeries; namespace RealTimeGraphX.WPF.Painters { /// /// Represents a WPF implementation for . /// This painter provides a graph image of type . /// /// /// public class WpfScrollingGraphPainter : GraphPainterBase { private WriteableBitmap _writeable_bitmap; private Bitmap _gdi_bitmap; private Graphics g; /// /// Gets the current graph image. /// public override BitmapSource Image { get; protected set; } /// /// Called when the connected input invoked the method. /// /// The series to draw. /// The points to draw. /// Specifies whether there is a need to reinitialize the image because surface size change. protected override void OnDraw(IEnumerable seriesCollection, WpfDataSeries series, IEnumerable points, bool sizeChanged) { if (sizeChanged) { if (g != null) { g.Dispose(); } _writeable_bitmap = new WriteableBitmap((int)Math.Max(Output.SurfaceWidth, 1), (int)Math.Max(Output.SurfaceHeight, 1), 96.0, 96.0, PixelFormats.Pbgra32, null); if (_gdi_bitmap != null) { _gdi_bitmap.Dispose(); } _gdi_bitmap = new Bitmap(_writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight, _writeable_bitmap.BackBufferStride, System.Drawing.Imaging.PixelFormat.Format32bppPArgb, _writeable_bitmap.BackBuffer); _writeable_bitmap.Lock(); } bool isFirst = series == seriesCollection.First(); bool isLast = series == seriesCollection.Last(); if (isFirst) { if (!sizeChanged) { _writeable_bitmap.Lock(); } g = Graphics.FromImage(_gdi_bitmap); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.Clear(System.Drawing.Color.Transparent); //Apply zooming. if (ZoomRect.Width > 0 && ZoomRect.Height > 0) { var scale_x = (float)(Output.SurfaceWidth / ZoomRect.Width); var scale_y = (float)(Output.SurfaceHeight / ZoomRect.Height); var translate_x = (float)-ZoomRect.Left * scale_x; var translate_y = (float)-ZoomRect.Top * scale_y; g.TranslateTransform(translate_x, translate_y); g.ScaleTransform(scale_x, scale_y); if (scale_x != Transform.ScaleX || scale_y != Transform.ScaleY || translate_x != Transform.TranslateX || translate_y != Transform.TranslateY) { OnTransformChanged(new TransformChangedEventArgs() { Transform = new GraphTransform() { ScaleX = scale_x, ScaleY = scale_y, TranslateX = translate_x, TranslateY = translate_y, } }); OnVirtualRangeXChanged(); OnVirtualRangeYChanged(); } } } OnDraw(seriesCollection, series, points, g); if (isLast) { _writeable_bitmap.AddDirtyRect(new Int32Rect(0, 0, _writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight)); _writeable_bitmap.Unlock(); var cloned = _writeable_bitmap.Clone(); cloned.Freeze(); OnPaintingCompleted(cloned); g.Dispose(); } } /// /// Called when the connected input invoked the method. /// /// The series collection. /// The series. /// The points. /// The graphics object. protected virtual void OnDraw(IEnumerable seriesCollection, WpfDataSeries series, IEnumerable points, Graphics g) { if (SurfaceWidth > 10 && SurfaceHeight > 10) { System.Drawing.Pen pen = new System.Drawing.Pen(series.GdiStroke, (float)series.StrokeThickness); List gdiPoints = points.Select(x => new PointF((float)x.X, (float)x.Y)).ToList(); if (series.GdiFill != null) { if (series.GdiFill is System.Drawing.Drawing2D.LinearGradientBrush) { var gradient = (series.GdiFill as System.Drawing.Drawing2D.LinearGradientBrush); gradient.ResetTransform(); gradient.ScaleTransform((float)(Output.SurfaceWidth / gradient.Rectangle.Width), (float)(Output.SurfaceHeight / gradient.Rectangle.Height)); } g.FillPolygon(series.GdiFill, GetFillPoints(gdiPoints)); } try { g.DrawCurve(pen, gdiPoints.ToArray()); } catch { } pen.Dispose(); } } /// /// Gets a closed polygon version of the specified points to use with FillPolygon(). /// /// The points. /// protected virtual PointF[] GetFillPoints(List points) { List closed = points.ToList(); closed.Add(new PointF(points.Last().X, (float)SurfaceWidth)); closed.Add(new PointF(0, (float)SurfaceHeight)); return closed.ToArray(); } } }