File indexing completed on 2024-05-19 04:29:30

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