File indexing completed on 2024-05-12 16:02:06

0001 /*
0002  * SPDX-FileCopyrightText: 2016 Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 #include "KisVisualTriangleSelectorShape.h"
0007 
0008 #include <QColor>
0009 #include <QPainter>
0010 #include <QRect>
0011 #include <QtMath>
0012 
0013 #include "kis_debug.h"
0014 #include "kis_global.h"
0015 
0016 KisVisualTriangleSelectorShape::KisVisualTriangleSelectorShape(QWidget *parent,
0017                                                                Dimensions dimension,
0018                                                                const KoColorSpace *cs,
0019                                                                int channel1, int channel2,
0020                                                                const KoColorDisplayRendererInterface *displayRenderer,
0021                                                                int margin)
0022     : KisVisualColorSelectorShape(parent, dimension, cs, channel1, channel2, displayRenderer),
0023       m_margin(margin)
0024 {
0025     //qDebug() << "creating KisVisualTriangleSelectorShape" << this;
0026 }
0027 
0028 KisVisualTriangleSelectorShape::~KisVisualTriangleSelectorShape()
0029 {
0030     //qDebug() << "deleting KisVisualTriangleSelectorShape" << this;
0031 }
0032 
0033 void KisVisualTriangleSelectorShape::setBorderWidth(int /*width*/)
0034 {
0035     // triangle doesn't have a 1-dimensional mode
0036 }
0037 
0038 QRect KisVisualTriangleSelectorShape::getSpaceForSquare(QRect geom)
0039 {
0040     return geom;
0041 }
0042 
0043 QRect KisVisualTriangleSelectorShape::getSpaceForCircle(QRect geom)
0044 {
0045     return geom;
0046 }
0047 
0048 QRect KisVisualTriangleSelectorShape::getSpaceForTriangle(QRect geom)
0049 {
0050     return geom;
0051 }
0052 
0053 QPointF KisVisualTriangleSelectorShape::convertShapeCoordinateToWidgetCoordinate(QPointF coordinate) const
0054 {
0055     // margin serves to render the cursor, and triangle is rendered 1px larger than its active area
0056     qreal offset = m_margin + 1.0;
0057 
0058     qreal y = (coordinate.y() * (height() - 1 - 2 * offset)) + offset;
0059 
0060     qreal triWidth = width() - 1 - 2 * offset;
0061     qreal horizontalLineLength = coordinate.y() * triWidth;
0062     qreal horizontalLineStart = offset + 0.5 * (triWidth - horizontalLineLength);
0063 
0064     qreal x = coordinate.x() * horizontalLineLength + horizontalLineStart;
0065 
0066     return QPointF(x, y);
0067 }
0068 
0069 QPointF KisVisualTriangleSelectorShape::convertWidgetCoordinateToShapeCoordinate(QPointF coordinate) const
0070 {
0071     // margin serves to render the cursor, and triangle is rendered 1px larger than its active area
0072     qreal offset = m_margin + 1.0;
0073 
0074     qreal x = 0.5;
0075     qreal y = qBound(0.0, (coordinate.y() - offset)/(height() - 1 - 2 * offset), 1.0);
0076 
0077     if (y > 0) {
0078         qreal triWidth = width() - 1 - 2 * offset;
0079         qreal horizontalLineLength = y * triWidth;
0080         qreal horizontalLineStart = offset + 0.5 * (triWidth - horizontalLineLength);
0081 
0082         x = qBound(0.0, (coordinate.x() - horizontalLineStart) / horizontalLineLength, 1.0);
0083     }
0084 
0085     return QPointF(x, y);
0086 }
0087 
0088 QRegion KisVisualTriangleSelectorShape::getMaskMap()
0089 {
0090     const int cursorWidth = qMax(2 * m_margin, 2);
0091     QPolygon maskPoly;
0092     maskPoly << QPoint(qFloor(0.5 * (width() - cursorWidth)), 0)
0093              << QPoint(qCeil(0.5 * (width() + cursorWidth)), 0)
0094              << QPoint(width(), height() - cursorWidth)
0095              << QPoint(width(), height())
0096              << QPoint(0, height())
0097              << QPoint(0, height() - cursorWidth);
0098 
0099     return QRegion(maskPoly);
0100 }
0101 
0102 QImage KisVisualTriangleSelectorShape::renderAlphaMask() const
0103 {
0104     // Hi-DPI aware rendering requires that we determine the device pixel dimension;
0105     // actual widget size in device pixels is not accessible unfortunately, it might be 1px smaller...
0106     const int deviceWidth = qCeil(width() * devicePixelRatioF());
0107     const int deviceHeight = qCeil(height() * devicePixelRatioF());
0108 
0109     QImage alphaMask(deviceWidth, deviceHeight, QImage::Format_Alpha8);
0110     alphaMask.fill(0);
0111     alphaMask.setDevicePixelRatio(devicePixelRatioF());
0112     QPainter painter(&alphaMask);
0113     painter.setRenderHint(QPainter::Antialiasing);
0114     painter.setBrush(Qt::white);
0115     painter.setPen(Qt::NoPen);
0116     QPointF triangle[3] = {
0117         QPointF(0.5 * width(), m_margin),
0118         QPointF(m_margin, height() - m_margin),
0119         QPointF(width() - m_margin, height() - m_margin),
0120     };
0121     painter.drawConvexPolygon(triangle, 3);
0122 
0123     return alphaMask;
0124 }
0125 
0126 void KisVisualTriangleSelectorShape::drawCursor()
0127 {
0128     //qDebug() << this << "KisVisualTriangleSelectorShape::drawCursor: image needs update" << imagesNeedUpdate();
0129     QPointF cursorPoint = convertShapeCoordinateToWidgetCoordinate(getCursorPosition());
0130     QImage fullSelector = getImageMap();
0131     QColor col = getColorFromConverter(getCurrentColor());
0132     QPainter painter(&fullSelector);
0133     painter.setRenderHint(QPainter::Antialiasing);
0134 
0135     QBrush fill(Qt::SolidPattern);
0136 
0137     int cursorwidth = 5;
0138 
0139     painter.setPen(Qt::white);
0140     fill.setColor(Qt::white);
0141     painter.setBrush(fill);
0142     painter.drawEllipse(cursorPoint, cursorwidth, cursorwidth);
0143     fill.setColor(col);
0144     painter.setPen(Qt::black);
0145     painter.setBrush(fill);
0146     painter.drawEllipse(cursorPoint, cursorwidth-1.0, cursorwidth-1.0);
0147 
0148     painter.end();
0149     setFullImage(fullSelector);
0150 }