From 469b1e92d068037bdadbe2b5ca7bc99e8642fe2a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sat, 13 Jun 2020 03:01:35 +1000 Subject: [PATCH] nodes: implemented basic text node --- app/node/factory.cpp | 3 + app/node/factory.h | 1 + app/node/generator/CMakeLists.txt | 1 + app/node/generator/text/CMakeLists.txt | 22 +++++ app/node/generator/text/text.cpp | 119 +++++++++++++++++++++++++ app/node/generator/text/text.h | 55 ++++++++++++ app/widget/timelinewidget/tool/add.cpp | 12 ++- 7 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 app/node/generator/text/CMakeLists.txt create mode 100644 app/node/generator/text/text.cpp create mode 100644 app/node/generator/text/text.h diff --git a/app/node/factory.cpp b/app/node/factory.cpp index dfd2fef61..ee2fe3892 100644 --- a/app/node/factory.cpp +++ b/app/node/factory.cpp @@ -27,6 +27,7 @@ #include "generator/matrix/matrix.h" #include "generator/polygon/polygon.h" #include "generator/solid/solid.h" +#include "generator/text/text.h" #include "filter/blur/blur.h" #include "filter/stroke/stroke.h" #include "input/media/video/video.h" @@ -201,6 +202,8 @@ Node *NodeFactory::CreateInternal(const NodeFactory::InternalID &id) return new MergeNode(); case kStrokeFilter: return new StrokeFilterNode(); + case kTextGenerator: + return new TextGenerator(); case kInternalNodeCount: break; diff --git a/app/node/factory.h b/app/node/factory.h index c82b2b63e..b5c1b6f0f 100644 --- a/app/node/factory.h +++ b/app/node/factory.h @@ -49,6 +49,7 @@ public: kSolidGenerator, kMerge, kStrokeFilter, + kTextGenerator, // Count value kInternalNodeCount diff --git a/app/node/generator/CMakeLists.txt b/app/node/generator/CMakeLists.txt index 52d74e469..264d7dade 100644 --- a/app/node/generator/CMakeLists.txt +++ b/app/node/generator/CMakeLists.txt @@ -17,6 +17,7 @@ add_subdirectory(matrix) add_subdirectory(polygon) add_subdirectory(solid) +add_subdirectory(text) set(OLIVE_SOURCES ${OLIVE_SOURCES} diff --git a/app/node/generator/text/CMakeLists.txt b/app/node/generator/text/CMakeLists.txt new file mode 100644 index 000000000..ec2049f42 --- /dev/null +++ b/app/node/generator/text/CMakeLists.txt @@ -0,0 +1,22 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + node/generator/text/text.h + node/generator/text/text.cpp + PARENT_SCOPE +) diff --git a/app/node/generator/text/text.cpp b/app/node/generator/text/text.cpp new file mode 100644 index 000000000..78a09332a --- /dev/null +++ b/app/node/generator/text/text.cpp @@ -0,0 +1,119 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "text.h" + +#include + +OLIVE_NAMESPACE_ENTER + +TextGenerator::TextGenerator() +{ + QString default_str = QStringLiteral("
%1
").arg(tr("Sample Text")); + + text_input_ = new NodeInput(QStringLiteral("text_in"), + NodeParam::kText, + default_str); + AddInput(text_input_); + + color_input_ = new NodeInput(QStringLiteral("color_in"), + NodeParam::kColor, + QVariant::fromValue(Color(1.0f, 1.0f, 1.0))); + AddInput(color_input_); +} + +Node *TextGenerator::copy() const +{ + return new TextGenerator(); +} + +QString TextGenerator::Name() const +{ + return tr("Text"); +} + +QString TextGenerator::id() const +{ + return QStringLiteral("org.olivevideoeditor.Olive.textgenerator"); +} + +QList TextGenerator::Category() const +{ + return {kCategoryGenerator}; +} + +QString TextGenerator::Description() const +{ + return tr("Generate rich text."); +} + +void TextGenerator::Retranslate() +{ + text_input_->set_name(tr("Text")); + color_input_->set_name(tr("Color")); +} + +NodeValueTable TextGenerator::Value(NodeValueDatabase &value) const +{ + GenerateJob job; + job.InsertValue(text_input_, value); + job.InsertValue(color_input_, value); + job.SetAlphaChannelRequired(true); + + NodeValueTable table = value.Merge(); + + if (!job.GetValue(text_input_).data().toString().isEmpty()) { + table.Push(NodeParam::kGenerateJob, QVariant::fromValue(job), this); + } + + return table; +} + +void TextGenerator::GenerateFrame(FramePtr frame, const GenerateJob& job) const +{ + // This could probably be more optimized, but for now we use Qt to draw to a QImage. + // QImages only support integer pixels and we use float pixels, so what we do here is draw onto + // a single-channel QImage (alpha only) and then transplant that alpha channel to our float buffer + // with correct float RGB. + QImage img(frame->width(), frame->height(), QImage::Format_Grayscale8); + img.fill(0); + + QTextDocument text_doc; + text_doc.setHtml(job.GetValue(text_input_).data().toString()); + text_doc.setTextWidth(frame->video_params().width()); + + // Draw rich text onto image + QPainter p(&img); + p.scale(1.0 / frame->video_params().divider(), 1.0 / frame->video_params().divider()); + text_doc.drawContents(&p); + + // Transplant alpha channel to frame + Color rgb = job.GetValue(color_input_).data().value(); + for (int x=0; xwidth(); x++) { + for (int y=0; yheight(); y++) { + uchar src_alpha = img.bits()[img.bytesPerLine() * y + x]; + float alpha = float(src_alpha) / 255.0f; + + frame->set_pixel(x, y, Color(rgb.red() * alpha, rgb.green() * alpha, rgb.blue() * alpha, alpha)); + } + } +} + +OLIVE_NAMESPACE_EXIT diff --git a/app/node/generator/text/text.h b/app/node/generator/text/text.h new file mode 100644 index 000000000..3f28626c2 --- /dev/null +++ b/app/node/generator/text/text.h @@ -0,0 +1,55 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef TEXTGENERATOR_H +#define TEXTGENERATOR_H + +#include "node/node.h" + +OLIVE_NAMESPACE_ENTER + +class TextGenerator : public Node +{ +public: + TextGenerator(); + + virtual Node* copy() const override; + + virtual QString Name() const override; + virtual QString id() const override; + virtual QList Category() const override; + virtual QString Description() const override; + + virtual void Retranslate() override; + + virtual NodeValueTable Value(NodeValueDatabase& value) const override; + + virtual void GenerateFrame(FramePtr frame, const GenerateJob &job) const override; + +private: + NodeInput* text_input_; + + NodeInput* color_input_; + +}; + +OLIVE_NAMESPACE_EXIT + +#endif // TEXTGENERATOR_H diff --git a/app/widget/timelinewidget/tool/add.cpp b/app/widget/timelinewidget/tool/add.cpp index 19e6f5322..1e1a538e0 100644 --- a/app/widget/timelinewidget/tool/add.cpp +++ b/app/widget/timelinewidget/tool/add.cpp @@ -124,8 +124,18 @@ void TimelineWidget::AddTool::MouseRelease(TimelineViewMouseEvent *event) new NodeEdgeAddCommand(solid->output(), clip->texture_input(), command); break; } - case OLIVE_NAMESPACE::Tool::kAddableBars: case OLIVE_NAMESPACE::Tool::kAddableTitle: + { + Node* text = NodeFactory::CreateFromID(QStringLiteral("org.olivevideoeditor.Olive.textgenerator")); + + new NodeAddCommand(graph, + text, + command); + + new NodeEdgeAddCommand(text->output(), clip->texture_input(), command); + break; + } + case OLIVE_NAMESPACE::Tool::kAddableBars: case OLIVE_NAMESPACE::Tool::kAddableTone: // Not implemented yet qWarning() << "Unimplemented add object:" << Core::instance()->selected_addable_object();