84 lines
2.6 KiB
C++
84 lines
2.6 KiB
C++
#include "modern-qt/utility/painter/helper.hh"
|
|
#include "image.hh"
|
|
|
|
#include <qevent.h>
|
|
#include <qpainter.h>
|
|
#include <qpainterpath.h>
|
|
#include <qpicture.h>
|
|
#include <qwidget.h>
|
|
|
|
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<double>(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<PainterResource> resource_origin {};
|
|
std::shared_ptr<PainterResource> resource_render {
|
|
std::make_shared<PainterResource>(QPixmap {}),
|
|
};
|
|
|
|
Image& self;
|
|
};
|