File indexing completed on 2024-05-12 15:56:40

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2009-2010 Jan Hambrecht <jaham@gmx.net>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  */
0006 
0007 #include "KoFilterEffectStack.h"
0008 #include "KoFilterEffect.h"
0009 #include "KoXmlWriter.h"
0010 
0011 #include <QRectF>
0012 #include <QAtomicInt>
0013 #include <QSet>
0014 #include <QDebug>
0015 
0016 class Q_DECL_HIDDEN KoFilterEffectStack::Private
0017 {
0018 public:
0019     Private()
0020     : clipRect(-0.1, -0.1, 1.2, 1.2) // initialize as per svg spec
0021     {
0022     }
0023 
0024     ~Private()
0025     {
0026         qDeleteAll(filterEffects);
0027     }
0028 
0029     QList<KoFilterEffect*> filterEffects;
0030     QRectF clipRect;
0031     QAtomicInt refCount;
0032 };
0033 
0034 KoFilterEffectStack::KoFilterEffectStack()
0035 : d(new Private())
0036 {
0037 }
0038 
0039 KoFilterEffectStack::~KoFilterEffectStack()
0040 {
0041     delete d;
0042 }
0043 
0044 QList<KoFilterEffect*> KoFilterEffectStack::filterEffects() const
0045 {
0046     return d->filterEffects;
0047 }
0048 
0049 bool KoFilterEffectStack::isEmpty() const
0050 {
0051     return d->filterEffects.isEmpty();
0052 }
0053 
0054 void KoFilterEffectStack::insertFilterEffect(int index, KoFilterEffect * filter)
0055 {
0056     if (filter)
0057         d->filterEffects.insert(index, filter);
0058 }
0059 
0060 void KoFilterEffectStack::appendFilterEffect(KoFilterEffect *filter)
0061 {
0062     if (filter)
0063         d->filterEffects.append(filter);
0064 }
0065 
0066 void KoFilterEffectStack::removeFilterEffect(int index)
0067 {
0068     KoFilterEffect * filter = takeFilterEffect(index);
0069     delete filter;
0070 }
0071 
0072 KoFilterEffect* KoFilterEffectStack::takeFilterEffect(int index)
0073 {
0074     if (index >= d->filterEffects.size())
0075         return 0;
0076     return d->filterEffects.takeAt(index);
0077 }
0078 
0079 void KoFilterEffectStack::setClipRect(const QRectF &clipRect)
0080 {
0081     d->clipRect = clipRect;
0082 }
0083 
0084 QRectF KoFilterEffectStack::clipRect() const
0085 {
0086     return d->clipRect;
0087 }
0088 
0089 QRectF KoFilterEffectStack::clipRectForBoundingRect(const QRectF &boundingRect) const
0090 {
0091     qreal x = boundingRect.x() + d->clipRect.x() * boundingRect.width();
0092     qreal y = boundingRect.y() + d->clipRect.y() * boundingRect.height();
0093     qreal w = d->clipRect.width() * boundingRect.width();
0094     qreal h = d->clipRect.height() * boundingRect.height();
0095     return QRectF(x, y, w, h);
0096 }
0097 
0098 bool KoFilterEffectStack::ref()
0099 {
0100     return d->refCount.ref();
0101 }
0102 
0103 bool KoFilterEffectStack::deref()
0104 {
0105     return d->refCount.deref();
0106 }
0107 
0108 int KoFilterEffectStack::useCount() const
0109 {
0110     return d->refCount;
0111 }
0112 
0113 void KoFilterEffectStack::save(KoXmlWriter &writer, const QString &filterId)
0114 {
0115     writer.startElement("filter");
0116     writer.addAttribute("id", filterId);
0117     writer.addAttribute("filterUnits", "objectBoundingBox");
0118     writer.addAttribute("primitiveUnits", "objectBoundingBox");
0119     writer.addAttribute("x", d->clipRect.x());
0120     writer.addAttribute("y", d->clipRect.y());
0121     writer.addAttribute("width", d->clipRect.width());
0122     writer.addAttribute("height", d->clipRect.height());
0123 
0124     Q_FOREACH (KoFilterEffect *effect, d->filterEffects) {
0125         effect->save(writer);
0126     }
0127 
0128     writer.endElement();
0129 }
0130 
0131 QSet<QString> KoFilterEffectStack::requiredStandarsInputs() const
0132 {
0133     static QSet<QString> stdInputs = QSet<QString>()
0134         << "SourceGraphic"
0135         << "SourceAlpha"
0136         << "BackgroundImage"
0137         << "BackgroundAlpha"
0138         << "FillPaint"
0139         << "StrokePaint";
0140 
0141     QSet<QString> requiredInputs;
0142     if (isEmpty())
0143         return requiredInputs;
0144 
0145     if (d->filterEffects.first()->inputs().contains(QString()))
0146         requiredInputs.insert("SourceGraphic");
0147 
0148     Q_FOREACH (KoFilterEffect *effect, d->filterEffects) {
0149         Q_FOREACH (const QString &input, effect->inputs()) {
0150             if (stdInputs.contains(input))
0151                 requiredInputs.insert(input);
0152         }
0153     }
0154 
0155     return requiredInputs;
0156 }