renderer.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * renderer.cpp - renderer
  3. * Copyright (C) 2017 caryoscelus
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <boost/filesystem/path.hpp>
  19. #include <fmt/format.h>
  20. #include <QDebug>
  21. #include <QPixmap>
  22. #include <core/renderers/svg_renderer.h>
  23. #include <util/strings.h>
  24. #include <widgets/canvas.h>
  25. #include "renderer.h"
  26. using namespace fmt::literals;
  27. namespace rainynite::studio {
  28. Renderer::Renderer(Canvas* canvas_) :
  29. canvas(canvas_)
  30. {
  31. connect(this, SIGNAL(redraw_signal()), this, SLOT(redraw()));
  32. setup_renderer();
  33. }
  34. Renderer::~Renderer() {
  35. quit();
  36. }
  37. void Renderer::set_fname(string fname_) {
  38. fname = fname_;
  39. }
  40. void Renderer::set_context(shared_ptr<EditorContext> context_) {
  41. ContextListener::set_context(context_);
  42. get_context()->changed_time().connect([this](core::Time){
  43. redraw();
  44. });
  45. }
  46. void Renderer::setup_renderer() {
  47. renderer = make_shared<core::renderers::SvgRenderer>();
  48. render_thread = std::thread([this]() {
  49. while (!renderer_quit) {
  50. if (renderer_queue.size() > 0) {
  51. renderer_mutex.lock();
  52. auto ctx = std::move(renderer_queue.front());
  53. renderer_queue.pop();
  54. renderer_mutex.unlock();
  55. try {
  56. renderer->render(std::move(ctx));
  57. } catch (std::exception const& ex) {
  58. auto msg = util::str("Uncaught exception while rendering:\n{}"_format(ex.what()));
  59. qDebug() << msg;
  60. }
  61. Q_EMIT redraw_signal();
  62. } else {
  63. std::this_thread::sleep_for(std::chrono::milliseconds(128));
  64. }
  65. }
  66. });
  67. }
  68. void Renderer::render_period(core::TimePeriod const& period) {
  69. if (get_core_context()->get_document()) {
  70. auto rsettings = core::renderers::SvgRendererSettings();
  71. rsettings.render_pngs = true;
  72. rsettings.keep_alive = true;
  73. rsettings.extra_style = extra_style;
  74. rsettings.path = fname;
  75. get_core_context()->mod_render_settings() = rsettings;
  76. auto ctx = *get_core_context();
  77. ctx.set_period(period);
  78. std::lock_guard<std::mutex> lock(renderer_mutex);
  79. renderer_queue.push(ctx);
  80. }
  81. }
  82. void Renderer::render() {
  83. render_period(get_core_context()->get_period());
  84. }
  85. void Renderer::render_frame() {
  86. auto time = get_core_context()->get_time();
  87. auto time_end = time;
  88. ++time_end;
  89. render_period({time, time_end});
  90. }
  91. void Renderer::stop_render() {
  92. renderer->stop();
  93. }
  94. void Renderer::redraw() {
  95. // TODO: fix this mess
  96. boost::filesystem::path base_path = fname;
  97. base_path.remove_filename();
  98. auto path = base_path/"renders"/"{:.3f}.png"_format(get_core_context()->get_time().get_seconds());
  99. set_mainarea_image(path.string());
  100. }
  101. void Renderer::toggle_extra_style(bool checked) {
  102. extra_style = checked;
  103. }
  104. void Renderer::set_mainarea_image(string const& fname) {
  105. QPixmap pixmap;
  106. pixmap.load(util::str(fname));
  107. canvas->set_main_image(pixmap);
  108. }
  109. void Renderer::quit() {
  110. stop_render();
  111. if (render_thread.joinable()) {
  112. renderer_quit = true;
  113. render_thread.join();
  114. }
  115. }
  116. } // namespace rainynite::studio