/// <summary>
        /// Speed - max 17 (for most languages) characters per second
        /// </summary>
        public void Check(Subtitle subtitle, NetflixQualityController controller)
        {
            var oldIgnoreWhiteSpace = Configuration.Settings.General.CharactersPerSecondsIgnoreWhiteSpace;

            try
            {
                Configuration.Settings.General.CharactersPerSecondsIgnoreWhiteSpace = false;
                foreach (Paragraph p in subtitle.Paragraphs)
                {
                    var jp = new Paragraph(p);
                    if (controller.Language == "ja")
                    {
                        jp.Text = HtmlUtil.RemoveHtmlTags(jp.Text, true);
                        jp.Text = NetflixImsc11Japanese.RemoveTags(jp.Text);
                    }
                    var charactersPerSeconds = Utilities.GetCharactersPerSecond(jp);
                    if (charactersPerSeconds > controller.CharactersPerSecond)
                    {
                        var fixedParagraph = new Paragraph(p, false);
                        while (Utilities.GetCharactersPerSecond(fixedParagraph) > controller.CharactersPerSecond)
                        {
                            fixedParagraph.EndTime.TotalMilliseconds++;
                        }
                        string comment = "Maximum " + controller.CharactersPerSecond + " characters per second";
                        controller.AddRecord(p, fixedParagraph, comment, charactersPerSeconds.ToString(CultureInfo.InvariantCulture));
                    }
                }
            }
            finally
            {
                Configuration.Settings.General.CharactersPerSecondsIgnoreWhiteSpace = oldIgnoreWhiteSpace;
            }
        }
Esempio n. 2
0
        public void Check(Subtitle subtitle, NetflixQualityController controller)
        {
            ICalcLength calc = CalcFactory.MakeCalculator(nameof(CalcAll));
            var         charactersPerSecond = controller.CharactersPerSecond;
            var         comment             = "Maximum " + charactersPerSecond + " characters per second";

            foreach (var p in subtitle.Paragraphs)
            {
                var jp = new Paragraph(p);
                if (controller.Language == "ja")
                {
                    jp.Text = HtmlUtil.RemoveHtmlTags(jp.Text, true);
                    jp.Text = NetflixImsc11Japanese.RemoveTags(jp.Text);
                }

                if (controller.Language == "ko")
                {
                    calc = CalcFactory.MakeCalculator(nameof(CalcCjk));
                }

                var charactersPerSeconds = Utilities.GetCharactersPerSecond(jp, calc);
                if (charactersPerSeconds > charactersPerSecond && !p.StartTime.IsMaxTime)
                {
                    var fixedParagraph = new Paragraph(p, false);
                    while (Utilities.GetCharactersPerSecond(fixedParagraph) > charactersPerSecond)
                    {
                        fixedParagraph.EndTime.TotalMilliseconds++;
                    }

                    controller.AddRecord(p, fixedParagraph, comment, FormattableString.Invariant($"CPS={charactersPerSeconds:0.##}"));
                }
            }
        }
