#include "modern-qt/utility/painter/helper.hh" #include "image.hh" #include #include #include #include #include using namespace creeper::image::internal; struct Image::Impl final { public: explicit Impl(Image& self) noexcept : self { self } { } auto paint_event(const QPaintEvent&) noexcept { const auto radius = get_radius(); const auto width = self.width(); const auto height = self.height(); if (request_regenerate) regenerate_pixmap(); auto painter = QPainter { &self }; painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setOpacity(opacity); if (resource_render && !resource_render->isNull()) { const auto& pixmap = *resource_render; const auto& point = QPointF { (width - pixmap.width()) / 2., (height - pixmap.height()) / 2., }; auto path = QPainterPath {}; path.addRoundedRect(border_width, border_width, width - 2 * border_width, height - 2 * border_width, radius - border_width, radius - border_width); painter.setBrush(Qt::NoBrush); painter.setPen(Qt::NoPen); painter.setClipPath(path); painter.setClipping(true); painter.drawPixmap(point, pixmap); } { painter.setClipping(false); util::PainterHelper { painter }.rounded_rectangle( Qt::transparent, border_color, border_width, self.rect(), radius, radius); } } auto resize_event(const QResizeEvent&) noexcept { request_regenerate = true; } private: auto regenerate_pixmap() noexcept -> void { if (!resource_origin) return; if (resource_origin->isNull()) return; const auto& _1 = *resource_origin; const auto& _2 = self.size(); *resource_render = content_scale.transform(_1, _2); request_regenerate = false; } auto get_radius() const noexcept -> double { return radius < 0 ? std::min(self.width(), self.height()) / 2. : radius; } public: ContentScale content_scale; bool request_regenerate = true; double border_width = 02.; QColor border_color = Qt::transparent; double radius = 10.; double opacity = 01.; std::shared_ptr resource_origin {}; std::shared_ptr resource_render { std::make_shared(QPixmap {}), }; Image& self; };