Kirigami2

shadowedrectanglenode.cpp
1 /*
2  * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 #include "shadowedrectanglenode.h"
8 #include "shadowedborderrectanglematerial.h"
9 
10 QColor premultiply(const QColor &color)
11 {
12  return QColor::fromRgbF(color.redF() * color.alphaF(), //
13  color.greenF() * color.alphaF(),
14  color.blueF() * color.alphaF(),
15  color.alphaF());
16 }
17 
18 ShadowedRectangleNode::ShadowedRectangleNode()
19 {
21  setGeometry(m_geometry);
22 
24 }
25 
27 {
28  // We can achieve more performant shaders by splitting the two into separate
29  // shaders. This requires separating the materials as well. So when
30  // borderWidth is increased to something where the border should be visible,
31  // switch to the with-border material. Otherwise use the no-border version.
32 
33  if (enabled) {
34  if (!m_material || m_material->type() == borderlessMaterialType()) {
35  auto newMaterial = createBorderMaterial();
36  newMaterial->shaderType = m_shaderType;
37  setMaterial(newMaterial);
38  m_material = newMaterial;
39  m_rect = QRectF{};
41  }
42  } else {
43  if (!m_material || m_material->type() == borderMaterialType()) {
44  auto newMaterial = createBorderlessMaterial();
45  newMaterial->shaderType = m_shaderType;
46  setMaterial(newMaterial);
47  m_material = newMaterial;
48  m_rect = QRectF{};
50  }
51  }
52 }
53 
54 void ShadowedRectangleNode::setRect(const QRectF &rect)
55 {
56  if (rect == m_rect) {
57  return;
58  }
59 
60  m_rect = rect;
61 
62  QVector2D newAspect{1.0, 1.0};
63  if (m_rect.width() >= m_rect.height()) {
64  newAspect.setX(m_rect.width() / m_rect.height());
65  } else {
66  newAspect.setY(m_rect.height() / m_rect.width());
67  }
68 
69  if (m_material->aspect != newAspect) {
70  m_material->aspect = newAspect;
72  m_aspect = newAspect;
73  }
74 }
75 
76 void ShadowedRectangleNode::setSize(qreal size)
77 {
78  auto minDimension = std::min(m_rect.width(), m_rect.height());
79  float uniformSize = (size / minDimension) * 2.0;
80 
81  if (!qFuzzyCompare(m_material->size, uniformSize)) {
82  m_material->size = uniformSize;
84  m_size = size;
85  }
86 }
87 
88 void ShadowedRectangleNode::setRadius(const QVector4D &radius)
89 {
90  float minDimension = std::min(m_rect.width(), m_rect.height());
91  auto uniformRadius = QVector4D{std::min(radius.x() * 2.0f / minDimension, 1.0f),
92  std::min(radius.y() * 2.0f / minDimension, 1.0f),
93  std::min(radius.z() * 2.0f / minDimension, 1.0f),
94  std::min(radius.w() * 2.0f / minDimension, 1.0f)};
95 
96  if (m_material->radius != uniformRadius) {
97  m_material->radius = uniformRadius;
99  m_radius = radius;
100  }
101 }
102 
103 void ShadowedRectangleNode::setColor(const QColor &color)
104 {
105  auto premultiplied = premultiply(color);
106  if (m_material->color != premultiplied) {
107  m_material->color = premultiplied;
109  }
110 }
111 
112 void ShadowedRectangleNode::setShadowColor(const QColor &color)
113 {
114  auto premultiplied = premultiply(color);
115  if (m_material->shadowColor != premultiplied) {
116  m_material->shadowColor = premultiplied;
118  }
119 }
120 
121 void ShadowedRectangleNode::setOffset(const QVector2D &offset)
122 {
123  auto minDimension = std::min(m_rect.width(), m_rect.height());
124  auto uniformOffset = offset / minDimension;
125 
126  if (m_material->offset != uniformOffset) {
127  m_material->offset = uniformOffset;
129  m_offset = offset;
130  }
131 }
132 
133 void ShadowedRectangleNode::setBorderWidth(qreal width)
134 {
135  if (m_material->type() != borderMaterialType()) {
136  return;
137  }
138 
139  auto minDimension = std::min(m_rect.width(), m_rect.height());
140  float uniformBorderWidth = width / minDimension;
141 
142  auto borderMaterial = static_cast<ShadowedBorderRectangleMaterial *>(m_material);
143  if (!qFuzzyCompare(borderMaterial->borderWidth, uniformBorderWidth)) {
144  borderMaterial->borderWidth = uniformBorderWidth;
146  m_borderWidth = width;
147  }
148 }
149 
150 void ShadowedRectangleNode::setBorderColor(const QColor &color)
151 {
152  if (m_material->type() != borderMaterialType()) {
153  return;
154  }
155 
156  auto borderMaterial = static_cast<ShadowedBorderRectangleMaterial *>(m_material);
157  auto premultiplied = premultiply(color);
158  if (borderMaterial->borderColor != premultiplied) {
159  borderMaterial->borderColor = premultiplied;
161  }
162 }
163 
164 void ShadowedRectangleNode::setShaderType(ShadowedRectangleMaterial::ShaderType type)
165 {
166  m_shaderType = type;
167 }
168 
170 {
171  auto rect = m_rect;
172  if (m_shaderType == ShadowedRectangleMaterial::ShaderType::Standard) {
173  rect = rect.adjusted(-m_size * m_aspect.x(), //
174  -m_size * m_aspect.y(),
175  m_size * m_aspect.x(),
176  m_size * m_aspect.y());
177 
178  auto offsetLength = m_offset.length();
179  rect = rect.adjusted(-offsetLength * m_aspect.x(), //
180  -offsetLength * m_aspect.y(),
181  offsetLength * m_aspect.x(),
182  offsetLength * m_aspect.y());
183  }
184 
185  QSGGeometry::updateTexturedRectGeometry(m_geometry, rect, QRectF{0.0, 0.0, 1.0, 1.0});
187 }
188 
189 ShadowedRectangleMaterial *ShadowedRectangleNode::createBorderlessMaterial()
190 {
191  return new ShadowedRectangleMaterial{};
192 }
193 
194 ShadowedBorderRectangleMaterial *ShadowedRectangleNode::createBorderMaterial()
195 {
196  return new ShadowedBorderRectangleMaterial{};
197 }
198 
199 QSGMaterialType *ShadowedRectangleNode::borderlessMaterialType()
200 {
201  return &ShadowedRectangleMaterial::staticType;
202 }
203 
204 QSGMaterialType *ShadowedRectangleNode::borderMaterialType()
205 {
206  return &ShadowedBorderRectangleMaterial::staticType;
207 }
qreal greenF() const const
qreal redF() const const
qreal blueF() const const
void setFlags(QSGNode::Flags f, bool enabled)
QRectF adjusted(qreal dx1, qreal dy1, qreal dx2, qreal dy2) const const
QColor fromRgbF(qreal r, qreal g, qreal b, qreal a)
void setGeometry(QSGGeometry *geometry)
A material rendering a rectangle with a shadow and a border.
void updateGeometry()
Update the geometry for this node.
void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
void setX(float x)
void setMaterial(QSGMaterial *material)
void markDirty(QSGNode::DirtyState bits)
qreal alphaF() const const
A material rendering a rectangle with a shadow.
void setBorderEnabled(bool enabled)
Set whether to draw a border.
qreal width() const const
QSGNode::NodeType type() const const
float x() const const
float y() const const
float w() const const
float x() const const
float y() const const
float z() const const
const QSGGeometry::AttributeSet & defaultAttributes_TexturedPoint2D()
float length() const const
qreal height() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 04:14:24 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.