File indexing completed on 2024-05-12 04:19:38

0001 /*
0002  * SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include "alphabackgrounditem.h"
0008 
0009 #include <QApplication>
0010 #include <QPainter>
0011 
0012 using namespace Gwenview;
0013 
0014 AlphaBackgroundItem::AlphaBackgroundItem(AbstractImageView *parent)
0015     : QGraphicsItem(parent)
0016     , mParent(parent)
0017 {
0018 }
0019 
0020 AlphaBackgroundItem::~AlphaBackgroundItem() = default;
0021 
0022 AbstractImageView::AlphaBackgroundMode AlphaBackgroundItem::mode() const
0023 {
0024     return mMode;
0025 }
0026 
0027 void Gwenview::AlphaBackgroundItem::setMode(AbstractImageView::AlphaBackgroundMode mode)
0028 {
0029     if (mode == mMode) {
0030         return;
0031     }
0032 
0033     mMode = mode;
0034     update();
0035 }
0036 
0037 QColor AlphaBackgroundItem::color()
0038 {
0039     return mColor;
0040 }
0041 
0042 void AlphaBackgroundItem::setColor(const QColor &color)
0043 {
0044     if (color == mColor) {
0045         return;
0046     }
0047 
0048     mColor = color;
0049     update();
0050 }
0051 
0052 void AlphaBackgroundItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/)
0053 {
0054     // We need to floor the image size. Unfortunately, QPointF and QSizeF both
0055     // _round_ when converting instead of flooring. This means that we need to
0056     // manually do the flooring here, because we otherwise run into pixel
0057     // alignment issues with the image that is drawn on top of the background.
0058     const auto width = int((mParent->documentSize().width() / qApp->devicePixelRatio()) * mParent->zoom());
0059     const auto height = int((mParent->documentSize().height() / qApp->devicePixelRatio()) * mParent->zoom());
0060     const auto imageRect = QRectF{mParent->imageOffset().toPoint(), QSize{width, height}};
0061 
0062     switch (mMode) {
0063     case AbstractImageView::AlphaBackgroundNone:
0064         // No background, do not paint anything.
0065         break;
0066     case AbstractImageView::AlphaBackgroundCheckBoard: {
0067         if (!mCheckBoardTexture) {
0068             createCheckBoardTexture();
0069         }
0070 
0071         painter->drawTiledPixmap(imageRect, *mCheckBoardTexture, mParent->scrollPos());
0072         break;
0073     }
0074     case AbstractImageView::AlphaBackgroundSolid:
0075         painter->fillRect(imageRect, mColor);
0076         break;
0077     default:
0078         break;
0079     }
0080 }
0081 
0082 QRectF AlphaBackgroundItem::boundingRect() const
0083 {
0084     return mParent->boundingRect();
0085 }
0086 
0087 void AlphaBackgroundItem::createCheckBoardTexture()
0088 {
0089     mCheckBoardTexture = std::make_unique<QPixmap>(32, 32);
0090     QPainter painter(mCheckBoardTexture.get());
0091     painter.fillRect(mCheckBoardTexture->rect(), QColor(128, 128, 128));
0092     const QColor light = QColor(192, 192, 192);
0093     painter.fillRect(0, 0, 16, 16, light);
0094     painter.fillRect(16, 16, 16, 16, light);
0095     // Don't set the pixmap's devicePixelRatio, just let Qt take care of scaling
0096     // this, otherwise we get some ugly glitches.
0097 }