private unsafe RenderBitmap GetPatternBitmapFromCache(RenderGraphics g, Pattern p) { int patternSizeX = Song.PatternLength - 1; int patternSizeY = trackSizeY - patternHeaderSizeY - 1; RenderBitmap bmp; if (patternBitmapCache.TryGetValue(p.Id, out bmp)) { if (bmp.Size.Width == patternSizeX) { return(bmp); } else { patternBitmapCache.Remove(p.Id); bmp.Dispose(); bmp = null; } } uint[] data = new uint[patternSizeX * patternSizeY]; Note minNote; Note maxNote; if (p.GetMinMaxNote(out minNote, out maxNote)) { if (maxNote.Value == minNote.Value) { minNote.Value = (byte)(minNote.Value - 5); maxNote.Value = (byte)(maxNote.Value + 5); } else { minNote.Value = (byte)(minNote.Value - 2); maxNote.Value = (byte)(maxNote.Value + 2); } Note lastValid = new Note { Value = Note.NoteInvalid }; for (int i = 0; i < Song.PatternLength - 1; i++) // TODO: We always skip the last note. { var n = p.Notes[i]; if (n.IsValid && !n.IsStop) { lastValid = p.Notes[i]; } if (lastValid.IsValid) { float scaleY = (patternSizeY - noteSizeY) / (float)patternSizeY; int x = i; int y = Math.Min((int)Math.Round((lastValid.Value - minNote.Value) / (float)(maxNote.Value - minNote.Value) * scaleY * patternSizeY), patternSizeY - noteSizeY); var instrument = lastValid.Instrument; var color = instrument == null ? ThemeBase.LightGreyFillColor1 : instrument.Color; for (int j = 0; j < noteSizeY; j++) { data[(patternSizeY - 1 - (y + j)) * patternSizeX + x] = (uint)color.ToArgb(); } } //if (n.HasEffect) //{ // for (int y = 0; y < patternSizeY; y++) // { // data[y * patternSizeX + i] = 0xff000000; // } //} } } bmp = g.CreateBitmap(patternSizeX, patternSizeY, data); patternBitmapCache[p.Id] = bmp; return(bmp); }