public void Equals_ShouldNotBeEqual() { var rectA = new BasicRectangle(0, 50, 100, 150); var rectB = new BasicRectangle(50, 100, 150, 200); Assert.IsFalse(rectA.Equals(rectB)); }
public void DrawImage(BasicRectangle rectangleDestination, BasicRectangle rectangleSource, IDisposable image) { // Make sure the source rectangle width isn't out of bounds var disposableImage = (DisposableBitmap)image; var croppedBitmap = new CroppedBitmap(disposableImage.Bitmap, GenericControlHelper.ToInt32Rect(rectangleSource)); _context.DrawImage(croppedBitmap, GenericControlHelper.ToRect(rectangleDestination)); }
public GraphicsContextWrapper(CGContext context, float boundsWidth, float boundsHeight, BasicRectangle dirtyRect) { Context = context; BoundsWidth = boundsWidth; BoundsHeight = boundsHeight; DirtyRect = dirtyRect; }
public void Equals_ShouldBeEqual() { var rectA = new BasicRectangle(0, 50, 100, 150); var rectB = new BasicRectangle(0, 50, 100, 150); Assert.IsTrue(rectA.Equals(rectB)); }
public GraphicsContextWrapper(Canvas canvas, float boundsWidth, float boundsHeight, float density, BasicRectangle dirtyRect) { _canvas = canvas; DirtyRect = dirtyRect; BoundsWidth = boundsWidth; BoundsHeight = boundsHeight; Density = density; }
public void Merge(BasicRectangle rect) { var mergedRect = BasicRectangle.Merge(this, rect); this.X = mergedRect.X; this.Y = mergedRect.Y; this.Width = mergedRect.Width; this.Height = mergedRect.Height; }
public GraphicsContextWrapper(CGContext context, float boundsWidth, float boundsHeight, BasicRectangle dirtyRect) { Context = context; BoundsWidth = boundsWidth; BoundsHeight = boundsHeight; DirtyRect = dirtyRect; Density = GetDisplayScale(); }
protected override void OnRender(DrawingContext dc) { base.OnRender(dc); // TODO: Fix this, dirty rects in WPF is still a mystery. It was simple in WinForms, why is it hidden in WPF? var dirtyRect = new BasicRectangle(0, 0, (float)ActualWidth, (float)ActualHeight); var wrapper = new GraphicsContextWrapper(dc, (float)ActualWidth, (float)ActualHeight, dirtyRect); _control.Render(wrapper); }
public GraphicsContextWrapper(DrawingContext context, float boundsWidth, float boundsHeight, BasicRectangle dirtyRect) { _context = context; BoundsWidth = boundsWidth; BoundsHeight = boundsHeight; DirtyRect = dirtyRect; using (var g = System.Drawing.Graphics.FromHwnd(IntPtr.Zero)) Density = g.DpiX/96f; }
public static BasicRectangle Merge(BasicRectangle rectA, BasicRectangle rectB) { var mergedRect = new BasicRectangle(); mergedRect.X = Math.Min(rectA.X, rectB.X); mergedRect.Y = Math.Min(rectA.Y, rectB.Y); mergedRect.Width = Math.Max(rectA.Right, rectB.Right) - mergedRect.X; mergedRect.Height = Math.Max(rectA.Bottom, rectB.Bottom) - mergedRect.Y; return mergedRect; }
public void DrawImage(BasicRectangle rectangleDestination, BasicRectangle rectangleSource, IDisposable image) { //Console.WriteLine("GraphicsContextWrapper - DrawImage - rectangleDestination: {0} rectangleSource: {1}", rectangleDestination, rectangleSource); var bitmap = image as NSImage; if (bitmap == null) return; bitmap.Draw(GenericControlHelper.ToRect(rectangleDestination), GenericControlHelper.ToRect(rectangleSource), NSCompositingOperation.SourceOver, 1, true, new NSDictionary()); }
public void Center_ShouldBeCentered() { float size = 200; var rect = new BasicRectangle(0, 0, size, size); var point = rect.Center(); Assert.AreEqual(point.X, size / 2f); Assert.AreEqual(point.Y, size / 2f); }
private void Initialize() { Frame = new BasicRectangle(); _timerRefresh = new Timer(); _timerRefresh.Interval = 50; _timerRefresh.Elapsed += HandleTimerRefreshElapsed; CreateDrawingResources(); }
public bool CheckIfTileIsInBounds(int tileSize, float zoom, BasicRectangle bounds) { float deltaZoom = zoom / Zoom; float tileWidth = tileSize*deltaZoom; //float offsetX = GetAdjustedContentOffsetForZoom(x, tileSize, zoom); //float offsetX = x; float offsetX = ContentOffset.X*deltaZoom; //Console.WriteLine("WaveFormTile - CheckIfTileIsInBounds - offsetX: {0} tileWidth: {1} tileZoom: {2} bounds: {3} zoom: {4}", offsetX, tileWidth, Zoom, bounds, zoom); //return offsetX >= bounds.X && offsetX + tileWidth <= bounds.X + bounds.Width; return offsetX <= bounds.X && offsetX + tileWidth >= bounds.X + bounds.Width; }
public List<WaveFormTile> GetTiles(WaveFormBitmapRequest request) { if (request.Zoom != _lastZoom && request.Zoom > 1) { lock (_lockerCache) { // Bug: when requesting the smaller tiles, the zoom changes //Console.WriteLine("WaveFormCacheService - Zoom has changed - lastZoom: {0} zoom: {1}", _lastZoom, request.Zoom); _lastZoom = request.Zoom; _tileCacheForZoom.Clear(); } } //float coveredAreaX = 0; float zoomThreshold = (float)Math.Floor(request.Zoom); var boundsWaveFormAdjusted = new BasicRectangle(0, 0, request.BoundsWaveForm.Width * zoomThreshold, request.BoundsWaveForm.Height); var tiles = new List<WaveFormTile>(); //List<WaveFormTile> previouslyAvailableTiles = new List<WaveFormTile>(); for (int a = request.StartTile; a < request.EndTile; a++) { WaveFormTile tile = null; float tileX = a * request.TileSize; // Add lock for cache WaveFormTile cachedTile = null; lock (_lockerCache) { if(request.IsScrollBar) cachedTile = _tileCacheForScrollBar.FirstOrDefault(x => x.ContentOffset.X == tileX); else cachedTile = _tileCacheForZoom.FirstOrDefault(x => x.ContentOffset.X == tileX); } if (cachedTile != null) { //Console.WriteLine(">>>>>>>>>> Taking cached tile!"); tile = cachedTile; } else { // This is a hot line, and needs to be avoided as much as possible. // the problem is that tiles vary in time in quality. // maybe as a first, when a tile at the right zoom is available, cache it locally so it isn't necessary to call the algo again. var availableTiles = GetAvailableTilesForPosition(tileX, request.Zoom); var boundsBitmap = new BasicRectangle(tileX, 0, TileSize, request.BoundsWaveForm.Height); if (availableTiles != null && availableTiles.Count > 0) { // TEMP: Add every tile for zoom == 100% (TESTING) -- This fixes the empty areas and proves the coveredAreaX technique doesn't work. var tileLowRes = availableTiles.FirstOrDefault(x => x.Zoom == 1); if (tileLowRes != null && !tiles.Contains(tileLowRes)) tiles.Add(tileLowRes); // Get the tile with the zoom that is the closest to the current zoom threshold tile = GetOptimalTileAtZoom(availableTiles, zoomThreshold); // If we could not find a tile at this zoom level, we need to generate one if (tile.Zoom != zoomThreshold) { //Console.WriteLine("WaveFormCacheService - Requesting a new bitmap (zoom doesn't match) - zoomThreshold: {0} tile.Zoom: {1} boundsBitmap: {2} boundsWaveForm: {3}", zoomThreshold, tile.Zoom, boundsBitmap, request.BoundsWaveForm); AddBitmapRequestToList(boundsBitmap, boundsWaveFormAdjusted, zoomThreshold, request.DisplayType); } else { lock (_lockerCache) { _tileCacheForZoom.Add(tile); } } } else { // We need to request a new bitmap at this zoom threshold because there are no bitmaps available (usually zoom @ 100%) //Console.WriteLine("WaveFormCacheService - Requesting a new bitmap - zoom: {0} zoomThreshold: {1} boundsWaveForm: {2}", zoomThreshold, boundsBitmap, request.BoundsWaveForm); AddBitmapRequestToList(boundsBitmap, boundsWaveFormAdjusted, zoomThreshold, request.DisplayType); } } //Console.WriteLine("WaveFormCacheService - GetTiles - tile {0} x: {1} Zoom: {2} // tileFound: {3} tile.X: {4} tile.Zoom: {5}", a, tileX, zoom, tile == null, tile != null ? tile.ContentOffset.X : -1, tile != null ? tile.Zoom : -1); if (tile != null) { // Calculate the new covered area (adjusted with the zoom delta) //float currentTileDeltaZoom = request.Zoom/tile.Zoom; //float currentTileX = tile.ContentOffset.X*currentTileDeltaZoom; //float currentTileWidth = request.TileSize*currentTileDeltaZoom; //// Check if the new tile leaves an empty area behind //if (coveredAreaX < tile.ContentOffset.X) //{ // //Console.WriteLine("[...] WaveFormCacheService - GetTiles - An empty area has been found - coveredAreaX: {0} tile.ContentOffset.X: {1}", coveredAreaX, currentTileX); // //var tilesToFillEmptyArea = GetAvailableTilesToFillBounds(tileX, zoom, new BasicRectangle(coveredAreaX, 0, tile.ContentOffset.X - coveredAreaX, boundsWaveForm.Height)); // var tilesToFillEmptyArea = GetAvailableTilesToFillBounds(zoom, new BasicRectangle(coveredAreaX, 0, tile.ContentOffset.X - coveredAreaX, boundsWaveForm.Height)); // //Console.WriteLine("[...] $$$$$$$$$$$$ WaveFormCacheService - GetTiles - tilesToFillEmptyArea.Count: {0}", tilesToFillEmptyArea.Count); // //foreach (var daTile in tilesToFillEmptyArea) // // Console.WriteLine(" .....>>>>>> tile.ContentOffset.X: {0} tile.Zoom: {1}", daTile.ContentOffset.X, daTile.Zoom); // // Go through previously available tiles to find a tile to cover the empty area. // // This should return at least one tile (there should always be one around at zoom=100% except for the initial loading) // WaveFormTile tileToCoverEmptyArea = null; // //foreach (var previouslyAvailableTile in previouslyAvailableTiles) // //{ // // float previousTileDeltaZoom = zoom/previouslyAvailableTile.Zoom; // // float previousTileX = previouslyAvailableTile.ContentOffset.X * previousTileDeltaZoom; // // float previousTileWidth = tileSize * previousTileDeltaZoom; // // if (previousTileX < coveredAreaX && // // previousTileX + previousTileWidth >= currentTileX) // // { // // tileToCoverEmptyArea = previouslyAvailableTile; // // Console.WriteLine("[...] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WaveFormCacheService - GetTiles - ==> A tile has been found to cover the empty area - tileToCover.ContentOffset.X: {0} tileWidth: {1} tile.Zoom: {2}", previousTileX, previousTileWidth, tileToCoverEmptyArea.Zoom); // // break; // // } // //} // //tileToCoverEmptyArea = tilesToFillEmptyArea.OrderByDescending(x => x.Zoom).FirstOrDefault(); // tileToCoverEmptyArea = tilesToFillEmptyArea.FirstOrDefault(x => x.Zoom == 1); // // We found a tile to cover the area. If not, this should be only when refreshing the wave form for the first time @ 100% // if (tileToCoverEmptyArea != null) // { // Console.WriteLine("---> Adding tile to fill empty - tile.X: {0} tile.Zoom: {1} -- {2}", tileToCoverEmptyArea.ContentOffset.X, tileToCoverEmptyArea.Zoom, DateTime.Now); // tiles.Add(tileToCoverEmptyArea); // } // else // { // // The problem is that there are sometimes a tile could not be found the previous list... is that really a good source of info? // // maybe try the previous list and if not, fall back to the 100% zoom. // // or actually make a linq query similar to the one with adjusted content offset x. // Console.WriteLine("[!!!] WARNING: WaveFormCacheService - GetTiles - An empty area could not be filled by a tile!"); // } //} // Update the covered area position after trying to fill any empty areas left behind // Note: There are still empty areas, this might not be the best way to make sure areas are all filled... //coveredAreaX = currentTileX + currentTileWidth; // Keep the available tiles from the last index so we can search through this list to cover an empty area if needed //previouslyAvailableTiles = availableTiles; // Add tile to list of tiles to draw (TO DO: Check for existing tiles with the same zoom + offset if(!tiles.Contains(tile)) tiles.Add(tile); } } // Order tiles by zoom and then by content offset x; this makes sure that the tiles with the nearest zoom level get drawn on top of farther zoom levels // maybe replace this linq query by inserting the tiles in the list in the right order (at tiles.Add(tile) just up from here) // Also use Distinct to prevent drawing the same tile multiple times // B U G: This might crash if a tile is removed from the list.... var tilesOrdered = tiles.OrderBy(obj => obj.Zoom).ThenBy(obj => obj.ContentOffset.X).ToList(); return tilesOrdered; }
public void Render(IGraphicsContext context) { // Value range is the size between max and min track bar value. // Ex: Min = 50, Max = 150. Value range = 100 + 1 (because we include 50 and 100) _valueRange = (Maximum - Minimum) + 1; // Get track bar value relative to value range (value - minimum value). // Ex: Min = 50, Max = 150, Value = 100. Value relative to value range = 50. _valueRelativeToValueRange = Value - Minimum; // Draw background context.DrawRectangle(new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight), _brushBackground, _penTransparent); // Return if value range is zero if (_valueRange == 0) return; // Draw fader track float trackX = context.BoundsWidth / 2; float trackY = Margin; float trackY2 = context.BoundsHeight - Margin; // Draw shadow track context.DrawLine(new BasicPoint(trackX + 1, trackY + 1), new BasicPoint(trackX + 1, trackY2 + 1), new BasicPen(new BasicBrush(_centerLineShadowColor), 1)); // Draw track context.DrawLine(new BasicPoint(trackX, trackY), new BasicPoint(trackX, trackY2), new BasicPen(new BasicBrush(_centerLineColor), 1)); // Get the track height (remove margin from top and bottom) _trackHeight = context.BoundsHeight - (Margin * 2); // Get tick width float tickHeight = _trackHeight / _valueRange; // Get the percentage of the value relative to value range (needed to draw the fader). // We need to divide the value relative to value range to the value range to get the ratio. // Ex: Min = 50, Max = 150, Value = 100. Value relative to value range = 50. Value range = 100. Value ratio = 0.5 _valueRatio = (_valueRelativeToValueRange / _valueRange); // Calculate fader position // We need to invert the values (i.e. max is on top, min is bottom) //float valueY = (valueRatio * trackHeight) + Margin; float valueY = _trackHeight - (_valueRatio * _trackHeight) + Margin; float faderY = valueY + ((tickHeight - FaderHeight) / 2); float tickCenterY = valueY + (tickHeight / 2); // Create fader rectangle _rectFader = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2), faderY, FaderWidth, FaderHeight); // // Draw tick zone (for debug) // //RectangleF rectTickZone = new RectangleF(valueX, 0, tickWidth, Height); // //g.FillRectangle(Brushes.DarkGray, rectTickZone); var rectFaderShadowTop = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + 1, FaderWidth, 8); var rectFaderShadowBottom = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + FaderHeight - 8 + 1, FaderWidth, 8); var rectFaderShadowCenter = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + 4 + 1, FaderWidth, FaderHeight - 8); context.DrawEllipsis(rectFaderShadowTop, _brushFaderShadowColor, _penTransparent); context.DrawEllipsis(rectFaderShadowBottom, _brushFaderShadowColor, _penTransparent); context.DrawRectangle(rectFaderShadowCenter, _brushFaderShadowColor, _penTransparent); // Draw fader outline (with 8px border) var rectFaderTop = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2), faderY, FaderWidth, 8); var rectFaderBottom = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2), faderY + FaderHeight - 8, FaderWidth, 8); var rectFaderBottomCenter = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2), faderY + FaderHeight - 10, FaderWidth, 6); var rectFaderCenter = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2), faderY + 4, FaderWidth, FaderHeight - 8); context.DrawEllipsis(rectFaderTop, _brushFaderGradient, _penTransparent); context.DrawEllipsis(rectFaderBottom, _brushFaderShadowColor1, _penTransparent); context.DrawRectangle(rectFaderCenter, _brushFaderColor2, _penTransparent); context.DrawRectangle(rectFaderBottomCenter, _brushFaderShadowColor1, _penTransparent); // Draw fader inside (with 4px border) var rectFaderInsideBottom = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + FaderHeight - 8, FaderWidth - 2, 4); var rectFaderInsideBottomCenter = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + FaderHeight - 12, FaderWidth - 2, FaderHeight - 24); var rectFaderInsideTop = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + 4, FaderWidth - 2, 8); var rectFaderInsideTopCenter = new BasicRectangle((context.BoundsWidth / 2) - (FaderWidth / 2) + 1, faderY + 8, FaderWidth - 2, FaderHeight - 24); context.DrawEllipsis(rectFaderInsideTop, _brushFaderShadowColor1, _penTransparent); context.DrawEllipsis(rectFaderInsideTopCenter, _brushFaderShadowGradient, _penTransparent); context.DrawEllipsis(rectFaderInsideBottom, _brushFaderColor2, _penTransparent); context.DrawRectangle(rectFaderInsideBottomCenter, _brushFaderColor2, _penTransparent); context.DrawLine(new BasicPoint((context.BoundsWidth / 2) - (FaderWidth / 2), tickCenterY), new BasicPoint((context.BoundsWidth / 2) - (FaderWidth / 2) + FaderWidth, tickCenterY), _penMiddleLineColor); }
public static RectangleF ToRect(BasicRectangle rectangle) { return new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); }
public BasicRectangle MeasureText(string text, BasicRectangle rectangle, string fontFace, float fontSize) { return new BasicRectangle(0, 0, 30, 20); }
public void Render(IGraphicsContext context) { // Value range is the size between max and min track bar value. // Ex: Min = 50, Max = 150. Value range = 100 + 1 (because we include 50 and 100) _valueRange = (Maximum - Minimum) + 1; // Get track bar value relative to value range (value - minimum value). // Ex: Min = 50, Max = 150, Value = 100. Value relative to value range = 50. _valueRelativeToValueRange = Value - Minimum; // Draw background context.DrawRectangle(new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight), _brushBackground, _penTransparent); // Return if value range is zero if (_valueRange == 0) return; // Draw fader track float trackX = Margin; // add margin from left float trackX2 = context.BoundsWidth - Margin; // add margin from right float trackY = context.BoundsHeight / 2; // right in the center context.DrawLine(new BasicPoint(trackX + 1, trackY + 1), new BasicPoint(trackX2 + 1, trackY + 1), _penCenterLineShadow); context.DrawLine(new BasicPoint(trackX, trackY), new BasicPoint(trackX2, trackY), _penCenterLine); // Get the track width (remove margin from left and right) _trackWidth = context.BoundsWidth - (Margin * 2); // Get tick width float tickWidth = _trackWidth / _valueRange; // Get the percentage of the value relative to value range (needed to draw the fader). // We need to divide the value relative to value range to the value range to get the ratio. // Ex: Min = 50, Max = 150, Value = 100. Value relative to value range = 50. Value range = 100. Value ratio = 0.5 _valueRatio = (_valueRelativeToValueRange / _valueRange); // Get the value X coordinate by multiplying the value ratio to the track bar width (removed 3 pixels from left // and right). Add margin from left. float valueX = (_valueRatio * _trackWidth) + Margin; // this gives the LEFT x for our zone float faderX = valueX + ((tickWidth - FaderWidth) / 2); float tickCenterX = valueX + (tickWidth / 2); // Create fader rectangle _rectFader = new BasicRectangle(faderX, (context.BoundsHeight / 2) - (FaderHeight / 2), FaderWidth, FaderHeight); //// Draw tick zone (for debug) ////RectangleF rectTickZone = new RectangleF(valueX, 0, tickWidth, Height); ////g.FillRectangle(Brushes.DarkGray, rectTickZone); // Draw fader outline (with 8px border) //var rectFaderLeft = new BasicRectangle(faderX, (context.BoundsHeight / 2) - (FaderHeight / 2), 8, FaderHeight); //var rectFaderRight = new BasicRectangle(faderX + FaderWidth - 8, (context.BoundsHeight / 2) - (FaderHeight / 2), 8, FaderHeight); var rectFaderCenter = new BasicRectangle(faderX + 4, (context.BoundsHeight / 2) - (FaderHeight / 2), FaderWidth - 8, FaderHeight); //context.DrawEllipsis(rectFaderLeft, new BasicGradientBrush(_faderColor1, _faderColor, 90), new BasicPen()); //context.DrawEllipsis(rectFaderLeft, new BasicGradientBrush(new BasicColor(255, 0, 0), new BasicColor(0, 0, 255), 90), new BasicPen()); //context.DrawEllipsis(rectFaderRight, new BasicGradientBrush(_faderColor1, _faderColor, 90), new BasicPen()); //context.DrawEllipsis(rectFaderRight, new BasicGradientBrush(new BasicColor(0, 255, 0), new BasicColor(255, 0, 255), 90), new BasicPen()); context.DrawEllipsis(rectFaderCenter, _brushFaderColor2, _penShadowColor1); //context.DrawEllipsis(rectFaderCenter, new BasicBrush(_faderColor), new BasicPen()); // Draw fader inside (with 4px border) //var rectFaderInsideLeft = new BasicRectangle(faderX + 2, (context.BoundsHeight / 2) - (FaderHeight / 2) + 2, 4, FaderHeight - 4); //var rectFaderInsideRight = new BasicRectangle(faderX + FaderWidth - 6, (context.BoundsHeight / 2) - (FaderHeight / 2) + 2, 4, FaderHeight - 4); //context.DrawEllipsis(rectFaderInsideLeft, new BasicGradientBrush(_faderShadowColor, _faderShadowColor, 90), new BasicPen()); //context.DrawEllipsis(rectFaderInsideRight, new BasicGradientBrush(_faderShadowColor, _faderShadowColor, 90), new BasicPen()); context.DrawLine(new BasicPoint(tickCenterX, (context.BoundsHeight / 2) - (FaderHeight / 2)), new BasicPoint(tickCenterX, (context.BoundsHeight / 2) - (FaderHeight / 2) + FaderHeight), _penShadowColor1); }
public void DrawRectangle(BasicRectangle rectangle, BasicBrush brush, BasicPen pen) { _context.SetSourceRGB(brush.Color.R / 255f, brush.Color.G / 255f, brush.Color.B / 255f); _context.Rectangle(GenericControlHelper.ToRect(rectangle)); _context.Fill(); }
public void DrawText(string text, BasicRectangle rectangle, BasicColor color, string fontFace, float fontSize) { }
public void DrawImage(BasicRectangle rectangleDestination, BasicRectangle rectangleSource, IDisposable image) { }
public void DrawEllipsis(BasicRectangle rectangle, BasicBrush brush, BasicPen pen) { }
public void DrawImage(BasicRectangle rectangle, IDisposable image) { }
private void AddBitmapRequestToList(BasicRectangle boundsBitmap, BasicRectangle boundsWaveForm, float zoom, WaveFormDisplayType displayType) { // Make sure we don't slow down GetTile() by creating a task and running LINQ queries on another thread Task.Factory.StartNew(() => { var request = new WaveFormBitmapRequest() { DisplayType = displayType, BoundsBitmap = boundsBitmap, BoundsWaveForm = boundsWaveForm, Zoom = zoom }; // Check if a tile already exists WaveFormTile existingTile = null; lock (_lockerTiles) { existingTile = _tiles.FirstOrDefault(obj => obj.ContentOffset.X == boundsBitmap.X && obj.Zoom == zoom); } lock (_lockerRequests) { // Check if bitmap has already been requested in queue var existingRequest = _requests.FirstOrDefault(obj => obj.BoundsBitmap.Equals(request.BoundsBitmap) && obj.BoundsWaveForm.Equals(request.BoundsWaveForm) && obj.Zoom == request.Zoom); // Request a new bitmap only if necessary if (existingRequest == null && existingTile == null) { //Console.WriteLine("WaveFormCacheService - Adding bitmap request to queue - zoom: {0} boundsBitmap: {1} boundsWaveForm: {2}", zoom, boundsBitmap, boundsWaveForm); _requests.Add(request); // Remove the oldest request from the list if we hit the maximum if(_requests.Count > MaxNumberOfRequests) _requests.RemoveAt(0); //Console.WriteLine("............. PULSING"); Monitor.Pulse(_lockerRequests); } } }); }
private List<WaveFormTile> GetAvailableTilesToFillBounds(float zoom, BasicRectangle bounds) { var tiles = new List<WaveFormTile>(); float zoomThreshold = (float)Math.Floor(zoom); lock (_lockerTiles) { tiles = _tiles.Where(obj => obj.CheckIfTileIsInBounds(TileSize, zoomThreshold, bounds)).ToList(); } return tiles; }
public static Rect ToRect(BasicRectangle rectangle) { return new Rect((int) rectangle.X, (int) rectangle.Y, (int) (rectangle.X + rectangle.Width), (int) (rectangle.Y + rectangle.Height)); }
public WaveFormScaleControl() : base() { OnInvalidateVisual += () => { }; OnInvalidateVisualInRect += (rect) => { }; Frame = new BasicRectangle(); FontFace = "Roboto"; FontSize = 10; }
public void Render(IGraphicsContext context) { lock (_locker) { if (_brushBackground == null) { _brushBackground = new BasicBrush(_backgroundColor); _penTransparent = new BasicPen(); _penBorder = new BasicPen(new BasicBrush(_borderColor), 1); _rectText = context.MeasureText("12345:678.90", new BasicRectangle(0, 0, Frame.Width, Frame.Height), "HelveticaNeue", 10); } } _density = context.Density; Frame = new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight); context.DrawRectangle(new BasicRectangle(0, 0, context.BoundsWidth, context.BoundsHeight), _brushBackground, _penTransparent); if (_audioFile == null || _audioFileLength == 0) return; // Check if scale type needs to be updated if (_lastWidth != ContentSize.Width) { _lastWidth = ContentSize.Width; CalculateScale(context.Density); } // Draw scale borders //Console.WriteLine("WaveFormScaleView - scaleType: {0} totalMinutes: {1} totalSeconds: {2} totalMinutesScaled: {3} totalSecondsScaled: {4}", scaleType.ToString(), totalMinutes, totalSeconds, totalMinutesScaled, totalSecondsScaled); context.SetPen(_penBorder); context.StrokeLine(new BasicPoint(0, ContentSize.Height - 1), new BasicPoint(ContentSize.Width, ContentSize.Height - 1)); int firstVisibleIndex = (int)Math.Floor(ContentOffset.X / _tickWidth); int lastVisibleIndex = firstVisibleIndex + (int)Math.Floor(context.BoundsWidth / _tickWidth); float tickX = -ContentOffset.X + (firstVisibleIndex * _tickWidth); int majorTickIndex = (int)Math.Ceiling(firstVisibleIndex / 10f); //for (int a = firstVisibleIndex; a < _tickCount; a++) for (int a = firstVisibleIndex; a < lastVisibleIndex; a++) { // Ignore ticks out of bounds bool isMajorTick = ((a % 10) == 0); if (tickX >= 0 && tickX <= Frame.Width) { //Console.WriteLine("####> WaveFormView - Scale - tick {0} x: {1} isMajorTick: {2} tickCount: {3}", a, tickX, isMajorTick, tickCount); if(isMajorTick) // //context.DrawLine(new BasicPoint(tickX, context.BoundsHeight - (context.BoundsHeight / 1.25f)), new BasicPoint(tickX, context.BoundsHeight), _penMajorTick); context.StrokeLine(new BasicPoint(tickX, 0), new BasicPoint(tickX, ContentSize.Height - 1)); else context.StrokeLine(new BasicPoint(tickX, ContentSize.Height - (ContentSize.Height / 6) - 1), new BasicPoint(tickX, ContentSize.Height - 1)); if (isMajorTick) { // Draw dashed traversal line for major ticks context.StrokeLine(new BasicPoint(tickX, ContentSize.Height - 1), new BasicPoint(tickX, ContentSize.Height - 1)); // Determine major scale text int minutes = 0; int seconds = 0; switch (_scaleType) { case WaveFormScaleType._10minutes: minutes = majorTickIndex * 10; seconds = 0; break; case WaveFormScaleType._5minutes: minutes = majorTickIndex * 5; seconds = 0; break; case WaveFormScaleType._2minutes: minutes = majorTickIndex * 2; seconds = 0; break; case WaveFormScaleType._1minute: minutes = majorTickIndex; seconds = 0; break; case WaveFormScaleType._30seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = (majorTickIndex % _scaleMultiplier == 0) ? 0 : 30; break; case WaveFormScaleType._10seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = ((int)Math.Floor(majorTickIndex % _scaleMultiplier)) * 10; break; case WaveFormScaleType._5seconds: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = ((int)Math.Floor(majorTickIndex % _scaleMultiplier)) * 5; break; case WaveFormScaleType._1second: minutes = (int)Math.Floor(majorTickIndex / _scaleMultiplier); seconds = (int)Math.Floor(majorTickIndex % _scaleMultiplier); break; } // Draw text at every major tick (minute count) string scaleMajorTitle = string.Format("{0}:{1:00}", minutes, seconds); //float y = ContentSize.Height - (ContentSize.Height/12f) - _rectText.Height - (0.5f * context.Density); float y = 3 * context.Density;//ContentSize.Height - _rectText.Height - (10 * context.Density); context.DrawText(scaleMajorTitle, new BasicPoint(tickX + (4 * context.Density), y), _textColor, FontFace, FontSize); } } if(isMajorTick) majorTickIndex++; tickX += _tickWidth; } }
public WaveFormTile GetTile(float x, float height, float waveFormWidth, float zoom) { //var stopwatch = new Stopwatch(); //stopwatch.Start(); WaveFormTile tile = null; float zoomThreshold = (float) Math.Floor(zoom); var boundsBitmap = new BasicRectangle(x, 0, TileSize, height); var boundsWaveForm = new BasicRectangle(0, 0, waveFormWidth * zoomThreshold, height); var tiles = GetAvailableTilesForPosition(x, zoom); if (tiles != null && tiles.Count > 0) { // Get the tile with the zoom that is the closest to the current zoom threshold tile = GetOptimalTileAtZoom(tiles, zoomThreshold); // If we could not find a tile at this zoom level, we need to generate one if (tile.Zoom != zoomThreshold) { //Console.WriteLine("WaveFormCacheService - Requesting a new bitmap (zoom doesn't match) - zoom: {0} tile.Zoom: {1} boundsBitmap: {2} boundsWaveForm: {3}", zoom, tile.Zoom, boundsBitmap, boundsWaveForm); AddBitmapRequestToList(boundsBitmap, boundsWaveForm, zoomThreshold, WaveFormDisplayType.Stereo); } return tile; } else { // We need to request a new bitmap at this zoom threshold because there are no bitmaps available (usually zoom @ 100%) //Console.WriteLine("WaveFormCacheService - Requesting a new bitmap - zoom: {0} boundsBitmap: {1} boundsWaveForm: {2}", zoomThreshold, boundsBitmap, boundsWaveForm); AddBitmapRequestToList(boundsBitmap, boundsWaveForm, zoomThreshold, WaveFormDisplayType.Stereo); } //stopwatch.Stop(); //Console.WriteLine("WaveFormCacheService - GetTile - stopwatch: {0} ms", stopwatch.ElapsedMilliseconds); return tile; }