Пример #1
0
        private AssStyle GetStyleMatchingStructure(AssSection section)
        {
            HashSet <ShadowType> sectionShadowTypes = section.ShadowColors.Keys.ToHashSet();

            foreach (AssStyle style in _styles.Values)
            {
                AssStyleOptions options = GetStyleOptions(style);

                if (style.HasOutlineBox != (section.BackColor.A > 0))
                {
                    continue;
                }

                HashSet <ShadowType> styleShadowTypes = new HashSet <ShadowType>();
                if (style.HasOutline && !style.OutlineIsBox)
                {
                    styleShadowTypes.Add(ShadowType.Glow);
                }

                if (options != null)
                {
                    styleShadowTypes.UnionWith(options.ShadowTypes);
                }

                if (!styleShadowTypes.SetEquals(sectionShadowTypes))
                {
                    continue;
                }

                return(style);
            }
            return(null);
        }
Пример #2
0
        private static string GetBackgroundImageUrl(AssStyleOptions options)
        {
            byte[] imageData;
            string mimeType;

            if (options?.HasExistingBackgroundImage ?? false)
            {
                try
                {
                    imageData = File.ReadAllBytes(options.BackgroundImagePath);
                    mimeType  = ExtensionToMimeType.GetOrDefault(Path.GetExtension(options.BackgroundImagePath).ToLower()) ?? "image/png";
                }
                catch
                {
                    imageData = Resources.Checkers;
                    mimeType  = "image/png";
                }
            }
            else
            {
                imageData = Resources.Checkers;
                mimeType  = "image/png";
            }

            return($"data:{mimeType};base64,{Convert.ToBase64String(imageData)}");
        }
Пример #3
0
        private void _lstStyles_SelectedIndexChanged(object sender, EventArgs e)
        {
            AssStyleOptions options = SelectedStyleOptions;

            if (options == null)
            {
                _spltStyleOptions.Panel2.Enabled = false;
                _brwPreview.DocumentText         = string.Empty;
                return;
            }

            AssStyle style = _styles[options.Name];

            _previewSuspended = true;

            _spltStyleOptions.Panel2.Enabled = true;
            _pnlOptions.Enabled    = !_builtinStyleNames.Contains(style.Name);
            _pnlShadowType.Enabled = style.HasShadow;

            if (style.HasOutline && !style.HasOutlineBox)
            {
                _chkGlow.Checked = true;
                _chkGlow.Enabled = false;
            }
            else
            {
                _chkGlow.Checked = style.HasShadow && options.ShadowTypes.Contains(ShadowType.Glow);
                _chkGlow.Enabled = true;
            }

            _chkBevel.Checked      = style.HasShadow && options.ShadowTypes.Contains(ShadowType.Bevel);
            _chkSoftShadow.Checked = style.HasShadow && options.ShadowTypes.Contains(ShadowType.SoftShadow);
            _chkHardShadow.Checked = style.HasShadow && options.ShadowTypes.Contains(ShadowType.HardShadow);

            Color currentWordTextColor    = options.CurrentWordTextColor;
            Color currentWordOutlineColor = options.CurrentWordOutlineColor;
            Color currentWordShadowColor  = options.CurrentWordShadowColor;

            _chkKaraoke.Checked = options.IsKaraoke;
            _chkHighlightCurrentWord.Checked = !currentWordTextColor.IsEmpty;

            _txtCurrentWordTextColor.Enabled = _chkHighlightCurrentWord.Checked;
            _txtCurrentWordTextColor.Text    = _txtCurrentWordTextColor.Enabled ? ColorUtil.ToHtml(currentWordTextColor) : string.Empty;
            _btnPickTextColor.Enabled        = _txtCurrentWordTextColor.Enabled;

            _txtCurrentWordOutlineColor.Enabled = _chkHighlightCurrentWord.Checked && style.HasOutline && !style.HasOutlineBox;
            _txtCurrentWordOutlineColor.Text    = _txtCurrentWordOutlineColor.Enabled ? ColorUtil.ToHtml(currentWordOutlineColor) : string.Empty;
            _btnPickOutlineColor.Enabled        = _txtCurrentWordOutlineColor.Enabled;

            _txtCurrentWordShadowColor.Enabled = _chkHighlightCurrentWord.Checked && style.HasShadow;
            _txtCurrentWordShadowColor.Text    = _txtCurrentWordShadowColor.Enabled ? ColorUtil.ToHtml(currentWordShadowColor) : string.Empty;
            _btnPickShadowColor.Enabled        = _txtCurrentWordShadowColor.Enabled;

            UpdateBackgroundImageButton();

            _previewSuspended = false;
            UpdateStylePreview();
        }
