|
@@ -0,0 +1,127 @@
|
|
|
+using KaraokeRenderPoc.Karaoke;
|
|
|
+using System;
|
|
|
+using System.Drawing;
|
|
|
+using System.Drawing.Drawing2D;
|
|
|
+using System.Drawing.Text;
|
|
|
+using System.Windows.Forms;
|
|
|
+
|
|
|
+namespace KaraokeRenderPoc
|
|
|
+{
|
|
|
+ public partial class RenderForm : Form
|
|
|
+ {
|
|
|
+ private KaraokeLyric _karaoke;
|
|
|
+
|
|
|
+ public RenderForm()
|
|
|
+ {
|
|
|
+ InitializeComponent();
|
|
|
+ InputTextBox.Text = Properties.Resources.Example;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ParseButton_Click(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ _karaoke = new KaraokeLyric(InputTextBox.Lines);
|
|
|
+ PositionTrackBar.Maximum = _karaoke.Length;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void PositionTrackBar_Scroll(object sender, EventArgs e)
|
|
|
+ {
|
|
|
+ RenderPictureBox.Invalidate();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RenderPictureBox_Paint(object sender, PaintEventArgs e)
|
|
|
+ {
|
|
|
+ var g = e.Graphics;
|
|
|
+
|
|
|
+ g.CompositingMode = CompositingMode.SourceOver;
|
|
|
+ g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
|
|
+ g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
|
|
+ g.SmoothingMode = SmoothingMode.HighQuality;
|
|
|
+ g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
|
|
|
+
|
|
|
+ g.PageUnit = GraphicsUnit.Pixel;
|
|
|
+
|
|
|
+ var top = 400;
|
|
|
+
|
|
|
+ var correctWidth = -25f;
|
|
|
+
|
|
|
+ var readyOutlineColor = Color.Black;
|
|
|
+ var readyFillColor = Color.White;
|
|
|
+
|
|
|
+ var singOutlineColor = Color.White;
|
|
|
+ var singFillColor = Color.Blue;
|
|
|
+
|
|
|
+ var timelinePosition = PositionTrackBar.Value;
|
|
|
+
|
|
|
+ if (_karaoke != null)
|
|
|
+ {
|
|
|
+ var index = _karaoke.GetSentenceIndex(timelinePosition);
|
|
|
+
|
|
|
+ var sentence = _karaoke.Sentences[index];
|
|
|
+
|
|
|
+ using var rubyFont = new Font("方正准圆_GBK", 20, FontStyle.Bold);
|
|
|
+ using var textFont = new Font("方正准圆_GBK", 40, FontStyle.Bold);
|
|
|
+
|
|
|
+ var left = 0f;
|
|
|
+
|
|
|
+ foreach (var word in sentence.Words)
|
|
|
+ {
|
|
|
+ var rubySize = g.MeasureString(word.Ruby, rubyFont);//g.MeasureDisplayString(word.Ruby, rubyFont);//TextRenderer.MeasureText(g, word.Ruby, rubyFont); //
|
|
|
+ var textSize = g.MeasureString(word.Text, textFont);//g.MeasureDisplayString(word.Text, textFont);//TextRenderer.MeasureText(g, word.Text, textFont); //
|
|
|
+
|
|
|
+ var maxWidth = Math.Max(rubySize.Width, textSize.Width);
|
|
|
+
|
|
|
+ //g.DrawRectangle(Pens.Red, left, top, rubySize.Width, rubyFont.Height);
|
|
|
+ //g.DrawRectangle(Pens.Red, left, top + rubyFont.Height, textSize.Width, textFont.Height);
|
|
|
+
|
|
|
+ if (word.StartPosition <= timelinePosition && word.EndPosition >= timelinePosition)
|
|
|
+ {
|
|
|
+ var percent = ((float)timelinePosition - word.StartPosition) / word.Duration;
|
|
|
+
|
|
|
+ var singWidth = maxWidth * percent;
|
|
|
+ var readyWidth = maxWidth - singWidth;
|
|
|
+
|
|
|
+ g.SetClip(new RectangleF(left, top, singWidth, rubyFont.Height + textFont.Height));
|
|
|
+ g.DrawKaraoke(word.Ruby, rubyFont, new RectangleF(left, top, maxWidth, rubyFont.Height), singOutlineColor, singFillColor);
|
|
|
+ g.DrawKaraoke(word.Text, textFont, new RectangleF(left, top + rubyFont.Height, maxWidth, textFont.Height), singOutlineColor, singFillColor);
|
|
|
+
|
|
|
+ g.SetClip(new RectangleF(left + singWidth, top, readyWidth, rubyFont.Height + textFont.Height));
|
|
|
+ g.DrawKaraoke(word.Ruby, rubyFont, new RectangleF(left, top, maxWidth, rubyFont.Height), readyOutlineColor, readyFillColor);
|
|
|
+ g.DrawKaraoke(word.Text, textFont, new RectangleF(left, top + rubyFont.Height, maxWidth, textFont.Height), readyOutlineColor, readyFillColor);
|
|
|
+
|
|
|
+ g.ResetClip();
|
|
|
+ }
|
|
|
+ else if (word.EndPosition < timelinePosition)
|
|
|
+ {
|
|
|
+ g.DrawKaraoke(word.Ruby, rubyFont, new RectangleF(left, top, maxWidth, rubyFont.Height), singOutlineColor, singFillColor);
|
|
|
+ g.DrawKaraoke(word.Text, textFont, new RectangleF(left, top + rubyFont.Height, maxWidth, textFont.Height), singOutlineColor, singFillColor);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g.DrawKaraoke(word.Ruby, rubyFont, new RectangleF(left, top, maxWidth, rubySize.Height), readyOutlineColor, readyFillColor);
|
|
|
+ g.DrawKaraoke(word.Text, textFont, new RectangleF(left, top + rubyFont.Height, maxWidth, textSize.Height), readyOutlineColor, readyFillColor);
|
|
|
+ }
|
|
|
+
|
|
|
+ left += correctWidth + maxWidth;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ internal static class ExtensionMethods
|
|
|
+ {
|
|
|
+ public static void DrawKaraoke(this Graphics g, string s, Font f, RectangleF rectangle, Color outline, Color fill, int outlineWidth = 1)
|
|
|
+ {
|
|
|
+ using var path = new GraphicsPath();
|
|
|
+ {
|
|
|
+ using var alignment = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Near };
|
|
|
+ path.AddString(s, f.FontFamily, (int)f.Style, f.Size, rectangle, alignment);
|
|
|
+ }
|
|
|
+
|
|
|
+ using var fillBrush = new SolidBrush(fill);
|
|
|
+ g.FillPath(fillBrush, path);
|
|
|
+
|
|
|
+ using var outlinePen = new Pen(outline, outlineWidth);
|
|
|
+ g.DrawPath(outlinePen, path);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|