Esempio n. 3
0
 public void Check(Subtitle subtitle, NetflixQualityController controller)
 {
     foreach (var p in subtitle.Paragraphs)
     {
         foreach (var line in p.Text.SplitToLines())
         {
             if (controller.Language == "ja")
             {
                 var vertical = p.Text.Contains("{\\an7", StringComparison.Ordinal) || p.Text.Contains("{\\an9", StringComparison.Ordinal);
                 var text     = HtmlUtil.RemoveHtmlTags(line, true);
                 text = NetflixImsc11Japanese.RemoveTags(text);
                 if (vertical) // Vertical subtitles - Maximum 11 full-width characters per line
                 {
                     if (CalculateJapaneseLength(text) > 11)
                     {
                         var comment = "Single vertical line length > 11";
                         controller.AddRecord(p, p.StartTime.ToHHMMSSFF(), comment, line.Length.ToString(CultureInfo.InvariantCulture));
                     }
                 }
                 else // Horizontal subtitles - Maximum 13 full-width characters per line
                 {
                     if (CalculateJapaneseLength(text) > 13)
                     {
                         var comment = "Single horizontal line length > 13";
                         controller.AddRecord(p, p.StartTime.ToHHMMSSFF(), comment, line.Length.ToString(CultureInfo.InvariantCulture));
                     }
                 }
             }
             else if (controller.Language == "ko" && line.CountCharacters(nameof(CalcCjk)) > controller.SingleLineMaxLength)
             {
                 var fixedParagraph = new Paragraph(p, false);
                 fixedParagraph.Text = Utilities.AutoBreakLine(fixedParagraph.Text, controller.SingleLineMaxLength, controller.SingleLineMaxLength - 3, controller.Language);
                 var comment = "Single line length > " + controller.SingleLineMaxLength;
                 controller.AddRecord(p, fixedParagraph, comment, line.CountCharacters(nameof(CalcCjk)).ToString(CultureInfo.InvariantCulture));
             }
             else if (line.CountCharacters() > controller.SingleLineMaxLength)
             {
                 var fixedParagraph = new Paragraph(p, false);
                 fixedParagraph.Text = Utilities.AutoBreakLine(fixedParagraph.Text, controller.SingleLineMaxLength, controller.SingleLineMaxLength - 3, controller.Language);
                 var comment = "Single line length > " + controller.SingleLineMaxLength;
                 controller.AddRecord(p, fixedParagraph, comment, line.Length.ToString(CultureInfo.InvariantCulture));
             }
         }
     }
 }
        private static List <Paragraph> MakeHorizontalParagraphs(Paragraph p, int width, int height)
        {
            var lines      = p.Text.SplitToLines();
            var adjustment = 34;
            var startY     = height - lines.Count * 2 * adjustment + 30;

            if (p.Text.StartsWith("{\\an8", StringComparison.Ordinal))
            {
                startY = 40;
            }

            var list         = new List <Paragraph>();
            var furiganaList = new List <Paragraph>();
            var rubyOn       = false;
            var italinOn     = false;
            int startX;

            using (var g = Graphics.FromHwnd(IntPtr.Zero))
            {
                var actualText     = NetflixImsc11Japanese.RemoveTags(HtmlUtil.RemoveHtmlTags(p.Text, true));
                var actualTextSize = g.MeasureString(actualText, new Font(SystemFonts.DefaultFont.FontFamily, 20));
                startX = (int)(width / 2.0 - actualTextSize.Width / 2.0);
                if (p.Text.StartsWith("{\\an5", StringComparison.Ordinal))
                {
                    startY = (int)(height / 2.0 - actualTextSize.Height / 2.0);
                }
            }

            for (var index = 0; index < lines.Count; index++)
            {
                var line = lines[index];
                if (italinOn)
                {
                    line = "<i>" + line;
                }
                var actual = new StringBuilder();
                int i      = 0;
                while (i < line.Length)
                {
                    if (line.Substring(i).StartsWith("{\\"))
                    {
                        var end = line.IndexOf('}', i);
                        if (end < 0)
                        {
                            break;
                        }

                        i = end + 1;
                    }
                    else if (line.Substring(i).StartsWith("<i>", StringComparison.Ordinal) || line.Substring(i).StartsWith("<u>", StringComparison.Ordinal) || line.Substring(i).StartsWith("<b>", StringComparison.Ordinal))
                    {
                        actual.Append("{\\i1}");
                        i       += 3;
                        italinOn = true;
                    }
                    else if (line.Substring(i).StartsWith("</i>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</u>", StringComparison.Ordinal) || line.Substring(i).StartsWith("</b>", StringComparison.Ordinal))
                    {
                        actual.Append("{\\i0}");
                        i       += 4;
                        italinOn = false;
                    }
                    else if (line.Substring(i).StartsWith("<bouten-", StringComparison.Ordinal))
                    {
                        var end = line.IndexOf('>', i);
                        if (end < 0)
                        {
                            break;
                        }

                        if (end + 1 >= line.Length)
                        {
                            break;
                        }

                        var endTagStart = line.IndexOf("</", end, StringComparison.Ordinal);
                        if (endTagStart < 0)
                        {
                            break;
                        }

                        var tag  = line.Substring(i + 1, end - i - 1);
                        var text = line.Substring(end + 1, endTagStart - end - 1);

                        foreach (var ch in text)
                        {
                            var furiganaChar = BoutenTagToUnicode(tag);
                            if (!string.IsNullOrWhiteSpace(furiganaChar))
                            {
                                furiganaList.Add(new Paragraph($"{{\\alpha&FF&}}{actual}{{\\alpha&0&}}{furiganaChar}", p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                            }
                            actual.Append(ch);
                        }

                        var endTagEnd = line.IndexOf('>', endTagStart);
                        if (endTagEnd < 0)
                        {
                            break;
                        }

                        i = endTagEnd + 1;
                    }
                    else if (line.Substring(i).StartsWith("<ruby-container>", StringComparison.Ordinal))
                    {
                        var baseTextStart = line.IndexOf("<ruby-base>", i, StringComparison.Ordinal);
                        var baseTextEnd   = line.IndexOf("</ruby-base>", i, StringComparison.Ordinal);
                        if (baseTextStart < 0 || baseTextEnd < 0)
                        {
                            baseTextStart = line.IndexOf("<ruby-base-italic>", i, StringComparison.Ordinal);
                            baseTextEnd   = line.IndexOf("</ruby-base-italic>", i, StringComparison.Ordinal);
                            if (baseTextStart < 0 || baseTextEnd < 0)
                            {
                                break;
                            }
                        }
                        baseTextStart += "<ruby-base>".Length;
                        var baseText = line.Substring(baseTextStart, baseTextEnd - baseTextStart);

                        var extraText      = string.Empty;
                        var extraTextStart = line.IndexOf("<ruby-text>", i, StringComparison.Ordinal);
                        var extraTextEnd   = line.IndexOf("</ruby-text>", i, StringComparison.Ordinal);
                        if (extraTextStart >= 0 || extraTextEnd >= 0 && extraTextStart < extraTextEnd)
                        {
                            extraTextStart += "<ruby-text>".Length;
                            extraText       = line.Substring(extraTextStart, extraTextEnd - extraTextStart);
                        }

                        if (string.IsNullOrEmpty(extraText))
                        {
                            extraTextStart = line.IndexOf("<ruby-text-italic>", i, StringComparison.Ordinal);
                            extraTextEnd   = line.IndexOf("</ruby-text-italic>", i, StringComparison.Ordinal);
                            if (extraTextStart >= 0 || extraTextEnd >= 0 && extraTextStart < extraTextEnd)
                            {
                                extraTextStart += "<ruby-text-italic>".Length;
                                extraText       = line.Substring(extraTextStart, extraTextEnd - extraTextStart);
                            }
                        }

                        var extraTextAfter      = string.Empty;
                        var extraTextStartAfter = line.IndexOf("<ruby-text-after>", i, StringComparison.Ordinal);
                        var extraTextEndAfter   = line.IndexOf("</ruby-text-after>", i, StringComparison.Ordinal);
                        if (extraTextStartAfter >= 0 || extraTextEndAfter >= 0 && extraTextStartAfter < extraTextEndAfter)
                        {
                            extraTextStartAfter += "<ruby-text-after>".Length;
                            extraText            = line.Substring(extraTextStartAfter, extraTextEndAfter - extraTextStartAfter);
                        }

                        var preFurigana = string.Empty;
                        if (actual.Length > 0)
                        {
                            preFurigana = $"{{\\alpha&FF&}}{actual.ToString().TrimEnd()}{{\\alpha&0&}}";
                        }
                        if (!string.IsNullOrWhiteSpace(extraText))
                        {
                            furiganaList.Add(new Paragraph($"{preFurigana}{{\\fs20}}{extraText}", p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                        }
                        if (!string.IsNullOrWhiteSpace(extraTextAfter))
                        {
                            furiganaList.Add(new Paragraph($"{preFurigana}{{\\fs20}} {extraTextAfter}", p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                        }
                        actual.Append(baseText);

                        var endTagEnd = line.IndexOf("</ruby-container>", i, StringComparison.Ordinal);
                        if (endTagEnd < 0)
                        {
                            break;
                        }
                        i      = endTagEnd + "</ruby-container>".Length;
                        rubyOn = true;
                    }
                    else
                    {
                        actual.Append(line.Substring(i, 1));
                        i++;
                    }
                }

                var  actualText    = actual.ToString().TrimEnd();
                bool displayBefore = lines.Count == 2 && index == 0 || lines.Count == 1;
                if (displayBefore && furiganaList.Count > 0)
                {
                    foreach (var fp in furiganaList)
                    {
                        var beforeText = "{\\an1}{\\pos(" + startX + "," + startY + ")}" + fp.Text;
                        list.Add(new Paragraph(beforeText, p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                    }
                    startY += adjustment;
                    if (rubyOn && index == 0 && lines.Count == 2)
                    {
                        startY += 3;
                    }
                }

                actualText = "{\\an1}{\\pos(" + startX + "," + startY + ")}" + actualText;

                list.Add(new Paragraph(actualText, p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                startY += adjustment;

                if (!displayBefore && furiganaList.Count > 0)
                {
                    if (rubyOn && index == 1 && lines.Count == 2)
                    {
                        startY = (int)(startY - adjustment * 0.4);
                    }

                    foreach (var fp in furiganaList)
                    {
                        var beforeText = "{\\an1}{\\pos(" + startX + "," + startY + ")}" + fp.Text;
                        list.Add(new Paragraph(beforeText, p.StartTime.TotalMilliseconds, p.EndTime.TotalMilliseconds));
                    }
                    startY += adjustment;
                }
                furiganaList.Clear();
            }

            return(list);
        }