Пример #4
0
        internal void ApplyStyle(AssSection section, AssStyle style, AssStyleOptions options)
        {
            section.Font           = style.Font;
            section.Scale          = style.LineHeight / DefaultStyle.LineHeight;
            section.Bold           = style.Bold;
            section.Italic         = style.Italic;
            section.Underline      = style.Underline;
            section.ForeColor      = style.PrimaryColor;
            section.SecondaryColor = style.SecondaryColor;
            if (options?.IsKaraoke ?? false)
            {
                section.CurrentWordForeColor    = options.CurrentWordTextColor;
                section.CurrentWordOutlineColor = options.CurrentWordOutlineColor;
                section.CurrentWordShadowColor  = options.CurrentWordShadowColor;
            }
            else
            {
                section.CurrentWordForeColor    = Color.Empty;
                section.CurrentWordOutlineColor = Color.Empty;
                section.CurrentWordShadowColor  = Color.Empty;
            }

            section.BackColor = Color.Empty;
            section.ShadowColors.Clear();

            if (style.HasShadow)
            {
                foreach (ShadowType shadowType in options?.ShadowTypes ?? new List <ShadowType> {
                    ShadowType.SoftShadow
                })
                {
                    section.ShadowColors[shadowType] = style.ShadowColor;
                }
            }

            if (style.HasOutline)
            {
                if (style.OutlineIsBox)
                {
                    section.BackColor = style.OutlineColor;
                }
                else
                {
                    section.ShadowColors[ShadowType.Glow] = style.OutlineColor;
                }
            }

            section.Blur = 0;
        }
Пример #5
0
        private List <AssLine> ParseLine(AssDialogue dialogue, AssStyle style, AssStyleOptions styleOptions)
        {
            AssLine line =
                new AssLine(
                    TimeUtil.RoundTimeToFrameCenter(dialogue.Start),
                    TimeUtil.RoundTimeToFrameCenter(dialogue.End)
                    )
            {
                AnchorPoint = style.AnchorPoint
            };

            string[] effects = dialogue.Effect.Split(';');
            if (effects.Contains(EffectNames.NoAndroidDarkTextHack))
            {
                line.AndroidDarkTextHackAllowed = false;
            }

            AssTagContext context = new AssTagContext
            {
                Document            = this,
                InitialStyle        = style,
                InitialStyleOptions = styleOptions,
                Style        = style,
                StyleOptions = styleOptions,
                Line         = line,
                Section      = new AssSection()
            };

            ApplyStyle(context.Section, style, styleOptions);
            CreateTagSections(line, dialogue.Text, context);
            CreateRubySections(line);

            List <AssLine> lines = new List <AssLine> {
                line
            };

            foreach (AssTagContext.PostProcessor postProcessor in context.PostProcessors)
            {
                List <AssLine> extraLines = postProcessor();
                if (extraLines != null)
                {
                    lines.AddRange(extraLines);
                }
            }

            return(lines);
        }
Пример #6
0
        private static string GetVerticalAlign(AssStyle style, AssStyleOptions options)
        {
            if (!(options?.HasExistingBackgroundImage ?? false))
            {
                return("middle");
            }

            if (AnchorPointUtil.IsTopAligned(style.AnchorPoint))
            {
                return("top");
            }

            if (AnchorPointUtil.IsBottomAligned(style.AnchorPoint))
            {
                return("bottom");
            }

            return("middle");
        }
Пример #7
0
        private static string GetTextAlign(AssStyle style, AssStyleOptions options)
        {
            if (!(options?.HasExistingBackgroundImage ?? false))
            {
                return("center");
            }

            if (AnchorPointUtil.IsLeftAligned(style.AnchorPoint))
            {
                return("left");
            }

            if (AnchorPointUtil.IsRightAligned(style.AnchorPoint))
            {
                return("right");
            }

            return("center");
        }
