File indexing completed on 2025-01-05 04:01:16
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QBuffer> 0010 #include <QImage> 0011 #include <QPainter> 0012 0013 #include "io/mime/mime_serializer.hpp" 0014 #include "io/io_registry.hpp" 0015 #include "model/document.hpp" 0016 #include "model/shapes/image.hpp" 0017 #include "model/assets/assets.hpp" 0018 0019 namespace glaxnimate::io::raster { 0020 0021 class RasterMime : public io::mime::MimeSerializer 0022 { 0023 public: 0024 QString slug() const override { return "raster"; } 0025 QString name() const override { return i18n("Raster Image"); } 0026 QStringList mime_types() const override { return {"image/png"}; } 0027 0028 QByteArray serialize(const std::vector<model::DocumentNode*>& selection) const override 0029 { 0030 QByteArray data; 0031 QBuffer buffer(&data); 0032 to_image(selection).save(&buffer, "PNG"); 0033 return data; 0034 } 0035 0036 bool can_deserialize() const override { return true; } 0037 0038 void to_mime_data(QMimeData& mime, const std::vector<model::DocumentNode*>& objects) const override 0039 { 0040 mime.setImageData(to_image(objects)); 0041 } 0042 0043 static QImage to_image(const std::vector<model::DocumentNode*>& selection) 0044 { 0045 if ( selection.empty() ) 0046 return {}; 0047 0048 std::vector<model::VisualNode*> visual_nodes; 0049 visual_nodes.reserve(selection.size()); 0050 QRectF box; 0051 0052 for ( auto node : selection ) 0053 { 0054 if ( auto visual = node->cast<model::VisualNode>() ) 0055 { 0056 visual_nodes.push_back(visual); 0057 box |= visual->local_bounding_rect(visual->time()); 0058 } 0059 } 0060 0061 QImage image(box.size().toSize(), QImage::Format_ARGB32); 0062 image.fill(Qt::transparent); 0063 QPainter painter(&image); 0064 painter.setRenderHint(QPainter::Antialiasing); 0065 painter.translate(-box.topLeft()); 0066 for ( auto visual : visual_nodes ) 0067 { 0068 visual->paint(&painter, visual->time(), model::VisualNode::Render); 0069 } 0070 return image; 0071 } 0072 0073 static QImage frame_to_image(const model::VisualNode* node, model::FrameTime time) 0074 { 0075 if ( !node ) 0076 return {}; 0077 0078 QImage image(node->local_bounding_rect(time).size().toSize(), QImage::Format_ARGB32); 0079 image.fill(Qt::transparent); 0080 QPainter painter(&image); 0081 painter.setRenderHint(QPainter::Antialiasing); 0082 node->paint(&painter, time, model::VisualNode::Render); 0083 return image; 0084 } 0085 0086 io::mime::DeserializedData deserialize(const QByteArray& data) const override 0087 { 0088 io::mime::DeserializedData out; 0089 out.initialize_data(); 0090 auto bmp = out.document->assets()->images->values.insert(std::make_unique<model::Bitmap>(out.document.get())); 0091 bmp->data.set(data); 0092 auto img = std::make_unique<model::Image>(out.document.get()); 0093 img->image.set(bmp); 0094 QPointF p(bmp->pixmap().width() / 2.0, bmp->pixmap().height() / 2.0); 0095 img->transform->anchor_point.set(p); 0096 img->transform->position.set(p); 0097 out.main->shapes.insert(std::move(img)); 0098 return out; 0099 } 0100 0101 private: 0102 static Autoreg<RasterMime> autoreg; 0103 }; 0104 0105 } // namespace glaxnimate::io::mime 0106