From ab0052e08e1d25e71f16ebb7b75d31256ae08eb6 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 14 Mar 2019 23:57:16 +1100 Subject: [PATCH] added shadow to rich text effect and removed old effect residue --- effects/effect.cpp | 3 ++ effects/internal/richtexteffect.cpp | 73 +++++++++++++++++++++++++++-- effects/internal/richtexteffect.h | 7 +++ effects/internal/texteffect.cpp | 67 +------------------------- olive.pro | 6 ++- ui/blur.cpp | 65 +++++++++++++++++++++++++ ui/blur.h | 13 +++++ ui/colorbutton.cpp | 5 -- ui/colorbutton.h | 2 - ui/embeddedfilechooser.cpp | 5 -- ui/embeddedfilechooser.h | 2 - ui/fontcombobox.cpp | 5 -- ui/fontcombobox.h | 4 +- ui/labelslider.cpp | 2 - ui/labelslider.h | 1 - ui/texteditex.cpp | 42 ----------------- 16 files changed, 163 insertions(+), 139 deletions(-) create mode 100644 ui/blur.cpp create mode 100644 ui/blur.h diff --git a/effects/effect.cpp b/effects/effect.cpp index b016c07bc..d5ae333d6 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -373,6 +373,9 @@ void Effect::copy_field_keyframes(EffectPtr e) { // Copy keyframes between effects copy_field->keyframes = field->keyframes; + + // Copy persistet data between effects + copy_field->persistent_data_ = field->persistent_data_; } } } diff --git a/effects/internal/richtexteffect.cpp b/effects/internal/richtexteffect.cpp index d03cd2085..84cb01f1f 100644 --- a/effects/internal/richtexteffect.cpp +++ b/effects/internal/richtexteffect.cpp @@ -1,8 +1,10 @@ #include "richtexteffect.h" #include +#include #include "timeline/clip.h" +#include "ui/blur.h" enum AutoscrollDirection { SCROLL_OFF, @@ -46,6 +48,34 @@ RichTextEffect::RichTextEffect(Clip *c, const EffectMeta *em) : autoscroll->AddItem(tr("Right"), SCROLL_RIGHT); autoscroll->SetColumnSpan(2); + EffectRow* shadow_row = new EffectRow(this, tr("Shadow")); + shadow_bool = new BoolField(shadow_row, "shadow"); + shadow_bool->SetColumnSpan(2); + + EffectRow* shadow_color_row = new EffectRow(this, tr("Shadow Color")); + shadow_color = new ColorField(shadow_color_row, "shadowcolor"); + shadow_color->SetColumnSpan(2); + + EffectRow* shadow_angle_row = new EffectRow(this, tr("Shadow Angle")); + shadow_angle = new DoubleField(shadow_angle_row, "shadowangle"); + shadow_angle->SetColumnSpan(2); + + EffectRow* shadow_distance_row = new EffectRow(this, tr("Shadow Distance")); + shadow_distance = new DoubleField(shadow_distance_row, "shadowdistance"); + shadow_distance->SetColumnSpan(2); + shadow_distance->SetMinimum(0); + + EffectRow* shadow_softness_row = new EffectRow(this, tr("Shadow Softness")); + shadow_softness = new DoubleField(shadow_softness_row, "shadowsoftness"); + shadow_softness->SetColumnSpan(2); + shadow_softness->SetMinimum(0); + + EffectRow* shadow_opacity_row = new EffectRow(this, tr("Shadow Opacity")); + shadow_opacity = new DoubleField(shadow_opacity_row, "shadowopacity"); + shadow_opacity->SetColumnSpan(2); + shadow_opacity->SetMinimum(0); + shadow_opacity->SetMaximum(100); + // Create default text text_val->SetValueAt(0, "" "" @@ -61,8 +91,6 @@ void RichTextEffect::redraw(double timecode) int width = img.width(); int height = img.height(); - img.fill(Qt::transparent); - int padding = qRound(padding_field->GetDoubleAt(timecode)); width -= 2 * padding; @@ -79,7 +107,7 @@ void RichTextEffect::redraw(double timecode) AutoscrollDirection auto_scroll_dir = static_cast(autoscroll->GetValueAt(timecode).toInt()); - double scroll_progress; + double scroll_progress = 0; if (auto_scroll_dir != SCROLL_OFF) { double clip_length_secs = double(parent_clip->length()) / parent_clip->media_frame_rate(); @@ -102,7 +130,7 @@ void RichTextEffect::redraw(double timecode) scroll_progress = 1.0 - scroll_progress; } - int doc_width = td.size().width(); + int doc_width = qRound(td.size().width()); translate_x += qRound(-doc_width + (img.width() + doc_width) * scroll_progress); } @@ -114,7 +142,7 @@ void RichTextEffect::redraw(double timecode) scroll_progress = 1.0 - scroll_progress; } - translate_y += qRound(-doc_height + (height + doc_height)*scroll_progress); + translate_y += qRound(-doc_height + (img.height() + doc_height)*scroll_progress); } @@ -122,8 +150,43 @@ void RichTextEffect::redraw(double timecode) clip_rect.translate(-translate_x, -translate_y); p.translate(translate_x, translate_y); + img.fill(Qt::transparent); + + // draw software shadow + if (shadow_bool->GetBoolAt(timecode)) { + + // calculate offset using distance and angle + double angle = shadow_angle->GetDoubleAt(timecode) * M_PI / 180.0; + double distance = qFloor(shadow_distance->GetDoubleAt(timecode)); + int shadow_x_offset = qRound(qCos(angle) * distance); + int shadow_y_offset = qRound(qSin(angle) * distance); + + p.translate(shadow_x_offset, shadow_y_offset); + clip_rect.translate(-shadow_x_offset, -shadow_y_offset); + + td.drawContents(&p, clip_rect); + + int blurSoftness = qFloor(shadow_softness->GetDoubleAt(timecode)); + if (blurSoftness > 0) { + olive::ui::blur(img, img.rect(), blurSoftness, true); + } + + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + + p.fillRect(img.rect(), shadow_color->GetColorAt(timecode)); + + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + + p.translate(-shadow_x_offset, -shadow_y_offset); + clip_rect.translate(shadow_x_offset, shadow_y_offset); + + + + } td.drawContents(&p, clip_rect); + + p.end(); } bool RichTextEffect::AlwaysUpdate() diff --git a/effects/internal/richtexteffect.h b/effects/internal/richtexteffect.h index a636be3d3..2a8a7978b 100644 --- a/effects/internal/richtexteffect.h +++ b/effects/internal/richtexteffect.h @@ -17,6 +17,13 @@ private: DoubleField* position_y; ComboField* vertical_align; ComboField* autoscroll; + + BoolField* shadow_bool; + DoubleField* shadow_angle; + DoubleField* shadow_distance; + ColorField* shadow_color; + DoubleField* shadow_softness; + DoubleField* shadow_opacity; }; #endif // RICHTEXTEFFECT_H diff --git a/effects/internal/texteffect.cpp b/effects/internal/texteffect.cpp index 8365a57ce..ee183f0b3 100644 --- a/effects/internal/texteffect.cpp +++ b/effects/internal/texteffect.cpp @@ -40,6 +40,7 @@ #include "ui/comboboxex.h" #include "ui/colorbutton.h" #include "ui/fontcombobox.h" +#include "ui/blur.h" #include "global/config.h" TextEffect::TextEffect(Clip* c, const EffectMeta* em) : @@ -154,70 +155,6 @@ TextEffect::TextEffect(Clip* c, const EffectMeta* em) : fragPath = "dropshadow.frag"; } -void blurred2(QImage& result, const QRect& rect, int radius, bool alphaOnly) { - int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; - int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; - - int r1 = rect.top(); - int r2 = rect.bottom(); - int c1 = rect.left(); - int c2 = rect.right(); - - int bpl = result.bytesPerLine(); - int rgba[4]; - unsigned char* p; - - int i1 = 0; - int i2 = 3; - - if (alphaOnly) - i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3); - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r1) + col * 4; - for (int i = i1; i <= i2; i++) - rgba[i] = p[i] << 4; - - p += bpl; - for (int j = r1; j < r2; j++, p += bpl) - for (int i = i1; i <= i2; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c1 * 4; - for (int i = i1; i <= i2; i++) - rgba[i] = p[i] << 4; - - p += 4; - for (int j = c1; j < c2; j++, p += 4) - for (int i = i1; i <= i2; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r2) + col * 4; - for (int i = i1; i <= i2; i++) - rgba[i] = p[i] << 4; - - p -= bpl; - for (int j = r1; j < r2; j++, p -= bpl) - for (int i = i1; i <= i2; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c2 * 4; - for (int i = i1; i <= i2; i++) - rgba[i] = p[i] << 4; - - p -= 4; - for (int j = c1; j < c2; j++, p -= 4) - for (int i = i1; i <= i2; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } -} - void TextEffect::redraw(double timecode) { QColor bkg = set_color_button->GetColorAt(timecode); bkg.setAlpha(0); @@ -340,7 +277,7 @@ void TextEffect::redraw(double timecode) { p.drawPath(shadow_path); int blurSoftness = qFloor(shadow_softness->GetDoubleAt(timecode)); - if (blurSoftness > 0) blurred2(img, img.rect(), blurSoftness, true); + if (blurSoftness > 0) olive::ui::blur(img, img.rect(), blurSoftness, true); } // draw outline diff --git a/olive.pro b/olive.pro index ccf476442..ba5fd9ca1 100644 --- a/olive.pro +++ b/olive.pro @@ -173,7 +173,8 @@ SOURCES += \ effects/transition.cpp \ ui/styling.cpp \ undo/undostack.cpp \ - effects/internal/richtexteffect.cpp + effects/internal/richtexteffect.cpp \ + ui/blur.cpp HEADERS += \ ui/mainwindow.h \ @@ -300,7 +301,8 @@ HEADERS += \ effects/transition.h \ ui/styling.h \ undo/undostack.h \ - effects/internal/richtexteffect.h + effects/internal/richtexteffect.h \ + ui/blur.h FORMS += diff --git a/ui/blur.cpp b/ui/blur.cpp new file mode 100644 index 000000000..ecdf7442a --- /dev/null +++ b/ui/blur.cpp @@ -0,0 +1,65 @@ +#include "blur.h" + +void olive::ui::blur(QImage& result, const QRect& rect, int radius, bool alphaOnly) { + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + int i1 = 0; + int i2 = 3; + + if (alphaOnly) + i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3); + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = i1; i <= i2; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = i1; i <= i2; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = i1; i <= i2; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = i1; i <= i2; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = i1; i <= i2; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = i1; i <= i2; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = i1; i <= i2; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = i1; i <= i2; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } +} diff --git a/ui/blur.h b/ui/blur.h new file mode 100644 index 000000000..ddf44fb86 --- /dev/null +++ b/ui/blur.h @@ -0,0 +1,13 @@ +#ifndef BLUR_H +#define BLUR_H + +#include +#include + +namespace olive { + namespace ui { + void blur(QImage& result, const QRect& rect, int radius, bool alphaOnly); + } +} + +#endif // BLUR_H diff --git a/ui/colorbutton.cpp b/ui/colorbutton.cpp index e841707b1..9423b616c 100644 --- a/ui/colorbutton.cpp +++ b/ui/colorbutton.cpp @@ -33,15 +33,10 @@ QColor ColorButton::get_color() { } void ColorButton::set_color(QColor c) { - previousColor = color; color = c; set_button_color(); } -const QColor &ColorButton::getPreviousValue() { - return previousColor; -} - void ColorButton::set_button_color() { QPalette pal = palette(); pal.setColor(QPalette::Button, color); diff --git a/ui/colorbutton.h b/ui/colorbutton.h index 944378b8c..e67ca8cd5 100644 --- a/ui/colorbutton.h +++ b/ui/colorbutton.h @@ -31,10 +31,8 @@ public: ColorButton(QWidget* parent = nullptr); QColor get_color(); void set_color(QColor c); - const QColor& getPreviousValue(); private: QColor color; - QColor previousColor; void set_button_color(); signals: void color_changed(const QColor& c); diff --git a/ui/embeddedfilechooser.cpp b/ui/embeddedfilechooser.cpp index 99e35905d..4a5bfbec2 100644 --- a/ui/embeddedfilechooser.cpp +++ b/ui/embeddedfilechooser.cpp @@ -42,12 +42,7 @@ const QString &EmbeddedFileChooser::getFilename() { return filename; } -const QString &EmbeddedFileChooser::getPreviousValue() { - return old_filename; -} - void EmbeddedFileChooser::setFilename(const QString &s) { - old_filename = filename; filename = s; update_label(); emit changed(filename); diff --git a/ui/embeddedfilechooser.h b/ui/embeddedfilechooser.h index 9d15d1264..8022022ee 100644 --- a/ui/embeddedfilechooser.h +++ b/ui/embeddedfilechooser.h @@ -31,14 +31,12 @@ public: EmbeddedFileChooser(QWidget* parent = 0); const QString& getFilename(); - const QString& getPreviousValue(); void setFilename(const QString& s); signals: void changed(const QString& s); private: QLabel* file_label; QString filename; - QString old_filename; void update_label(); private slots: void browse(); diff --git a/ui/fontcombobox.cpp b/ui/fontcombobox.cpp index 4e5547c26..c8e10d920 100644 --- a/ui/fontcombobox.cpp +++ b/ui/fontcombobox.cpp @@ -30,11 +30,6 @@ FontCombobox::FontCombobox(QWidget* parent) : QComboBox(parent) { connect(this, SIGNAL(currentTextChanged(QString)), this, SLOT(updateInternals())); } -const QString& FontCombobox::getPreviousValue() { - return previousValue; -} - void FontCombobox::updateInternals() { - previousValue = value; value = currentText(); } diff --git a/ui/fontcombobox.h b/ui/fontcombobox.h index 90fb24813..54a7b0823 100644 --- a/ui/fontcombobox.h +++ b/ui/fontcombobox.h @@ -26,12 +26,10 @@ class FontCombobox : public QComboBox { Q_OBJECT public: - FontCombobox(QWidget* parent = 0); - const QString &getPreviousValue(); + FontCombobox(QWidget* parent = nullptr); private slots: void updateInternals(); private: - QString previousValue; QString value; }; diff --git a/ui/labelslider.cpp b/ui/labelslider.cpp index 94751124e..f83165abf 100644 --- a/ui/labelslider.cpp +++ b/ui/labelslider.cpp @@ -245,8 +245,6 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) { drag_proc = false; - previous_value = drag_start_value; - emit valueChanged(internal_value); } else { diff --git a/ui/labelslider.h b/ui/labelslider.h index e7550513c..c1402d1de 100644 --- a/ui/labelslider.h +++ b/ui/labelslider.h @@ -160,7 +160,6 @@ private: double default_value; double internal_value; double drag_start_value; - double previous_value; int decimal_places; diff --git a/ui/texteditex.cpp b/ui/texteditex.cpp index 1688042b1..7c558ce98 100644 --- a/ui/texteditex.cpp +++ b/ui/texteditex.cpp @@ -21,48 +21,6 @@ #include "texteditex.h" #include - -/* -TextEditEx::TextEditEx(QWidget *parent) : QTextEdit(parent) { - setUndoRedoEnabled(false); - connect(this, SIGNAL(textChanged()), this, SLOT(updateInternals())); - connect(this, SIGNAL(updateSelf()), this, SLOT(updateText())); -} - -const QString& TextEditEx::getPlainTextEx() { - return text; -} - -void TextEditEx::setPlainTextEx(const QString &t) { - previousText = text; - text = t; - emit updateSelf(); -} - -const QString &TextEditEx::getPreviousValue() { - return previousText; -} - -void TextEditEx::updateInternals() { - previousText = text; - text = toPlainText(); -} - -void TextEditEx::updateText() { - blockSignals(true); - - int pos = textCursor().position(); - - setPlainText(text); - - QTextCursor newCursor(document()); - newCursor.setPosition(pos); - setTextCursor(newCursor); - - blockSignals(false); -} -*/ - #include #include "dialogs/texteditdialog.h"