Пример #8
0
        public AssDocument(string filePath, List <AssStyleOptions> styleOptions = null)
        {
            RegisterTagHandlers();

            Dictionary <string, AssDocumentSection> fileSections = ReadDocument(filePath);

            AssDocumentSection infoSection = fileSections["Script Info"];

            VideoDimensions = new Size(infoSection.GetItemInt("PlayResX", 384), infoSection.GetItemInt("PlayResY", 288));

            _styles = fileSections["V4+ Styles"].MapItems("Style", i => new AssStyle(i))
                      .ToDictionary(s => s.Name);

            if (styleOptions != null)
            {
                _styleOptions = styleOptions.ToDictionary(o => o.Name);
            }

            DefaultFontSize = (_styles.GetOrDefault("Default") ?? _styles.First().Value).FontSize;

            foreach (AssDialogue dialogue in fileSections["Events"].MapItems("Dialogue", i => new AssDialogue(i)))
            {
                AssStyle style = GetStyle(dialogue.Style);
                if (style == null)
                {
                    throw new Exception($"Line \"{dialogue.Text}\" refers to style \"{dialogue.Style}\" which doesn't exist.");
                }

                AssStyleOptions options = GetStyleOptions(dialogue.Style);

                List <AssLine> lines = ParseLine(dialogue, style, options);
                Lines.AddRange(lines.SelectMany(ExpandLine));
            }

            EmulateKaraokeForSimultaneousLines();
            foreach (AssLine line in Lines)
            {
                MergeIdenticallyFormattedSections(line);
                line.NormalizeAlpha();
            }
        }
