File indexing completed on 2024-12-22 04:40:09
0001 /* 0002 SPDX-FileCopyrightText: 2021-2022 Mladen Milinkovic <max@smoothware.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "webvttoutputformat.h" 0008 0009 #include "core/richtext/richdocument.h" 0010 #include "core/subtitleiterator.h" 0011 #include "helpers/common.h" 0012 0013 #include <QRegularExpression> 0014 0015 using namespace SubtitleComposer; 0016 0017 0018 WebVTTOutputFormat::WebVTTOutputFormat() 0019 : OutputFormat($("WebVTT"), QStringList($("vtt"))) 0020 {} 0021 0022 inline static QString 0023 fixEmptyLines(QString str) 0024 { 0025 staticRE$(reEmptyLine, "\\n(?=\\n)", REu); 0026 return str.replace(reEmptyLine, $("\n ")); 0027 } 0028 0029 QString 0030 WebVTTOutputFormat::dumpSubtitles(const Subtitle &subtitle, bool primary) const 0031 { 0032 QString ret; 0033 0034 ret += $("WEBVTT"); 0035 ret.append(QChar::LineFeed); 0036 const QString &intro = fixEmptyLines(subtitle.meta("comment.intro.0")); 0037 if(!intro.isEmpty()) { 0038 ret.append(intro); 0039 ret.append(QChar::LineFeed); 0040 } 0041 ret.append(QChar::LineFeed); 0042 0043 for(int noteId = 0;;) { 0044 const QByteArray key(QByteArray("comment.top.") + QByteArray::number(noteId++)); 0045 if(!subtitle.metaExists(key)) 0046 break; 0047 ret.append($("NOTE")); 0048 ret.append(QChar::LineFeed); 0049 ret.append(fixEmptyLines(subtitle.meta(key))); 0050 ret.append(QChar::LineFeed); 0051 ret.append(QChar::LineFeed); 0052 } 0053 0054 if(!subtitle.stylesheet()->unformattedCSS().isEmpty()) { 0055 ret.append($("STYLE")); 0056 ret.append(QChar::LineFeed); 0057 ret.append(fixEmptyLines(subtitle.stylesheet()->unformattedCSS())); 0058 ret.append(QChar::LineFeed); 0059 ret.append(QChar::LineFeed); 0060 } 0061 0062 for(SubtitleIterator it(subtitle); it.current(); ++it) { 0063 const SubtitleLine *line = it.current(); 0064 0065 const QString &comment = line->meta("comment"); 0066 if(!comment.isEmpty()) { 0067 ret.append($("NOTE")); 0068 ret.append(comment.contains(QChar::LineFeed) ? QChar::LineFeed : QChar::Space); 0069 ret.append(fixEmptyLines(comment)); 0070 ret.append(QChar::LineFeed); 0071 ret.append(QChar::LineFeed); 0072 } 0073 0074 const QString &cueId = line->meta("id"); 0075 if(!cueId.isEmpty()) { 0076 ret.append(cueId); 0077 ret.append(QChar::LineFeed); 0078 } 0079 0080 const Time showTime = line->showTime(); 0081 const Time hideTime = line->hideTime(); 0082 ret += QString::asprintf("%02d:%02d:%02d.%03d --> %02d:%02d:%02d.%03d", 0083 showTime.hours(), showTime.minutes(), showTime.seconds(), showTime.millis(), 0084 hideTime.hours(), hideTime.minutes(), hideTime.seconds(), hideTime.millis()); 0085 const SubtitleRect &p = line->pos(); 0086 // FIXME: consider hAlign/vAlign in rect calculations 0087 // FIXME: position/line can have extra alignment/anchor parameter 0088 if(p.vertical) { 0089 ret.append($(" vertical:lr")); // FIXME: RTL support (vertical:rl) 0090 const int top = p.top; 0091 const int left = p.left; 0092 const int height = int(p.bottom) - top; 0093 if(left) // FIXME: with vertical:rl should be right 0094 ret.append(QString::asprintf(" line:%02d%%", left)); 0095 if(top) 0096 ret.append(QString::asprintf(" position:%02d%%", top)); 0097 if(height != 100) 0098 ret.append(QString::asprintf(" size:%02d%%", height)); 0099 } else { 0100 const int top = p.top; 0101 const int left = p.left; 0102 const int width = int(p.right) - left; 0103 if(top) 0104 ret.append(QString::asprintf(" line:%02d%%", top)); 0105 if(left) 0106 ret.append(QString::asprintf(" position:%02d%%", left)); 0107 if(width != 100) 0108 ret.append(QString::asprintf(" size:%02d%%", width)); 0109 } 0110 if(p.hAlign == SubtitleRect::START) 0111 ret.append(QLatin1String(" align:start")); 0112 else if(p.hAlign == SubtitleRect::END) 0113 ret.append(QLatin1String(" align:end")); 0114 ret.append(QChar::LineFeed); 0115 0116 const RichString text = (primary ? line->primaryDoc() : line->secondaryDoc())->toRichText(); 0117 ret += text.richString() 0118 .replace(QLatin1String("&"), QLatin1String("&")) 0119 .replace(QLatin1String("<"), QLatin1String("<")) 0120 .replace(QLatin1String(">"), QLatin1String(">")); 0121 0122 ret += $("\n\n"); 0123 } 0124 return ret; 0125 }