Krita Source Code Documentation
Loading...
Searching...
No Matches
KoPatternBackground.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2008 Jan Hambrecht <jaham@gmx.net>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
9#include <KoXmlNS.h>
10#include <KoUnit.h>
11
12#include <FlakeDebug.h>
13
14#include <QBrush>
15#include <QPainter>
16#include <QPainterPath>
17#include <QSharedData>
18
19class KoPatternBackground::Private : public QSharedData
20{
21public:
23 : QSharedData()
26 {
27 }
28
30 {
31 }
32
33 QSizeF targetSize() const {
34 QSizeF size = pattern.size();
35 if (targetImageSizePercent.width() > 0.0)
36 size.setWidth(0.01 * targetImageSizePercent.width() * size.width());
37 else if (targetImageSize.width() > 0.0)
38 size.setWidth(targetImageSize.width());
39 if (targetImageSizePercent.height() > 0.0)
40 size.setHeight(0.01 * targetImageSizePercent.height() * size.height());
41 else if (targetImageSize.height() > 0.0)
42 size.setHeight(targetImageSize.height());
43
44 return size;
45 }
46
47 QPointF offsetFromRect(const QRectF &fillRect, const QSizeF &imageSize) const {
48 QPointF offset;
49 switch (refPoint) {
51 offset = fillRect.topLeft();
52 break;
54 offset.setX(fillRect.center().x() - 0.5 * imageSize.width());
55 offset.setY(fillRect.top());
56 break;
58 offset.setX(fillRect.right() - imageSize.width());
59 offset.setY(fillRect.top());
60 break;
62 offset.setX(fillRect.left());
63 offset.setY(fillRect.center().y() - 0.5 * imageSize.height());
64 break;
66 offset.setX(fillRect.center().x() - 0.5 * imageSize.width());
67 offset.setY(fillRect.center().y() - 0.5 * imageSize.height());
68 break;
70 offset.setX(fillRect.right() - imageSize.width());
71 offset.setY(fillRect.center().y() - 0.5 * imageSize.height());
72 break;
74 offset.setX(fillRect.left());
75 offset.setY(fillRect.bottom() - imageSize.height());
76 break;
78 offset.setX(fillRect.center().x() - 0.5 * imageSize.width());
79 offset.setY(fillRect.bottom() - imageSize.height());
80 break;
82 offset.setX(fillRect.right() - imageSize.width());
83 offset.setY(fillRect.bottom() - imageSize.height());
84 break;
85 default:
86 break;
87 }
88 if (refPointOffsetPercent.x() > 0.0)
89 offset += QPointF(0.01 * refPointOffsetPercent.x() * imageSize.width(), 0);
90 if (refPointOffsetPercent.y() > 0.0)
91 offset += QPointF(0, 0.01 * refPointOffsetPercent.y() * imageSize.height());
92
93 return offset;
94 }
95
96 QTransform matrix;
103 QImage pattern;
104};
105
106
107// ----------------------------------------------------------------
108
109
115
119
124
126{
127 d = rhs.d;
128 return *this;
129}
130
132{
133 Q_UNUSED(other);
134 return false;
135}
136
137void KoPatternBackground::setTransform(const QTransform &matrix)
138{
139 d->matrix = matrix;
140}
141
143{
144 return d->matrix;
145}
146
147void KoPatternBackground::setPattern(const QImage &pattern)
148{
149 d->pattern = pattern;
150}
151
153{
154 return d->pattern;
155}
156
158{
159 d->repeat = repeat;
160}
161
166
171
173{
174 d->refPoint = referencePoint;
175}
176
178{
179 return d->refPointOffsetPercent;
180}
181
183{
184 qreal ox = qMax(qreal(0.0), qMin(qreal(100.0), offset.x()));
185 qreal oy = qMax(qreal(0.0), qMin(qreal(100.0), offset.y()));
186
187 d->refPointOffsetPercent = QPointF(ox, oy);
188}
189
191{
192 return d->tileRepeatOffsetPercent;
193}
194
196{
197 d->tileRepeatOffsetPercent = offset;
198}
199
201{
202 return d->targetSize();
203}
204
206{
207 d->targetImageSizePercent = QSizeF();
208 d->targetImageSize = size;
209}
210
212{
213 return d->pattern.size();
214}
215
216void KoPatternBackground::paint(QPainter &painter, const QPainterPath &fillPath) const
217{
218 if (d->pattern.isNull()) {
219 return;
220 }
221
222 painter.save();
223 if (d->repeat == Tiled) {
224 // calculate scaling of pixmap
225 QSizeF targetSize = d->targetSize();
226 QSizeF imageSize = d->pattern.size();
227 qreal scaleX = targetSize.width() / imageSize.width();
228 qreal scaleY = targetSize.height() / imageSize.height();
229
230 QRectF targetRect = fillPath.boundingRect();
231 // undo scaling on target rectangle
232 targetRect.setWidth(targetRect.width() / scaleX);
233 targetRect.setHeight(targetRect.height() / scaleY);
234
235 // determine pattern offset
236 QPointF offset = d->offsetFromRect(targetRect, imageSize);
237
238 // create matrix for pixmap scaling
239 QTransform matrix;
240 matrix.scale(scaleX, scaleY);
241
242 painter.setClipPath(fillPath);
243 painter.setWorldTransform(matrix, true);
244 painter.drawTiledPixmap(targetRect, QPixmap::fromImage(d->pattern), -offset);
245 } else if (d->repeat == Original) {
246 QRectF sourceRect(QPointF(0, 0), d->pattern.size());
247 QRectF targetRect(QPoint(0, 0), d->targetSize());
248 targetRect.moveCenter(fillPath.boundingRect().center());
249 painter.setClipPath(fillPath);
250 painter.drawPixmap(targetRect, QPixmap::fromImage(d->pattern).scaled(sourceRect.size().toSize()), sourceRect);
251 } else if (d->repeat == Stretched) {
252 painter.setClipPath(fillPath);
253 // undo conversion of the scaling so that we can use a nicely scaled image of the correct size
254 qWarning() << "WARNING: stretched KoPatternBackground painting code is abandoned. The result might be not correct";
255 const QRectF targetRect = fillPath.boundingRect();
256 painter.drawPixmap(targetRect.topLeft(), QPixmap::fromImage(d->pattern).scaled(targetRect.size().toSize()));
257 }
258
259 painter.restore();
260}
261
262
264{
265 QRectF rect;
266
267 switch (d->repeat) {
268 case Tiled:
269 rect.setTopLeft(d->offsetFromRect(QRectF(QPointF(), size), d->targetSize()));
270 rect.setSize(d->targetSize());
271 break;
272 case Original:
273 rect.setLeft(0.5 * (size.width() - d->targetSize().width()));
274 rect.setTop(0.5 * (size.height() - d->targetSize().height()));
275 rect.setSize(d->targetSize());
276 break;
277 case Stretched:
278 rect.setTopLeft(QPointF(0.0, 0.0));
279 rect.setSize(size);
280 break;
281 }
282
283 return rect;
284}
KoPatternBackground::ReferencePoint refPoint
QPointF offsetFromRect(const QRectF &fillRect, const QSizeF &imageSize) const
KoPatternBackground::PatternRepeat repeat
A pattern shape background.
PatternRepeat repeat() const
Returns the pattern repeat.
void setRepeat(PatternRepeat repeat)
Sets the pattern repeatgfl.
void paint(QPainter &painter, const QPainterPath &fillPath) const override
reimplemented from KoShapeBackground
QRectF patternRectFromFillSize(const QSizeF &size)
Returns the bounding rect of the pattern image based on the given fill size.
QPointF referencePointOffset() const
Returns reference point offset in percent of the pattern display size.
KoPatternBackground & operator=(const KoPatternBackground &)
QSizeF patternOriginalSize() const
Returns the original image size.
QImage pattern() const
Returns the pattern.
QSharedDataPointer< Private > d
PatternRepeat
Pattern rendering style.
ReferencePoint
Pattern reference point.
QSizeF patternDisplaySize() const
Returns the pattern display size.
QPointF tileRepeatOffset() const
Returns tile repeat offset in percent of the pattern display size.
void setReferencePoint(ReferencePoint referencePoint)
Sets the pattern reference point.
void setPattern(const QImage &pattern)
Sets a new pattern.
bool compareTo(const KoShapeBackground *other) const override
QTransform transform() const
Returns the transform matrix.
ReferencePoint referencePoint() const
Returns the pattern reference point identifier.
void setTileRepeatOffset(const QPointF &offset)
Sets the tile repeat offset in percent of the pattern display size.
void setTransform(const QTransform &matrix)
Sets the transform matrix.
void setPatternDisplaySize(const QSizeF &size)
Sets pattern display size.
void setReferencePointOffset(const QPointF &offset)
Sets the reference point offset in percent of the pattern display size.