@@ -108,6 +108,11 @@ void Config::SetDefaults()
|
||||
SetEntryInternal(QStringLiteral("DefaultAudioTransition"), NodeValue::kText, QStringLiteral("org.olivevideoeditor.Olive.crossdissolve"));
|
||||
SetEntryInternal(QStringLiteral("DefaultTransitionLength"), NodeValue::kRational, QVariant::fromValue(rational(1)));
|
||||
|
||||
SetEntryInternal(QStringLiteral("DefaultSubtitleSize"), NodeValue::kInt, 48);
|
||||
SetEntryInternal(QStringLiteral("DefaultSubtitleFamily"), NodeValue::kText, QString());
|
||||
SetEntryInternal(QStringLiteral("DefaultSubtitleWeight"), NodeValue::kInt, QFont::Bold);
|
||||
SetEntryInternal(QStringLiteral("AntialiasSubtitles"), NodeValue::kBoolean, true);
|
||||
|
||||
SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000);
|
||||
|
||||
SetEntryInternal(QStringLiteral("CatColor0"), NodeValue::kInt, ColorCoding::kRed);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "viewer.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFontDialog>
|
||||
#include <QGuiApplication>
|
||||
#include <QInputDialog>
|
||||
#include <QLabel>
|
||||
@@ -32,7 +33,6 @@
|
||||
|
||||
#include "audio/audiomanager.h"
|
||||
#include "common/clamp.h"
|
||||
#include "common/power.h"
|
||||
#include "common/ratiodialog.h"
|
||||
#include "common/timecodefunctions.h"
|
||||
#include "config/config.h"
|
||||
@@ -41,10 +41,9 @@
|
||||
#include "node/generator/shape/shapenodebase.h"
|
||||
#include "node/project/project.h"
|
||||
#include "render/rendermanager.h"
|
||||
#include "task/taskmanager.h"
|
||||
#include "viewerpreventsleep.h"
|
||||
#include "widget/audiomonitor/audiomonitor.h"
|
||||
#include "widget/menu/menu.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
#include "widget/nodeparamview/nodeparamviewundo.h"
|
||||
#include "widget/timelinewidget/tool/add.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
@@ -547,6 +546,20 @@ void ViewerWidget::HandleFirstRequeueDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::ShowSubtitleProperties()
|
||||
{
|
||||
QFont f(OLIVE_CONFIG("DefaultSubtitleFamily").toString(), OLIVE_CONFIG("DefaultSubtitleSize").toInt(), OLIVE_CONFIG("DefaultSubtitleWeight").toInt());
|
||||
QFontDialog fd(f, this);
|
||||
|
||||
if (fd.exec() == QDialog::Accepted) {
|
||||
f = fd.selectedFont();
|
||||
OLIVE_CONFIG("DefaultSubtitleSize") = f.pointSize();
|
||||
OLIVE_CONFIG("DefaultSubtitleFamily") = f.family();
|
||||
OLIVE_CONFIG("DefaultSubtitleWeight") = f.weight();
|
||||
display_widget_->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::CloseAudioProcessor()
|
||||
{
|
||||
audio_processor_.Close();
|
||||
@@ -1309,10 +1322,26 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
|
||||
}
|
||||
|
||||
if (context_menu_widget_ == display_widget_) {
|
||||
QAction* show_subtitles_action = menu.addAction(tr("Show Subtitles"));
|
||||
auto subtitle_menu = new Menu(tr("Subtitles"), &menu);
|
||||
menu.addMenu(subtitle_menu);
|
||||
|
||||
QAction* show_subtitles_action = subtitle_menu->addAction(tr("Show Subtitles"));
|
||||
show_subtitles_action->setCheckable(true);
|
||||
show_subtitles_action->setChecked(display_widget_->GetShowSubtitles());
|
||||
connect(show_subtitles_action, &QAction::triggered, display_widget_, &ViewerDisplayWidget::SetShowSubtitles);
|
||||
|
||||
subtitle_menu->addSeparator();
|
||||
|
||||
auto subtitle_font_properties = subtitle_menu->addAction(tr("Subtitle Properties"));
|
||||
connect(subtitle_font_properties, &QAction::triggered, this, &ViewerWidget::ShowSubtitleProperties);
|
||||
|
||||
auto subtitle_antialias = subtitle_menu->addAction(tr("Use Anti-aliasing"));
|
||||
subtitle_antialias->setCheckable(true);
|
||||
subtitle_antialias->setChecked(OLIVE_CONFIG("AntialiasSubtitles").toBool());
|
||||
connect(subtitle_antialias, &QAction::triggered, this, [this](bool e){
|
||||
OLIVE_CONFIG("AntialiasSubtitles") = e;
|
||||
display_widget_->update();
|
||||
});
|
||||
}
|
||||
|
||||
menu.exec(static_cast<QWidget*>(sender())->mapToGlobal(pos));
|
||||
|
||||
@@ -352,6 +352,8 @@ private slots:
|
||||
|
||||
void HandleFirstRequeueDestroy();
|
||||
|
||||
void ShowSubtitleProperties();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -463,45 +463,78 @@ void ViewerDisplayWidget::OnPaint()
|
||||
const QVector<Track*> &subtitle_tracklist = subtitle_tracks_->track_list(Track::kSubtitle)->GetTracks();
|
||||
|
||||
if (!subtitle_tracklist.empty()) {
|
||||
QPainter p(paint_device());
|
||||
QPainterPath path;
|
||||
|
||||
QTransform transform = GenerateWorldTransform();
|
||||
QRect bounding_box = transform.mapRect(rect());
|
||||
|
||||
QFont f;
|
||||
qreal font_sz = OLIVE_CONFIG("DefaultSubtitleSize").toInt();
|
||||
{
|
||||
// Scale font size by transform
|
||||
QTransform display_transform = GenerateDisplayTransform();
|
||||
font_sz *= display_transform.m11();
|
||||
}
|
||||
f.setPointSizeF(font_sz);
|
||||
|
||||
QString family = OLIVE_CONFIG("DefaultSubtitleFamily").toString();
|
||||
if (!family.isEmpty()) {
|
||||
f.setFamily(family);
|
||||
}
|
||||
|
||||
f.setWeight(OLIVE_CONFIG("DefaultSubtitleWeight").toInt());
|
||||
|
||||
bounding_box.adjust(bounding_box.width()/10, bounding_box.height()/10, -bounding_box.width()/10, -bounding_box.height()/10);
|
||||
|
||||
QFont f = p.font();
|
||||
int font_sz = bounding_box.height() / 18;
|
||||
f.setStyleHint(QFont::SansSerif);
|
||||
f.setFamily(f.defaultFamily());
|
||||
f.setPointSize(font_sz);
|
||||
f.setWeight(QFont::Bold);
|
||||
p.setFont(f);
|
||||
p.setPen(Qt::white);
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
int text_line = 1;
|
||||
QFontMetrics fm(f);
|
||||
|
||||
for (int j=subtitle_tracklist.size()-1; j>=0; j--) {
|
||||
Track *sub_track = subtitle_tracklist.at(j);
|
||||
if (!sub_track->IsMuted()) {
|
||||
if (SubtitleBlock *sub = dynamic_cast<SubtitleBlock*>(sub_track->BlockAtTime(time_))) {
|
||||
// Split into lines
|
||||
QStringList list = QtUtils::WordWrapString(sub->GetText(), p.fontMetrics(), bounding_box.width());
|
||||
QStringList list = QtUtils::WordWrapString(sub->GetText(), fm, bounding_box.width());
|
||||
|
||||
for (int i=list.size()-1; i>=0; i--) {
|
||||
int w = QtUtils::QFontMetricsWidth(p.fontMetrics(), list.at(i));
|
||||
path.addText(bounding_box.x() + bounding_box.width()/2 - w/2, bounding_box.y() + bounding_box.height() - p.fontMetrics().height() * text_line + p.fontMetrics().ascent(), p.font(), list.at(i));
|
||||
text_line++;
|
||||
int w = QtUtils::QFontMetricsWidth(fm, list.at(i));
|
||||
path.addText(bounding_box.width()/2 - w/2, bounding_box.height() - fm.height() * (list.size() - i) + fm.ascent(), f, list.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.setPen(QPen(Qt::black, font_sz / 16));
|
||||
p.setBrush(Qt::white);
|
||||
p.drawPath(path);
|
||||
bool antialias = OLIVE_CONFIG("AntialiasSubtitles").toBool();
|
||||
|
||||
QPixmap *aa_pixmap;
|
||||
QPainter *text_painter;
|
||||
if (antialias) {
|
||||
// QPainter only supports anti-aliasing in software, so to achieve it, we draw to a
|
||||
// software buffer first and then draw that onto the hardware
|
||||
aa_pixmap = new QPixmap(bounding_box.width(), bounding_box.height());
|
||||
aa_pixmap->fill(Qt::transparent);
|
||||
text_painter = new QPainter(aa_pixmap);
|
||||
} else {
|
||||
// Just draw straight to the hardware
|
||||
text_painter = new QPainter(paint_device());
|
||||
|
||||
// Offset path by however much is necessary
|
||||
path.translate(bounding_box.x(), bounding_box.y());
|
||||
}
|
||||
|
||||
text_painter->setPen(QPen(Qt::black, f.pointSizeF() / 16));
|
||||
text_painter->setBrush(Qt::white);
|
||||
text_painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
text_painter->drawPath(path);
|
||||
|
||||
delete text_painter;
|
||||
|
||||
if (antialias) {
|
||||
// We just drew to a software buffer, now draw this image onto the hardware device
|
||||
QPainter p(paint_device());
|
||||
p.drawPixmap(bounding_box.x(), bounding_box.y(), *aa_pixmap);
|
||||
delete aa_pixmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user