public Bitmap GetBitmap(int Width, int Height, int seq) { if (this.RenderedFramesContains(this.VisibleHashCode(seq))) { Console.WriteLine("Found pre-rendered frame with: {0}", this.VisibleHashCode(seq)); return(this.RenderedFramesGet(this.VisibleHashCode(seq)) as Bitmap); } else { Console.WriteLine("Rendering song frame for {0}", this.VisibleHashCode(seq)); } lock (renderLock) { Pen p; SolidBrush brush; Bitmap bmp = new Bitmap(Width, Height); Graphics graphics = Graphics.FromImage(bmp); GraphicsPath pth, pth2; Rectangle bounds; Font font; float fontSz; BeamTextFormat[] format = this.Theme.TextFormat; string[] text = new string[Enum.GetValues(typeof(SongTextType)).Length]; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.SmoothingMode = SmoothingMode.AntiAlias; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.TextRenderingHint = TextRenderingHint.AntiAlias; this.RenderBGImage(this.BGImagePath, graphics, Width, Height); if (HideText) { graphics.Dispose(); return(bmp); } LyricsItem lyrics = this.GetLyrics(seq); text[(int)SongTextType.Title] = (this.Title == null) ? "" : this.Title; text[(int)SongTextType.Verse] = (lyrics == null) ? "" : lyrics.Lyrics; text[(int)SongTextType.Author] = (this.Author == null) ? "" : this.Author; text[(int)SongTextType.Key] = this.GetKey(); pth = new GraphicsPath(); foreach (int type in Enum.GetValues(this.enumType)) { if (this.Hide[type]) { continue; } // We have to keep the text within these user-specified boundaries bounds = new System.Drawing.Rectangle( (int)(format[type].Bounds.X / 100 * Width), (int)(format[type].Bounds.Y / 100 * Height), (int)(format[type].Bounds.Width / 100 * Width), (int)(format[type].Bounds.Height / 100 * Height)); p = new Pen(format[type].TextColor, 1.0F); if (showRectangles == true) { graphics.DrawRectangle(p, bounds); } if (text[type].Length > 0) { p.LineJoin = LineJoin.Round; StringFormat sf = new StringFormat(); sf.Alignment = format[type].HAlignment; sf.LineAlignment = format[type].VAlignment; if (this.WordWrap) { // Used by TextTool (which inherits from Song). fontSz = format[type].TextFont.Size * ((float)Height / BeamTextFormat.ReferenceResolutionH); font = new Font(format[type].TextFont.FontFamily, fontSz, format[type].TextFont.Style); pth = wrapper.GetPath(text[type], font, sf, bounds); } else { // Tab characters are ignored by AddString below. Converting them to spaces. text[type] = Regex.Replace(text[type], "\t", " "); pth = new GraphicsPath(); fontSz = format[type].TextFont.Size * ((float)Height / BeamTextFormat.ReferenceResolutionH); font = new Font(format[type].TextFont.FontFamily, fontSz, format[type].TextFont.Style); pth.AddString(text[type], font.FontFamily, (int)font.Style, font.Size, new Point(0, 0), sf); pth.Transform(DreamTools.FitContents(bounds, pth.GetBounds(), sf)); } brush = new SolidBrush(format[type].TextColor); #region Add special effects if (format[type].Effects == "Outline") { p = new Pen(format[type].OutlineColor, format[type].OutlineSize); graphics.DrawPath(p, pth); } else if (format[type].Effects == "Filled Outline") { pth2 = (GraphicsPath)pth.Clone(); graphics.FillPath(brush, pth); graphics.DrawPath(p, pth); // Widen the path Pen widenPen = new Pen(format[type].OutlineColor, format[type].OutlineSize); widenPen.LineJoin = System.Drawing.Drawing2D.LineJoin.Round; pth2.Widen(widenPen); graphics.FillPath(new SolidBrush(format[type].OutlineColor), pth2); graphics.DrawPath(p, pth); graphics.FillPath(brush, pth); } else //if (format[type].Effects == "Normal") { { graphics.FillPath(brush, pth); graphics.DrawPath(p, pth); } #endregion } } graphics.Dispose(); if (this.config != null && this.config.PreRender) { this.RenderedFramesSet(this.VisibleHashCode(seq), bmp); } return(bmp); } }
/// <summary> /// This constructor creates a new song out of a plain text file. The file must contain a single /// song in the following format: /// === /// Number. OldSong title (key) /// /// verse 1: /// Line 1 of verse 1 /// Line 2 of verse 1 /// /// verse 2: /// Line 1 of verse 2 /// Line 2 of verse 2 /// /// chorus 1: /// Line 1 of chorus 1 ... /// === /// /// This constructor is mainly used when importing songs stored in this text format. /// </summary> /// <param name="fileName"></param> public Song(string fileName) : this() { // If BOM is present, read the file as Unicode, else default to UTF-8 string[] lines; Regex r; Match m; LyricsItem currItem = null; using (TextReader input = new StreamReader(fileName, true)) { lines = input.ReadToEnd().Split('\n'); } foreach (string rawLine in lines) { string line = rawLine.TrimEnd(); if (Regex.IsMatch(line, @"\s*#")) { this.Notes += Regex.Replace(line, @"\s*#\s?(.*)", @"$1"); continue; } r = new Regex(@"\s*(verse|chorus)\s+(\d+):", RegexOptions.IgnoreCase); m = r.Match(line); if (m.Success && m.Groups.Count == 3) { // This is the beginning of a verse or chorus if (currItem != null) { this.SongLyrics.Add(currItem); } if (m.Groups[1].Value.ToLower() == "verse") { currItem = new LyricsItem(LyricsType.Verse, Convert.ToInt16(m.Groups[2].Value), ""); } else if (m.Groups[1].Value.ToLower() == "chorus") { currItem = new LyricsItem(LyricsType.Chorus, Convert.ToInt16(m.Groups[2].Value), ""); } else { currItem = new LyricsItem(LyricsType.Other, Convert.ToInt16(m.Groups[2].Value), ""); } } else if (Regex.IsMatch(line, @"\w+")) { if (currItem != null) { currItem.Lyrics += line + "\n"; } else if (this.Title == null) { // Look for title of the form: "23. Title, words! (optional key)" r = new Regex(@"(\d+)[\.]*\s+(.+)"); m = r.Match(line); if (m.Success && m.Groups.Count == 3) { this.Number = m.Groups[1].Value; this.Title = m.Groups[2].Value.Trim(); // If we have a key in the Title, remove it and handle it separately // The key looks like: Ab, or F#, or Bbm r = new Regex(@"(.+)\s+\(([a-gA-G#]+)\)"); m = r.Match(this.Title); if (m.Success && m.Groups.Count == 3) { this.Title = m.Groups[1].Value.Trim(); string key = m.Groups[2].Value; int minor = key.IndexOf("m"); if (minor > 0) { key = key.Substring(0, minor); this.MinorKey = true; } this.KeyRangeHigh = key; this.KeyRangeLow = key; } } else { this.Title = line; } } } } if (currItem != null) { this.SongLyrics.Add(currItem); } // We end up with an extra "\n" at the end of each verse. Trim them off. foreach (LyricsItem item in this.SongLyrics) { item.Lyrics = item.Lyrics.TrimEnd(); } this.CreateSimpleSequence(); if (this.SongLyrics.Count > 0) { this.FileName = Regex.Replace(fileName, ".txt$", ".xml", RegexOptions.IgnoreCase); } }