Пример #9
0
        private void _btnBackgroundImage_Click(object sender, EventArgs e)
        {
            AssStyleOptions options = SelectedStyleOptions;

            if (options.HasExistingBackgroundImage)
            {
                options.BackgroundImagePath = null;
            }
            else
            {
                if (_dlgOpenImage.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                options.BackgroundImagePath = _dlgOpenImage.FileName;
            }

            UpdateBackgroundImageButton();
            UpdateStylePreview();
        }
Пример #10
0
        private List <AssLine> ParseLine(AssDialogue dialogue, AssStyle style, AssStyleOptions styleOptions)
        {
            DateTime startTime = TimeUtil.SnapTimeToFrame(dialogue.Start.AddMilliseconds(32));
            DateTime endTime   = TimeUtil.SnapTimeToFrame(dialogue.End).AddMilliseconds(32);
            AssLine  line      = new AssLine(startTime, endTime)
            {
                AnchorPoint = style.AnchorPoint, KaraokeType = SimpleKaraokeType
            };

            AssTagContext context = new AssTagContext
            {
                Document            = this,
                InitialStyle        = style,
                InitialStyleOptions = styleOptions,
                Style        = style,
                StyleOptions = styleOptions,
                Line         = line,
                Section      = new AssSection(null)
            };

            ApplyStyle(context.Section, style, styleOptions);
            CreateTagSections(line, dialogue.Text, context);
            CreateRubySections(line);

            List <AssLine> lines = new List <AssLine> {
                line
            };

            foreach (AssTagContext.PostProcessor postProcessor in context.PostProcessors)
            {
                List <AssLine> extraLines = postProcessor();
                if (extraLines != null)
                {
                    lines.AddRange(extraLines);
                }
            }

            return(lines);
        }
Пример #11
0
        public static string GenerateHtml(AssStyle style, AssStyleOptions options, AssStyle defaultStyle, float windowsScaleFactor)
        {
            StringBuilder html = new StringBuilder();

            html.Append($@"
                  <!DOCTYPE html>
                  <html>
                  <head>
                      <meta http-equiv=""X-UA-Compatible"" content=""IE=edge"" />
                      <style>
                          html, body
                          {{
                              width: 100%;
                              height: 100%;
                              padding: 0;
                              margin: 0;
                              cursor: default;
                          }}
                          body
                          {{
                              display: table;
                              background-image: url({GetBackgroundImageUrl(options)});
                              background-position: {GetBackgroundImagePosition(options)};
                              background-repeat: {GetBackgroundImageRepeat(options)};
                              -ms-user-select: none;
                          }}
                          #wrapper
                          {{
                              display: table-cell;
                              height: 100%;
                              padding: 10px;
                              text-align: {GetTextAlign(style, options)};
                              vertical-align: {GetVerticalAlign(style, options)};
                          }}
            ");

            if (options != null)
            {
                GenerateBackgroundCss(html, "#background", style, defaultStyle, windowsScaleFactor);
                GenerateForegroundCss(html, "#regular", style, style.PrimaryColor, style.OutlineColor, style.ShadowColor, options.ShadowTypes);
                if (options.IsKaraoke)
                {
                    GenerateForegroundCss(
                        html,
                        "#singing",
                        style,
                        !options.CurrentWordTextColor.IsEmpty ? options.CurrentWordTextColor : style.PrimaryColor,
                        !options.CurrentWordOutlineColor.IsEmpty ? options.CurrentWordOutlineColor : style.OutlineColor,
                        !options.CurrentWordShadowColor.IsEmpty ? options.CurrentWordShadowColor : style.ShadowColor,
                        options.ShadowTypes
                        );
                    GenerateForegroundCss(html, "#unsung", style, style.SecondaryColor, style.OutlineColor, style.ShadowColor, options.ShadowTypes);
                }
            }

            html.Append(@"
                      </style>
                  </head>
                  <body>
                      <div id=""wrapper"">
            ");

            if (options != null)
            {
                html.Append(@"<span id=""background"">");

                if (options.IsKaraoke)
                {
                    html.Append($@"<span id=""regular"">{Resources.PreviewSampleKaraoke1}</span>");
                    html.Append($@"<span id=""singing"">{Resources.PreviewSampleKaraoke2}</span>");
                    html.Append($@"<span id=""unsung"">{Resources.PreviewSampleKaraoke3}</span>");
                }
                else
                {
                    html.Append($@"<span id=""regular"">{Resources.PreviewSampleRegular}</span>");
                }

                html.Append(@"</span>");
            }

            html.Append(@"
                      </div>
                  </body>
                  </html>
            ");
            return(html.ToString());
        }
Пример #12
0
 private static string GetBackgroundImageRepeat(AssStyleOptions options)
 {
     return(options?.HasExistingBackgroundImage ?? false ? "no-repeat" : "repeat");
 }
Пример #13
0
 private static string GetBackgroundImagePosition(AssStyleOptions options)
 {
     return(options?.HasExistingBackgroundImage ?? false ? "center center" : "left top");
 }
Пример #14
0
        private List <AssLine> ParseLine(AssDialogue dialogue, AssStyle style, AssStyleOptions styleOptions)
        {
            DateTime startTime = TimeUtil.SnapTimeToFrame(dialogue.Start.AddMilliseconds(32));
            DateTime endTime   = TimeUtil.SnapTimeToFrame(dialogue.End).AddMilliseconds(32);
            AssLine  line      = new AssLine(startTime, endTime)
            {
                AnchorPoint = style.AnchorPoint
            };

            AssTagContext context = new AssTagContext
            {
                Document            = this,
                Dialogue            = dialogue,
                InitialStyle        = style,
                InitialStyleOptions = styleOptions,
                Style        = style,
                StyleOptions = styleOptions,
                Line         = line,
                Section      = new AssSection(null)
            };

            ApplyStyle(context.Section, style, styleOptions);

            string text  = Regex.Replace(dialogue.Text, @"(?:\\N)+$", "");
            int    start = 0;

            foreach (Match match in Regex.Matches(text, @"\{(?:\\(?<tag>fn|\d?[a-z]+)(?<arg>\([^\{\}\(\)]*\)|[^\{\}\(\)\\]*))+\}"))
            {
                int end = match.Index;

                if (end > start)
                {
                    context.Section.Text = text.Substring(start, end - start).Replace("\\N", "\r\n");
                    line.Sections.Add(context.Section);

                    context.Section          = (AssSection)context.Section.Clone();
                    context.Section.Text     = null;
                    context.Section.Duration = TimeSpan.Zero;
                }

                CaptureCollection tags      = match.Groups["tag"].Captures;
                CaptureCollection arguments = match.Groups["arg"].Captures;
                for (int i = 0; i < tags.Count; i++)
                {
                    if (_tagHandlers.TryGetValue(tags[i].Value, out AssTagHandlerBase handler))
                    {
                        handler.Handle(context, arguments[i].Value);
                    }
                }

                start = match.Index + match.Length;
            }

            if (start < text.Length)
            {
                context.Section.Text = text.Substring(start, text.Length - start).Replace("\\N", "\r\n");
                line.Sections.Add(context.Section);
            }

            if (line.RubyPosition != RubyPosition.None)
            {
                CreateRubySections(line);
            }

            List <AssLine> lines = new List <AssLine> {
                line
            };

            foreach (AssTagContext.PostProcessor postProcessor in context.PostProcessors)
            {
                List <AssLine> extraLines = postProcessor();
                if (extraLines != null)
                {
                    lines.AddRange(extraLines);
                }
            }

            return(lines);
        }