Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qsvgfilter.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsvgfilter_p.h"
5
6#include "qsvgnode_p.h"
8#include "qpainter.h"
9
10#include <QLoggingCategory>
11#include <QtGui/qimageiohandler.h>
12#include <QVector4D>
13
15
17
19 const QSvgRectF &rect)
20 : QSvgStructureNode(parent)
21 , m_input(input)
22 , m_result(result)
23 , m_rect(rect)
24{
25
26}
27
29{
30 return false;
31}
32
34 const QRectF &itemBounds, const QRectF &filterBounds,
35 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
36{
37
38 QRectF localBounds;
39 if (filterUnits != QtSvg::UnitTypes::userSpaceOnUse)
40 localBounds = itemBounds;
41 else
42 localBounds = filterBounds;
43 QRectF clipRect = m_rect.combinedWithLocalRect(localBounds, node->document()->viewBox(), primitiveUnits);
44 clipRect = clipRect.intersected(filterBounds);
45
46 return clipRect;
47}
48
50 const QRectF &itemBounds, const QRectF &filterBounds,
51 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
52{
53 return p->transform().mapRect(localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits));
54}
55
57{
59 painter.setRenderHints(p->renderHints());
60 painter.translate(-buffer->offset());
61 QPainterPath clipPath;
63 clipPath.addRect(QRect(buffer->offset(), buffer->size()).adjusted(-10, -10, 20, 20));
64 clipPath.addPolygon(p->transform().map(QPolygonF(localRect)));
67}
68
70{
71 return m_input == QLatin1StringView("SourceAlpha");
72}
73
75{
76 if (node->type() == QSvgNode::FeMerge ||
77 node->type() == QSvgNode::FeColormatrix ||
78 node->type() == QSvgNode::FeGaussianblur ||
79 node->type() == QSvgNode::FeOffset ||
80 node->type() == QSvgNode::FeComposite ||
81 node->type() == QSvgNode::FeFlood ) {
82 return reinterpret_cast<const QSvgFeFilterPrimitive*>(node);
83 } else {
84 return nullptr;
85 }
86}
87
91 , m_type(type)
92 , m_matrix(matrix)
93{
94 (void)m_type;
95 //Magic numbers see SVG 1.1(Second edition)
97 qreal s = qBound(0., matrix.data()[0], 1.);
98
99 m_matrix.fill(0);
100
101 m_matrix.data()[0+0*5] = 0.213f + 0.787f * s;
102 m_matrix.data()[1+0*5] = 0.715f - 0.717f * s;
103 m_matrix.data()[2+0*5] = 0.072f - 0.072f * s;
104
105 m_matrix.data()[0+1*5] = 0.213f - 0.213f * s;
106 m_matrix.data()[1+1*5] = 0.715f + 0.285f * s;
107 m_matrix.data()[2+1*5] = 0.072f - 0.072f * s;
108
109 m_matrix.data()[0+2*5] = 0.213f - 0.213f * s;
110 m_matrix.data()[1+2*5] = 0.715f - 0.715f * s;
111 m_matrix.data()[2+2*5] = 0.072f + 0.928f * s;
112
113 m_matrix.data()[3+3*5] = 1;
114
115 } else if (type == ColorShiftType::HueRotate){
116 qreal angle = matrix.data()[0]/180.*M_PI;
117 qreal s = sin(angle);
118 qreal c = cos(angle);
119
120 m_matrix.fill(0);
121
122 QMatrix3x3 m1;
123 m1.data()[0+0*3] = 0.213f;
124 m1.data()[1+0*3] = 0.715f;
125 m1.data()[2+0*3] = 0.072f;
126
127 m1.data()[0+1*3] = 0.213f;
128 m1.data()[1+1*3] = 0.715f;
129 m1.data()[2+1*3] = 0.072f;
130
131 m1.data()[0+2*3] = 0.213f;
132 m1.data()[1+2*3] = 0.715f;
133 m1.data()[2+2*3] = 0.072f;
134
135 QMatrix3x3 m2;
136 m2.data()[0+0*3] = 0.787 * c;
137 m2.data()[1+0*3] = -0.715 * c;
138 m2.data()[2+0*3] = -0.072 * c;
139
140 m2.data()[0+1*3] = -0.213 * c;
141 m2.data()[1+1*3] = 0.285 * c;
142 m2.data()[2+1*3] = -0.072 * c;
143
144 m2.data()[0+2*3] = -0.213 * c;
145 m2.data()[1+2*3] = -0.715 * c;
146 m2.data()[2+2*3] = 0.928 * c;
147
148 QMatrix3x3 m3;
149 m3.data()[0+0*3] = -0.213 * s;
150 m3.data()[1+0*3] = -0.715 * s;
151 m3.data()[2+0*3] = 0.928 * s;
152
153 m3.data()[0+1*3] = 0.143 * s;
154 m3.data()[1+1*3] = 0.140 * s;
155 m3.data()[2+1*3] = -0.283 * s;
156
157 m3.data()[0+2*3] = -0.787 * s;
158 m3.data()[1+2*3] = 0.715 * s;
159 m3.data()[2+2*3] = 0.072 * s;
160
161 QMatrix3x3 m = m1 + m2 + m3;
162
163 m_matrix.data()[0+0*5] = m.data()[0+0*3];
164 m_matrix.data()[1+0*5] = m.data()[1+0*3];
165 m_matrix.data()[2+0*5] = m.data()[2+0*3];
166
167 m_matrix.data()[0+1*5] = m.data()[0+1*3];
168 m_matrix.data()[1+1*5] = m.data()[1+1*3];
169 m_matrix.data()[2+1*5] = m.data()[2+1*3];
170
171 m_matrix.data()[0+2*5] = m.data()[0+2*3];
172 m_matrix.data()[1+2*5] = m.data()[1+2*3];
173 m_matrix.data()[2+2*5] = m.data()[2+2*3];
174
175 m_matrix.data()[3+3*5] = 1;
177 m_matrix.fill(0);
178
179 m_matrix.data()[0+3*5] = 0.2125;
180 m_matrix.data()[1+3*5] = 0.7154;
181 m_matrix.data()[2+3*5] = 0.0721;
182 }
183}
184
189
191 const QRectF &itemBounds, const QRectF &filterBounds,
192 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
193{
194 if (!sources.contains(m_input))
195 return QImage();
197
198 QRect clipRectGlob = globalFilterBoundingBox(item, p, itemBounds, filterBounds, primitiveUnits, filterUnits).toRect();
199 QRect requiredRect = p->transform().mapRect(itemBounds).toRect();
200 clipRectGlob = clipRectGlob.intersected(requiredRect);
201 if (clipRectGlob.isEmpty())
202 return QImage();
203
206 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
207 return QImage();
208 }
209 result.setOffset(clipRectGlob.topLeft());
211
212 Q_ASSERT(source.depth() == 32);
213
214 for (int i = 0; i < result.height(); i++) {
215 int sourceI = i - source.offset().y() + result.offset().y();
216
217 if (sourceI < 0 || sourceI >= source.height())
218 continue;
219
220 QRgb *sourceLine = reinterpret_cast<QRgb *>(source.scanLine(sourceI));
221 QRgb *resultLine = reinterpret_cast<QRgb *>(result.scanLine(i));
222
223 for (int j = 0; j < result.width(); j++) {
224 int sourceJ = j - source.offset().x() + result.offset().x();
225
226 if (sourceJ < 0 || sourceJ >= source.width())
227 continue;
228
229 qreal a = qAlpha(sourceLine[sourceJ]);
230 qreal r = qBlue(sourceLine[sourceJ]);
231 qreal g = qGreen(sourceLine[sourceJ]);
232 qreal b = qRed(sourceLine[sourceJ]);
233
234 qreal r2 = m_matrix.data()[0+0*5] * r +
235 m_matrix.data()[1+0*5] * g +
236 m_matrix.data()[2+0*5] * b +
237 m_matrix.data()[3+0*5] * a +
238 m_matrix.data()[4+0*5] * 255.;
239 qreal g2 = m_matrix.data()[0+1*5] * r +
240 m_matrix.data()[1+1*5] * g +
241 m_matrix.data()[2+1*5] * b +
242 m_matrix.data()[3+1*5] * a +
243 m_matrix.data()[4+1*5] * 255.;
244 qreal b2 = m_matrix.data()[0+2*5] * r +
245 m_matrix.data()[1+2*5] * g +
246 m_matrix.data()[2+2*5] * b +
247 m_matrix.data()[3+2*5] * a +
248 m_matrix.data()[4+2*5] * 255.;
249 qreal a2 = m_matrix.data()[0+3*5] * r +
250 m_matrix.data()[1+3*5] * g +
251 m_matrix.data()[2+3*5] * b +
252 m_matrix.data()[3+3*5] * a +
253 m_matrix.data()[4+3*5] * 255.;
254
255 resultLine[j] = qRgba(qBound(0, int(b2), 255),
256 qBound(0, int(g2), 255),
257 qBound(0, int(r2), 255),
258 qBound(0, int(a2), 255));
259 }
260 }
261
262 clipToTransformedBounds(&result, p, localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits));
263 return result;
264}
265
267 qreal stdDeviationX, qreal stdDeviationY, EdgeMode edgemode)
269 , m_stdDeviationX(stdDeviationX)
270 , m_stdDeviationY(stdDeviationY)
271 , m_edgemode(edgemode)
272{
273 (void)m_edgemode;
274}
275
280
282 const QRectF &itemBounds, const QRectF &filterBounds,
283 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
284{
285 if (!sources.contains(m_input))
286 return QImage();
288 Q_ASSERT(source.depth() == 32);
289
290 QPointF sigma_scaled = p->transform().map(QPointF(m_stdDeviationX, m_stdDeviationY)) -
291 p->transform().map(QPointF(0, 0));
292 qreal sigma_x = sigma_scaled.x();
293 qreal sigma_y = sigma_scaled.y();
294 if (primitiveUnits == QtSvg::UnitTypes::objectBoundingBox) {
295 sigma_x *= itemBounds.width();
296 sigma_y *= itemBounds.height();
297 }
298
299 // TODO: if p->transform contains anything other than translate and scale,
300 // then the gaussian filter has to be applied in local coordinates
301 // and the resulting image has to be transformed into global
302 // coordinates
303
304 int dx = qMax(1, int(floor(sigma_x * 3. * sqrt(2. * M_PI) / 4. + 0.5)));
305 int dy = qMax(1, int(floor(sigma_y * 3. * sqrt(2. * M_PI) / 4. + 0.5)));
306
307 QRect clipRectGlob = globalFilterBoundingBox(item, p, itemBounds, filterBounds, primitiveUnits, filterUnits).toRect();
308 QRect requiredRect = p->transform().mapRect(itemBounds).toRect();
309 requiredRect.adjust(- 3 * dx, -3 * dy, 3 * dx, 3 * dy);
310 clipRectGlob = clipRectGlob.intersected(requiredRect);
311 if (clipRectGlob.isEmpty())
312 return QImage();
313
314 QImage tempSource;
315 if (!QImageIOHandler::allocateImage(clipRectGlob.size(), QImage::Format_RGBA8888_Premultiplied, &tempSource)) {
316 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
317 return QImage();
318 }
319 tempSource.setOffset(clipRectGlob.topLeft());
320 tempSource.fill(Qt::transparent);
321 QPainter copyPainter(&tempSource);
322 copyPainter.drawImage(source.offset() - clipRectGlob.topLeft(), source);
323 copyPainter.end();
324
325 QImage result = tempSource;
326
327 // Using the approximation of a boxblur applied 3 times. Decoupling vertical and horizontal
328 for (int m = 0; m < 6; m++) {
329 QRgb *rawSource = reinterpret_cast<QRgb *>(tempSource.bits());
330 QRgb *rawResult = reinterpret_cast<QRgb *>(result.bits());
331
332 int d = (m % 2 == 0) ? dx : dy;
333 int maxdim = (m % 2 == 0) ? tempSource.width() : tempSource.height();
334
335 if (d < 1)
336 continue;
337
338 for (int i = 0; i < tempSource.width(); i++) {
339 for (int j = 0; j < tempSource.height(); j++) {
340
341 int iipos = (m % 2 == 0) ? i : j;
342
343 QVector4D val(0, 0, 0, 0);
344 for (int k = 0; k < d; k++) {
345 int ii = iipos + k - d / 2;
346 if (ii < 0 || ii >= maxdim)
347 continue;
348 QRgb rgbVal = (m % 2 == 0) ? rawSource[ii + j * tempSource.width()] : rawSource[i + ii * tempSource.width()];
349 val += QVector4D(qBlue(rgbVal), //TODO: Why are values switched here???
350 qGreen(rgbVal),
351 qRed(rgbVal), //TODO: Why are values switched here???
352 qAlpha(rgbVal)) / d;
353 }
354 rawResult[i + j * tempSource.width()] = qRgba(qBound(0, int(val[0]), 255),
355 qBound(0, int(val[1]), 255),
356 qBound(0, int(val[2]), 255),
357 qBound(0, int(val[3]), 255));
358 }
359 }
360 tempSource = result;
361 }
362
363 clipToTransformedBounds(&result, p, localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits));
364 return result;
365}
366
368 qreal dx, qreal dy)
370 , m_dx(dx)
371 , m_dy(dy)
372{
373
374}
375
380
381QImage QSvgFeOffset::apply(QSvgNode *item, const QMap<QString, QImage> &sources, QPainter *p,
382 const QRectF &itemBounds, const QRectF &filterBounds,
383 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
384{
385 if (!sources.contains(m_input))
386 return QImage();
387
388 const QImage &source = sources[m_input];
389
390 QRectF clipRect = localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits);
391 QRect clipRectGlob = p->transform().mapRect(clipRect).toRect();
392
393 QPoint offset(m_dx, m_dy);
394 if (primitiveUnits == QtSvg::UnitTypes::objectBoundingBox) {
395 offset = QPoint(m_dx * itemBounds.width(),
396 m_dy * itemBounds.height());
397 }
398 offset = p->transform().map(offset) - p->transform().map(QPoint(0, 0));
399
400 QRect requiredRect = QRect(source.offset(), source.size()).translated(offset);
401 clipRectGlob = clipRectGlob.intersected(requiredRect);
402
403 if (clipRectGlob.isEmpty())
404 return QImage();
405
408 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
409 return QImage();
410 }
411 result.setOffset(clipRectGlob.topLeft());
413
414 QPainter copyPainter(&result);
415 copyPainter.drawImage(source.offset()
416 - result.offset() + offset, source);
417 copyPainter.end();
418
419 clipToTransformedBounds(&result, p, clipRect);
420 return result;
421}
422
423
429
434
435QImage QSvgFeMerge::apply(QSvgNode *item, const QMap<QString, QImage> &sources, QPainter *p,
436 const QRectF &itemBounds, const QRectF &filterBounds,
437 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
438{
439 QList<QImage> mergeNodeResults;
440 QRect requiredRect;
441
442 for (int i = 0; i < renderers().size(); i++) {
444 if (child->type() == QSvgNode::FeMergenode) {
446 mergeNodeResults.append(filter->apply(item, sources, p, itemBounds, filterBounds, primitiveUnits, filterUnits));
447 requiredRect = requiredRect.united(QRect(mergeNodeResults.last().offset(),
448 mergeNodeResults.last().size()));
449 }
450 }
451
452 QRectF clipRect = localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits);
453 QRect clipRectGlob = p->transform().mapRect(clipRect).toRect();
454 clipRectGlob = clipRectGlob.intersected(requiredRect);
455 if (clipRectGlob.isEmpty())
456 return QImage();
457
460 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
461 return QImage();
462 }
463 result.setOffset(clipRectGlob.topLeft());
465
466 QPainter proxyPainter(&result);
467 for (const QImage &i : mergeNodeResults) {
468 proxyPainter.drawImage(QRect(i.offset() - result.offset(), i.size()), i);
469 }
470 proxyPainter.end();
471
472 clipToTransformedBounds(&result, p, clipRect);
473 return result;
474}
475
477{
478 for (int i = 0; i < renderers().size(); i++) {
480 if (child->type() == QSvgNode::FeMergenode) {
481 QSvgFeMergeNode *filter = static_cast<QSvgFeMergeNode *>(child);
482 if (filter->requiresSourceAlpha())
483 return true;
484 }
485 }
486 return false;
487}
488
494
499
500QImage QSvgFeMergeNode::apply(QSvgNode *, const QMap<QString, QImage> &sources, QPainter *,
501 const QRectF &, const QRectF &, QtSvg::UnitTypes, QtSvg::UnitTypes) const
502{
503 return sources.value(m_input);
504}
505
507 QString input2, Operator op, QVector4D k)
509 , m_input2(input2)
510 , m_operator(op)
511 , m_k(k)
512{
513
514}
515
520
521QImage QSvgFeComposite::apply(QSvgNode *item, const QMap<QString, QImage> &sources, QPainter *p,
522 const QRectF &itemBounds, const QRectF &filterBounds,
523 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
524{
525 if (!sources.contains(m_input))
526 return QImage();
527 if (!sources.contains(m_input2))
528 return QImage();
529 QImage source1 = sources[m_input];
530 QImage source2 = sources[m_input2];
531 Q_ASSERT(source1.depth() == 32);
532 Q_ASSERT(source2.depth() == 32);
533
534 QRectF clipRect = localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits);
535 QRect clipRectGlob = globalFilterBoundingBox(item, p, itemBounds, filterBounds, primitiveUnits, filterUnits).toRect();
536 QRect requiredRect = QRect(source1.offset(), source1.size()).united(
537 QRect(source2.offset(), source2.size()));
538 clipRectGlob = clipRectGlob.intersected(requiredRect);
539 if (clipRectGlob.isEmpty())
540 return QImage();
541
544 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
545 return QImage();
546 }
547 result.setOffset(clipRectGlob.topLeft());
549
550 if (m_operator == Operator::Arithmetic) {
551 const qreal k1 = m_k.x();
552 const qreal k2 = m_k.y();
553 const qreal k3 = m_k.z();
554 const qreal k4 = m_k.w();
555
556 for (int j = 0; j < result.height(); j++) {
557 int jj1 = j - source1.offset().y() + result.offset().y();
558 int jj2 = j - source2.offset().y() + result.offset().y();
559
560 QRgb *resultLine = reinterpret_cast<QRgb *>(result.scanLine(j));
561 QRgb *source1Line = nullptr;
562 QRgb *source2Line = nullptr;
563
564 if (jj1 >= 0 && jj1 < source1.size().height())
565 source1Line = reinterpret_cast<QRgb *>(source1.scanLine(jj1));
566 if (jj2 >= 0 && jj2 < source2.size().height())
567 source2Line = reinterpret_cast<QRgb *>(source2.scanLine(jj2));
568
569 for (int i = 0; i < result.width(); i++) {
570 int ii1 = i - source1.offset().x() + result.offset().x();
571 int ii2 = i - source2.offset().x() + result.offset().x();
572
573 QVector4D s1 = QVector4D(0, 0, 0, 0);
574 QVector4D s2 = QVector4D(0, 0, 0, 0);
575
576 if (ii1 >= 0 && ii1 < source1.size().width() && source1Line) {
577 QRgb pixel1 = source1Line[ii1];
578 s1 = QVector4D(qRed(pixel1),
579 qGreen(pixel1),
580 qBlue(pixel1),
581 qAlpha(pixel1));
582 }
583
584 if (ii2 >= 0 && ii2 < source2.size().width() && source2Line) {
585 QRgb pixel2 = source2Line[ii2];
586 s2 = QVector4D(qRed(pixel2),
587 qGreen(pixel2),
588 qBlue(pixel2),
589 qAlpha(pixel2));
590 }
591
592 int r = k1 * s1.x() * s2.x() / 255. + k2 * s1.x() + k3 * s2.x() + k4 * 255.;
593 int g = k1 * s1.y() * s2.y() / 255. + k2 * s1.y() + k3 * s2.y() + k4 * 255.;
594 int b = k1 * s1.z() * s2.z() / 255. + k2 * s1.z() + k3 * s2.z() + k4 * 255.;
595 int a = k1 * s1.w() * s2.w() / 255. + k2 * s1.w() + k3 * s2.w() + k4 * 255.;
596
597 qreal alpha = qBound(0, a, 255) / 255.;
598 if (alpha == 0)
599 alpha = 1;
600 resultLine[i] = qRgba(qBound(0., r / alpha, 255.),
601 qBound(0., g / alpha, 255.),
602 qBound(0., b / alpha, 255.),
603 qBound(0, a, 255));
604 }
605 }
606 } else {
607 QPainter proxyPainter(&result);
608 proxyPainter.drawImage(QRect(source1.offset() - result.offset(), source1.size()), source1);
609
610 switch (m_operator) {
611 case Operator::In:
612 proxyPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
613 break;
614 case Operator::Out:
615 proxyPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
616 break;
617 case Operator::Xor:
618 proxyPainter.setCompositionMode(QPainter::CompositionMode_Xor);
619 break;
621 proxyPainter.setCompositionMode(QPainter::CompositionMode_Lighten);
622 break;
623 case Operator::Atop:
624 proxyPainter.setCompositionMode(QPainter::CompositionMode_DestinationAtop);
625 break;
626 case Operator::Over:
627 proxyPainter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
628 break;
629 case Operator::Arithmetic: // handled above
630 Q_UNREACHABLE();
631 break;
632 }
633 proxyPainter.drawImage(QRect(source2.offset()-result.offset(), source2.size()), source2);
634 proxyPainter.end();
635 }
636
637 clipToTransformedBounds(&result, p, clipRect);
638 return result;
639}
640
642{
644 return true;
645 return m_input2 == QLatin1StringView("SourceAlpha");
646}
647
648
650 const QSvgRectF &rect, const QColor &color)
652 , m_color(color)
653{
654
655}
656
661
662QImage QSvgFeFlood::apply(QSvgNode *item, const QMap<QString, QImage> &,
663 QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds,
664 QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
665{
666
667 QRectF clipRect = localFilterBoundingBox(item, itemBounds, filterBounds, primitiveUnits, filterUnits);
668 QRect clipRectGlob = p->transform().mapRect(clipRect).toRect();
669
672 qCWarning(lcSvgDraw) << "The requested filter buffer is too big, ignoring";
673 return QImage();
674 }
675 result.setOffset(clipRectGlob.topLeft());
676 result.fill(m_color);
677
678 clipToTransformedBounds(&result, p, clipRect);
679 return result;
680}
681
687
692
693QImage QSvgFeUnsupported::apply(QSvgNode *, const QMap<QString, QImage> &,
694 QPainter *, const QRectF &, const QRectF &,
696{
697 qCDebug(lcSvgDraw) <<"Unsupported filter primitive should not be applied.";
698 return QImage();
699}
700
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
void fill(T value)
Fills all elements of this matrix with value.
T * data()
Returns a pointer to the raw data of this matrix.
static bool allocateImage(QSize size, QImage::Format format, QImage *image)
\inmodule QtGui
Definition qimage.h:37
@ Format_RGBA8888
Definition qimage.h:59
@ Format_RGBA8888_Premultiplied
Definition qimage.h:60
qsizetype size() const noexcept
Definition qlist.h:397
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
\inmodule QtGui
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
void setFillRule(Qt::FillRule fillRule)
Sets the fill rule of the painter path to the given fillRule.
void addPolygon(const QPolygonF &polygon)
Adds the given polygon to the path as an (unclosed) subpath.
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
void fillPath(const QPainterPath &path, const QBrush &brush)
Fills the given path using the given brush.
@ CompositionMode_Xor
Definition qpainter.h:109
@ CompositionMode_Lighten
Definition qpainter.h:117
@ CompositionMode_DestinationAtop
Definition qpainter.h:108
@ CompositionMode_DestinationOut
Definition qpainter.h:106
@ CompositionMode_DestinationOver
Definition qpainter.h:99
@ CompositionMode_DestinationIn
Definition qpainter.h:104
@ CompositionMode_SourceIn
Definition qpainter.h:103
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
void setRenderHints(RenderHints hints, bool on=true)
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
\inmodule QtCore\reentrant
Definition qpoint.h:25
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
Definition qrect.h:859
QRectF intersected(const QRectF &other) const noexcept
Definition qrect.h:847
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr void adjust(int x1, int y1, int x2, int y2) noexcept
Adds dx1, dy1, dx2 and dy2 respectively to the existing coordinates of the rectangle.
Definition qrect.h:373
QRect intersected(const QRect &other) const noexcept
Definition qrect.h:415
constexpr QRect adjusted(int x1, int y1, int x2, int y2) const noexcept
Returns a new rectangle with dx1, dy1, dx2 and dy2 added respectively to the existing coordinates of ...
Definition qrect.h:370
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:261
QRect united(const QRect &other) const noexcept
Definition qrect.h:420
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
Type type() const override
QSvgFeColorMatrix(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect, ColorShiftType type, Matrix matrix)
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
bool requiresSourceAlpha() const override
QSvgFeComposite(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect, QString input2, Operator op, QVector4D k)
Type type() const override
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
QRectF localFilterBoundingBox(QSvgNode *item, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
QSvgFeFilterPrimitive(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect)
bool shouldDrawNode(QPainter *, QSvgExtraStates &) const override
QString result() const
static const QSvgFeFilterPrimitive * castToFilterPrimitive(const QSvgNode *node)
virtual bool requiresSourceAlpha() const
void clipToTransformedBounds(QImage *buffer, QPainter *p, const QRectF &localRect) const
QRectF globalFilterBoundingBox(QSvgNode *item, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const
QSvgFeFlood(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect, const QColor &color)
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
Type type() const override
Type type() const override
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
QSvgFeGaussianBlur(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect, qreal stdDeviationX, qreal stdDeviationY, EdgeMode edgemode)
Type type() const override
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
QSvgFeMergeNode(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect)
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
bool requiresSourceAlpha() const override
QSvgFeMerge(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect)
Type type() const override
QSvgFeOffset(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect, qreal dx, qreal dy)
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
Type type() const override
QSvgFeUnsupported(QSvgNode *parent, QString input, QString result, const QSvgRectF &rect)
QImage apply(QSvgNode *item, const QMap< QString, QImage > &sources, QPainter *p, const QRectF &itemBounds, const QRectF &filterBounds, QtSvg::UnitTypes primitiveUnits, QtSvg::UnitTypes filterUnits) const override
Type type() const override
@ FeComposite
Definition qsvgnode_p.h:63
@ FeMergenode
Definition qsvgnode_p.h:59
@ FeUnsupported
Definition qsvgnode_p.h:65
@ FeGaussianblur
Definition qsvgnode_p.h:61
@ FeColormatrix
Definition qsvgnode_p.h:60
QSvgTinyDocument * document() const
Definition qsvgnode.cpp:372
virtual Type type() const =0
QRectF combinedWithLocalRect(const QRectF &localRect) const
QList< QSvgNode * > renderers() const
QRectF viewBox() const
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
constexpr float x() const noexcept
Returns the x coordinate of this point.
Definition qvectornd.h:878
constexpr float w() const noexcept
Returns the w coordinate of this point.
Definition qvectornd.h:881
constexpr float y() const noexcept
Returns the y coordinate of this point.
Definition qvectornd.h:879
constexpr float z() const noexcept
Returns the z coordinate of this point.
Definition qvectornd.h:880
rect
[4]
Combined button and popup list for selecting options.
@ transparent
Definition qnamespace.h:47
@ OddEvenFill
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define M_PI
Definition qmath.h:209
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLboolean GLboolean GLboolean b
const GLfloat * m
GLboolean GLboolean GLboolean GLboolean a
[7]
GLboolean r
[2]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLenum GLuint buffer
GLuint color
[2]
GLenum type
GLfloat angle
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum GLuint GLintptr offset
GLboolean GLboolean g
GLsizei GLenum * sources
GLsizei GLsizei GLchar * source
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLuint GLfloat * val
GLuint GLenum matrix
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLenum input
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QT_BEGIN_NAMESPACE typedef unsigned int QRgb
Definition qrgb.h:13
constexpr int qRed(QRgb rgb)
Definition qrgb.h:18
constexpr int qGreen(QRgb rgb)
Definition qrgb.h:21
constexpr QRgb qRgba(int r, int g, int b, int a)
Definition qrgb.h:33
constexpr int qBlue(QRgb rgb)
Definition qrgb.h:24
constexpr int qAlpha(QRgb rgb)
Definition qrgb.h:27
#define s2
#define a2
#define k1
double qreal
Definition qtypes.h:187
QRect r2(QPoint(100, 200), QSize(11, 16))
QGraphicsItem * item
QLayoutItem * child
[0]
QPainter painter(this)
[7]