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