Krita Source Code Documentation
Loading...
Searching...
No Matches
KoStopGradient Class Reference

#include <KoStopGradient.h>

+ Inheritance diagram for KoStopGradient:

Public Member Functions

void bakeVariableColors (KoCanvasResourcesInterfaceSP canvasResourcesInterface) override
 
KoResourceSP clone () const override
 
void colorAt (KoColor &, qreal t) const override
 reimplemented
 
QString defaultFileExtension () const override
 reimplemented
 
 KoStopGradient (const KoStopGradient &rhs)
 
 KoStopGradient (const QString &filename=QString())
 
bool loadFromDevice (QIODevice *dev, KisResourcesInterfaceSP resourcesInterface) override
 
KoStopGradientoperator= (const KoStopGradient &rhs)=delete
 
bool operator== (const KoStopGradient &rhs) const
 
QList< int > requiredCanvasResources () const override
 
QPair< QString, QString > resourceType () const override
 
QString saveSvgGradient () const
 
bool saveToDevice (QIODevice *dev) const override
 
void setStops (QList< KoGradientStop > stops)
 Sets the gradient stops.
 
QList< KoGradientStopstops () const
 
bool stopsAt (KoGradientStop &leftStop, KoGradientStop &rightStop, qreal t) const
 Find stops surrounding position, returns false if position outside gradient.
 
QGradient * toQGradient () const override
 reimplemented
 
void toXML (QDomDocument &doc, QDomElement &gradientElt) const
 toXML Convert the gradient to an XML string.
 
void updateVariableColors (KoCanvasResourcesInterfaceSP canvasResourcesInterface) override
 
 ~KoStopGradient () override
 
- Public Member Functions inherited from KoAbstractGradient
KoAbstractGradientSP cloneAndBakeVariableColors (KoCanvasResourcesInterfaceSP canvasResourcesInterface) const
 
KoAbstractGradientSP cloneAndUpdateVariableColors (KoCanvasResourcesInterfaceSP canvasResourcesInterface) const
 
const KoColorSpacecolorSpace () const
 
QImage generatePreview (int width, int height) const
 
QImage generatePreview (int width, int height, KoCanvasResourcesInterfaceSP canvasResourcesInterface) const
 
 KoAbstractGradient (const KoAbstractGradient &rhs)
 
 KoAbstractGradient (const QString &filename)
 
void setColorSpace (KoColorSpace *colorSpace)
 
void setSpread (QGradient::Spread spreadMethod)
 
void setType (QGradient::Type repeatType)
 
QGradient::Spread spread () const
 
QGradient::Type type () const
 
void updatePreview ()
 
 ~KoAbstractGradient () override
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 
- Public Member Functions inherited from KoResource
bool active () const
 
void addMetaData (QString key, QVariant value)
 store the given key, value pair in the resource
 
virtual void clearSideLoadedResources ()
 
virtual QList< KoResourceLoadResultembeddedResources (KisResourcesInterfaceSP globalResourcesInterface) const
 
QString filename () const
 
QImage image () const
 
bool isDirty () const
 
virtual bool isEphemeral () const
 
virtual bool isSerializable () const
 
 KoResource ()
 
 KoResource (const KoResource &rhs)
 
 KoResource (const QString &filename)
 
virtual QList< KoResourceLoadResultlinkedResources (KisResourcesInterfaceSP globalResourcesInterface) const
 
bool load (KisResourcesInterfaceSP resourcesInterface)
 
QString md5Sum (bool generateIfEmpty=true) const
 
QMap< QString, QVariant > metadata () const
 get a map with all the metadata
 
virtual QString name () const
 
KoResourceoperator= (const KoResource &rhs)=delete
 
bool permanent () const
 
QList< KoResourceLoadResultrequiredResources (KisResourcesInterfaceSP globalResourcesInterface) const
 
int resourceId () const
 
bool save ()
 
void setActive (bool active)
 
void setDirty (bool value)
 Mark the preset as modified but not saved.
 
void setFilename (const QString &filename)
 
void setImage (const QImage &image)
 
void setMD5Sum (const QString &md5sum)
 Set the md5sum of this resource. It must be in hex-encoded string format.
 
void setName (const QString &name)
 
void setPermanent (bool permanent)
 
void setResourceId (int id)
 
void setStorageLocation (const QString &location)
 
void setValid (bool valid)
 
void setVersion (int version)
 
virtual QList< KoResourceLoadResultsideLoadedResources (KisResourcesInterfaceSP globalResourcesInterface) const
 
KoResourceSignature signature () const
 
QString storageLocation () const
 
QList< KoResourceLoadResulttakeSideLoadedResources (KisResourcesInterfaceSP globalResourcesInterface)
 
virtual QImage thumbnail () const
 thumbnail the thumbnail image to use in resource selectors
 
virtual QString thumbnailPath () const
 thumbnailPath returns the path to a separate thumbnail image, outside the actual resource file itself. If the path is relative, it is supposed start in the same location as the resource itself. If it's absolute, that is, it starts with "/", it is from the root of the storage.
 
virtual void updateThumbnail ()
 updateThumbnail updates the thumbnail for this resource. Reimplement if your thumbnail is something else than the image set with setImage.
 
bool valid () const
 
int version () const
 Get the version of the resource.
 
virtual ~KoResource ()
 

Static Public Member Functions

static QSharedPointer< KoStopGradientfromQGradient (const QGradient *gradient)
 Creates KoStopGradient from a QGradient.
 
static KoStopGradient fromXML (const QDomElement &elt)
 fromXML convert a gradient from xml.
 

Protected Attributes

QPointF m_focalPoint
 
bool m_hasVariableStops = false
 
QPointF m_start
 
QPointF m_stop
 
QList< KoGradientStopm_stops
 

Private Member Functions

void loadSvgGradient (QIODevice *file)
 
void parseSvgGradient (const QDomElement &element, QHash< QString, const KoColorProfile * > profiles)
 

Additional Inherited Members

- Public Attributes inherited from KoAbstractGradient
const KoColorSpacecolorSpace
 
QGradient::Spread spread
 
QGradient::Type type
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 
- Public Attributes inherited from KoResource
bool active {true}
 
QString filename
 
QImage image
 
QString md5sum
 
QMap< QString, QVariant > metadata
 
bool modified {false}
 
QString name
 
bool permanent {false}
 
int resourceId {-1}
 
QString storageLocation
 
bool valid {false}
 
int version {-1}
 

Detailed Description

Resource for colorstop based gradients like SVG gradients

Definition at line 89 of file KoStopGradient.h.

Constructor & Destructor Documentation

◆ KoStopGradient() [1/2]

KoStopGradient::KoStopGradient ( const QString & filename = QString())
explicit

Definition at line 39 of file KoStopGradient.cpp.

41{
42}
KoAbstractGradient(const QString &filename)
QString filename

◆ ~KoStopGradient()

KoStopGradient::~KoStopGradient ( )
override

Definition at line 44 of file KoStopGradient.cpp.

45{
46}

◆ KoStopGradient() [2/2]

KoStopGradient::KoStopGradient ( const KoStopGradient & rhs)

Definition at line 48 of file KoStopGradient.cpp.

50 , m_stops(rhs.m_stops)
51 , m_start(rhs.m_start)
52 , m_stop(rhs.m_stop)
54{
55}
QList< KoGradientStop > m_stops

Member Function Documentation

◆ bakeVariableColors()

void KoStopGradient::bakeVariableColors ( KoCanvasResourcesInterfaceSP canvasResourcesInterface)
overridevirtual

Reimplemented from KoAbstractGradient.

Definition at line 269 of file KoStopGradient.cpp.

270{
271 const KoColor fgColor = canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>();
272 const KoColor bgColor = canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>();
273
274 for (auto it = m_stops.begin(); it != m_stops.end(); ++it) {
275 if (it->type == FOREGROUNDSTOP) {
276 it->color = fgColor;
277 it->type = COLORSTOP;
278 } else if (it->type == BACKGROUNDSTOP) {
279 it->color = bgColor;
280 it->type = COLORSTOP;
281 }
282 }
283}
@ FOREGROUNDSTOP
@ BACKGROUNDSTOP
@ COLORSTOP
@ BackgroundColor
The active background color selected for this canvas.
@ ForegroundColor
The active foreground color selected for this canvas.

References KoCanvasResource::BackgroundColor, BACKGROUNDSTOP, COLORSTOP, KoCanvasResource::ForegroundColor, FOREGROUNDSTOP, and m_stops.

◆ clone()

KoResourceSP KoStopGradient::clone ( ) const
overridevirtual

Implements KoResource.

Definition at line 69 of file KoStopGradient.cpp.

70{
71 return KoResourceSP(new KoStopGradient(*this));
72}
KoStopGradient(const QString &filename=QString())
QSharedPointer< KoResource > KoResourceSP

References KoStopGradient().

◆ colorAt()

void KoStopGradient::colorAt ( KoColor & dst,
qreal t ) const
overridevirtual

reimplemented

Reimplemented from KoAbstractGradient.

Definition at line 154 of file KoStopGradient.cpp.

155{
156 KoGradientStop leftStop, rightStop;
157 if (!stopsAt(leftStop, rightStop, t)) return;
158
159 const KoColorSpace *mixSpace = dst.colorSpace();
160
161 KoColor buffer(mixSpace);
162 KoColor startDummy(leftStop.color, mixSpace);
163 KoColor endDummy(rightStop.color, mixSpace);
164
165 const std::array<quint8 *, 2> colors = {{startDummy.data(), endDummy.data()}};
166
167 qreal localT = NAN;
168 qreal stopDistance = rightStop.position - leftStop.position;
169 if (stopDistance < DBL_EPSILON) {
170 localT = 0.5;
171 } else {
172 localT = (t - leftStop.position) / stopDistance;
173 }
174 std::array<qint16, 2> colorWeights {};
175 colorWeights[0] = std::lround((1.0 - localT) * qint16_MAX);
176 colorWeights[1] = qint16_MAX - colorWeights[0];
177
178 mixSpace->mixColorsOp()->mixColors(colors.data(), colorWeights.data(), 2, buffer.data(), qint16_MAX);
179
180 dst = buffer;
181}
KoMixColorsOp * mixColorsOp
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
bool stopsAt(KoGradientStop &leftStop, KoGradientStop &rightStop, qreal t) const
Find stops surrounding position, returns false if position outside gradient.
const qint16 qint16_MAX
Definition kis_global.h:28

References KoGradientStop::color, KoColor::colorSpace(), KoColor::data(), KoMixColorsOp::mixColors(), KoColorSpace::mixColorsOp, KoGradientStop::position, qint16_MAX, and stopsAt().

◆ defaultFileExtension()

QString KoStopGradient::defaultFileExtension ( ) const
overridevirtual

reimplemented

Reimplemented from KoResource.

Definition at line 547 of file KoStopGradient.cpp.

548{
549 return QString(".svg");
550}

◆ fromQGradient()

QSharedPointer< KoStopGradient > KoStopGradient::fromQGradient ( const QGradient * gradient)
static

Creates KoStopGradient from a QGradient.

Definition at line 183 of file KoStopGradient.cpp.

184{
185 if (!gradient)
187
188 QSharedPointer<KoStopGradient> newGradient(new KoStopGradient(QString()));
189 newGradient->setType(gradient->type());
190 newGradient->setSpread(gradient->spread());
191
192 switch (gradient->type()) {
193 case QGradient::LinearGradient: {
194 const QLinearGradient* g = static_cast<const QLinearGradient*>(gradient);
195 newGradient->m_start = g->start();
196 newGradient->m_stop = g->finalStop();
197 newGradient->m_focalPoint = g->start();
198 break;
199 }
200 case QGradient::RadialGradient: {
201 const QRadialGradient* g = static_cast<const QRadialGradient*>(gradient);
202 newGradient->m_start = g->center();
203 newGradient->m_stop = g->center() + QPointF(g->radius(), 0);
204 newGradient->m_focalPoint = g->focalPoint();
205 break;
206 }
207 case QGradient::ConicalGradient: {
208 const QConicalGradient* g = static_cast<const QConicalGradient*>(gradient);
209 qreal radian = g->angle() * M_PI / 180.0;
210 newGradient->m_start = g->center();
211 newGradient->m_stop = QPointF(100.0 * cos(radian), 100.0 * sin(radian));
212 newGradient->m_focalPoint = g->center();
213 break;
214 }
215 default:
217 }
218
219 Q_FOREACH(const QGradientStop & stop, gradient->stops()) {
220 KoColor color(newGradient->colorSpace());
221 color.fromQColor(stop.second);
222 newGradient->m_stops.append(KoGradientStop(stop.first, color, COLORSTOP));
223 }
224
225 newGradient->setValid(true);
226
227 return newGradient;
228}
#define M_PI
Definition kis_global.h:111

References COLORSTOP, KoColor::fromQColor(), KoStopGradient(), and M_PI.

◆ fromXML()

KoStopGradient KoStopGradient::fromXML ( const QDomElement & elt)
static

fromXML convert a gradient from xml.

Returns
a gradient.

Definition at line 567 of file KoStopGradient.cpp.

568{
569 KoStopGradient gradient;
571 QDomElement stopElt = elt.firstChildElement("stop");
572 while (!stopElt.isNull()) {
573 qreal offset = KisDomUtils::toDouble(stopElt.attribute("offset", "0.0"));
574 QString bitDepth = stopElt.attribute("bitdepth", Integer8BitsColorDepthID.id());
575 KoColor color = KoColor::fromXML(stopElt.firstChildElement(), bitDepth);
576 color.setOpacity(KisDomUtils::toDouble(stopElt.attribute("alpha", "1.0")));
577 KoGradientStopType stoptype = static_cast<KoGradientStopType>(KisDomUtils::toInt(stopElt.attribute("stoptype", "0")));
578 stops.append(KoGradientStop(offset, color, stoptype));
579 stopElt = stopElt.nextSiblingElement("stop");
580 }
581 gradient.setStops(stops);
582 return gradient;
583}
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
KoGradientStopType
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
Definition KoColor.cpp:350
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
QString id() const
Definition KoID.cpp:63
void setStops(QList< KoGradientStop > stops)
Sets the gradient stops.
QList< KoGradientStop > stops() const
double toDouble(const QString &str, bool *ok=nullptr)
int toInt(const QString &str, bool *ok=nullptr)

References KoColor::fromXML(), KoID::id(), Integer8BitsColorDepthID, KoColor::setOpacity(), setStops(), stops(), KisDomUtils::toDouble(), and KisDomUtils::toInt().

◆ loadFromDevice()

bool KoStopGradient::loadFromDevice ( QIODevice * dev,
KisResourcesInterfaceSP resourcesInterface )
overridevirtual

Implements KoResource.

Definition at line 74 of file KoStopGradient.cpp.

75{
76 Q_UNUSED(resourcesInterface);
77 loadSvgGradient(dev);
78 if (m_stops.count() >= 2) {
79 setValid(true);
80 }
82 return true;
83}
void loadSvgGradient(QIODevice *file)
void setValid(bool valid)

References loadSvgGradient(), m_stops, KoResource::setValid(), and KoAbstractGradient::updatePreview().

◆ loadSvgGradient()

void KoStopGradient::loadSvgGradient ( QIODevice * file)
private

Definition at line 299 of file KoStopGradient.cpp.

300{
301 QDomDocument doc;
302
303 if (!(doc.setContent(file))) {
304 file->close();
305 } else {
306 QHash<QString, const KoColorProfile*> profiles;
307 for (QDomElement e = doc.documentElement().firstChildElement("defs"); !e.isNull(); e = e.nextSiblingElement("defs")) {
308 for (QDomElement profileEl = e.firstChildElement("color-profile"); !profileEl.isNull(); profileEl = profileEl.nextSiblingElement("color-profile")) {
309 const QString href = profileEl.attribute("xlink:href");
310 const QByteArray uniqueId = QByteArray::fromHex(profileEl.attribute("local").toLatin1());
311 const QString name = profileEl.attribute("name");
312
313 const KoColorProfile *profile =
315 if (!profile) {
316 QFile file(href);
317 if (file.exists()) {
319 KIS_ASSERT(engine);
320 file.open(QIODevice::ReadOnly);
321 const QByteArray profileData = file.readAll();
322 if (!profileData.isEmpty()) {
323 profile = engine->addProfile(href);
324 }
325 }
326 }
327
328
329 if (profile && !profiles.contains(name)) {
330 profiles.insert(name, profile);
331 }
332 }
333 }
334 for (QDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling()) {
335 QDomElement e = n.toElement();
336
337 if (e.isNull()) continue;
338
339 if (e.tagName() == "linearGradient" || e.tagName() == "radialGradient") {
340 parseSvgGradient(e, profiles);
341 return;
342 }
343 // Inkscape gradients are in another defs
344 if (e.tagName() == "defs") {
345
346
347 for (QDomNode defnode = e.firstChild(); !defnode.isNull(); defnode = defnode.nextSibling()) {
348 QDomElement defelement = defnode.toElement();
349
350 if (defelement.isNull()) continue;
351
352 if (defelement.tagName() == "linearGradient" || defelement.tagName() == "radialGradient") {
353 parseSvgGradient(defelement, profiles);
354 return;
355 }
356 }
357 }
358 }
359 }
360}
static KoColorSpaceEngineRegistry * instance()
T get(const QString &id) const
void parseSvgGradient(const QDomElement &element, QHash< QString, const KoColorProfile * > profiles)
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
virtual const KoColorProfile * addProfile(const QString &filename)=0
static KoColorSpaceRegistry * instance()
const KoColorProfile * profileByUniqueId(const QByteArray &id) const
QString name

References KoColorSpaceEngine::addProfile(), KoGenericRegistry< T >::get(), KoColorSpaceEngineRegistry::instance(), KoColorSpaceRegistry::instance(), KIS_ASSERT, KoResource::name, parseSvgGradient(), and KoColorSpaceRegistry::profileByUniqueId().

◆ operator=()

KoStopGradient & KoStopGradient::operator= ( const KoStopGradient & rhs)
delete

◆ operator==()

bool KoStopGradient::operator== ( const KoStopGradient & rhs) const

Definition at line 57 of file KoStopGradient.cpp.

58{
59 return
60 *colorSpace() == *rhs.colorSpace() &&
61 spread() == rhs.spread() &&
62 type() == rhs.type() &&
63 m_start == rhs.m_start &&
64 m_stop == rhs.m_stop &&
66 m_stops == rhs.m_stops;
67}
const KoColorSpace * colorSpace
QGradient::Spread spread

References KoAbstractGradient::colorSpace, m_focalPoint, m_start, m_stop, m_stops, KoAbstractGradient::spread, and KoAbstractGradient::type.

◆ parseSvgGradient()

void KoStopGradient::parseSvgGradient ( const QDomElement & element,
QHash< QString, const KoColorProfile * > profiles )
private

Definition at line 363 of file KoStopGradient.cpp.

364{
365 m_stops.clear();
366 m_hasVariableStops = false;
367 setSpread(QGradient::PadSpread);
368
369 /*QString href = e.attribute( "xlink:href" ).mid( 1 );
370 if( !href.isEmpty() )
371 {
372 }*/
373 setName(element.attribute("id", i18n("SVG Gradient")));
374
375 bool bbox = element.attribute("gradientUnits") != "userSpaceOnUse";
376
377 if (element.tagName() == "linearGradient") {
378
379 if (bbox) {
380 QString s;
381
382 s = element.attribute("x1", "0%");
383 qreal xOrigin;
384 if (s.endsWith('%'))
385 xOrigin = s.remove('%').toDouble();
386 else
387 xOrigin = s.toDouble() * 100.0;
388
389 s = element.attribute("y1", "0%");
390 qreal yOrigin;
391 if (s.endsWith('%'))
392 yOrigin = s.remove('%').toDouble();
393 else
394 yOrigin = s.toDouble() * 100.0;
395
396 s = element.attribute("x2", "100%");
397 qreal xVector;
398 if (s.endsWith('%'))
399 xVector = s.remove('%').toDouble();
400 else
401 xVector = s.toDouble() * 100.0;
402
403 s = element.attribute("y2", "0%");
404 qreal yVector;
405 if (s.endsWith('%'))
406 yVector = s.remove('%').toDouble();
407 else
408 yVector = s.toDouble() * 100.0;
409
410 m_start = QPointF(xOrigin, yOrigin);
411 m_stop = QPointF(xVector, yVector);
412 }
413 else {
414 m_start = QPointF(element.attribute("x1").toDouble(), element.attribute("y1").toDouble());
415 m_stop = QPointF(element.attribute("x2").toDouble(), element.attribute("y2").toDouble());
416 }
417 setType(QGradient::LinearGradient);
418 }
419 else {
420 if (bbox) {
421 QString s;
422
423 s = element.attribute("cx", "50%");
424 qreal xOrigin;
425 if (s.endsWith('%'))
426 xOrigin = s.remove('%').toDouble();
427 else
428 xOrigin = s.toDouble() * 100.0;
429
430 s = element.attribute("cy", "50%");
431 qreal yOrigin;
432 if (s.endsWith('%'))
433 yOrigin = s.remove('%').toDouble();
434 else
435 yOrigin = s.toDouble() * 100.0;
436
437 s = element.attribute("cx", "50%");
438 qreal xVector;
439 if (s.endsWith('%'))
440 xVector = s.remove('%').toDouble();
441 else
442 xVector = s.toDouble() * 100.0;
443
444 s = element.attribute("r", "50%");
445 if (s.endsWith('%'))
446 xVector += s.remove('%').toDouble();
447 else
448 xVector += s.toDouble() * 100.0;
449
450 s = element.attribute("cy", "50%");
451 qreal yVector;
452 if (s.endsWith('%'))
453 yVector = s.remove('%').toDouble();
454 else
455 yVector = s.toDouble() * 100.0;
456
457 s = element.attribute("fx", "50%");
458 qreal xFocal;
459 if (s.endsWith('%'))
460 xFocal = s.remove('%').toDouble();
461 else
462 xFocal = s.toDouble() * 100.0;
463
464 s = element.attribute("fy", "50%");
465 qreal yFocal;
466 if (s.endsWith('%'))
467 yFocal = s.remove('%').toDouble();
468 else
469 yFocal = s.toDouble() * 100.0;
470
471 m_start = QPointF(xOrigin, yOrigin);
472 m_stop = QPointF(xVector, yVector);
473 m_focalPoint = QPointF(xFocal, yFocal);
474 }
475 else {
476 m_start = QPointF(element.attribute("cx").toDouble(), element.attribute("cy").toDouble());
477 m_stop = QPointF(element.attribute("cx").toDouble() + element.attribute("r").toDouble(),
478 element.attribute("cy").toDouble());
479 m_focalPoint = QPointF(element.attribute("fx").toDouble(), element.attribute("fy").toDouble());
480 }
481 setType(QGradient::RadialGradient);
482 }
483 // handle spread method
484 QString spreadMethod = element.attribute("spreadMethod");
485 if (!spreadMethod.isEmpty()) {
486 if (spreadMethod == "reflect")
487 setSpread(QGradient::ReflectSpread);
488 else if (spreadMethod == "repeat")
489 setSpread(QGradient::RepeatSpread);
490 }
491
492 for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling()) {
493 QDomElement colorstop = n.toElement();
494 if (colorstop.tagName() == "stop") {
495 qreal opacity = 0.0;
496 KoColor color;
497 float off;
498 QString temp = colorstop.attribute("offset");
499 if (temp.contains('%')) {
500 temp = temp.left(temp.length() - 1);
501 off = temp.toFloat() / 100.0;
502 }
503 else
504 off = temp.toFloat();
505
506 if (!colorstop.attribute("stop-color").isEmpty())
507 color = KoColor::fromSVG11(colorstop.attribute("stop-color"), profiles);
508 else {
509 // try style attr
510 QString style = colorstop.attribute("style").simplified();
511 QStringList substyles = style.split(';', Qt::SkipEmptyParts);
512 Q_FOREACH(const QString & s, substyles) {
513 QStringList substyle = s.split(':');
514 QString command = substyle[0].trimmed();
515 QString params = substyle[1].trimmed();
516 if (command == "stop-color")
517 color = KoColor::fromSVG11(params, profiles);
518 if (command == "stop-opacity")
519 opacity = params.toDouble();
520 }
521
522 }
523 if (!colorstop.attribute("stop-opacity").isEmpty())
524 opacity = colorstop.attribute("stop-opacity").toDouble();
525
526 color.setOpacity(static_cast<quint8>(std::lround(opacity * OPACITY_OPAQUE_U8)));
527 QString stopTypeStr = colorstop.attribute("krita:stop-type", "color-stop");
529 if (stopType != COLORSTOP) {
530 m_hasVariableStops = true;
531 }
532 //According to the SVG spec each gradient offset has to be equal to or greater than the previous one
533 //if not it needs to be adjusted to be equal
534 if (m_stops.count() > 0 && m_stops.last().position >= off) {
535 off = m_stops.last().position;
536 }
537 m_stops.append(KoGradientStop(off, color, stopType));
538 }
539 }
540 if (m_stops.count() >= 2) {
541 setValid(true);
542 } else {
543 setValid(false);
544 }
545}
const quint8 OPACITY_OPAQUE_U8
static KoColor fromSVG11(const QString value, QHash< QString, const KoColorProfile * > profileList, KoColor current=KoColor())
fromSVG11 Parses a color attribute value and returns a KoColor. SVG defines the colorprofiles elsewhe...
Definition KoColor.cpp:534
void setSpread(QGradient::Spread spreadMethod)
void setType(QGradient::Type repeatType)
static KoGradientStopType typeFromString(QString typestring)
void setName(const QString &name)

References COLORSTOP, KoColor::fromSVG11(), m_focalPoint, m_hasVariableStops, m_start, m_stop, m_stops, OPACITY_OPAQUE_U8, KoResource::setName(), KoColor::setOpacity(), KoAbstractGradient::setSpread(), KoAbstractGradient::setType(), KoResource::setValid(), and KoGradientStop::typeFromString().

◆ requiredCanvasResources()

QList< int > KoStopGradient::requiredCanvasResources ( ) const
overridevirtual

A list of per-canvas active resources that are needed for this resource to function properly. E.g. some gradients may require Fg/Bg colors and some presets would like to know about the current gradient selection.

Returns
a list of canvas resources needed for the current resource

Reimplemented from KoResource.

Definition at line 255 of file KoStopGradient.cpp.

256{
257 QList<int> result;
258
259 if (std::find_if_not(m_stops.begin(), m_stops.end(),
261 != m_stops.end()) {
262
264 }
265
266 return result;
267}
auto mem_equal_to(MemTypeNoRef Class::*ptr, MemType &&value)
mem_equal_to is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:233
KoGradientStopType type

References KoCanvasResource::BackgroundColor, COLORSTOP, KoCanvasResource::ForegroundColor, m_stops, kismpl::mem_equal_to(), and KoGradientStop::type.

◆ resourceType()

QPair< QString, QString > KoStopGradient::resourceType ( ) const
inlineoverridevirtual
Returns
the resource type

Implements KoResource.

Definition at line 104 of file KoStopGradient.h.

104 {
105 return QPair<QString, QString>(ResourceType::Gradients, ResourceSubType::StopGradients);
106 }
const QString StopGradients
const QString Gradients

References ResourceType::Gradients, and ResourceSubType::StopGradients.

◆ saveSvgGradient()

QString KoStopGradient::saveSvgGradient ( ) const

Definition at line 585 of file KoStopGradient.cpp.

586{
587 QDomDocument doc;
588
589 doc.setContent(QString("<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:krita=\"%1\" > </svg>").arg(KoXmlNS::krita));
590
591 const QString spreadMethod[3] = {
592 QString("pad"),
593 QString("reflect"),
594 QString("repeat")
595 };
596
597 QDomElement gradient = doc.createElement("linearGradient");
598 gradient.setAttribute("id", name());
599 gradient.setAttribute("gradientUnits", "objectBoundingBox");
600 gradient.setAttribute("spreadMethod", spreadMethod[spread()]);
601
602 QHash<QString, const KoColorProfile*> profiles;
603 for(const KoGradientStop & stop: m_stops) {
604 QDomElement stopEl = doc.createElement("stop");
605 stopEl.setAttribute("stop-color", stop.color.toSVG11(&profiles));
606 stopEl.setAttribute("offset", QString().setNum(stop.position));
607 stopEl.setAttribute("stop-opacity", stop.color.opacityF());
608 stopEl.setAttribute("krita:stop-type", stop.typeString());
609 gradient.appendChild(stopEl);
610 }
611
612 if (profiles.size()>0) {
613 QDomElement defs = doc.createElement("defs");
614 for (QString key: profiles.keys()) {
615 const KoColorProfile * profile = profiles.value(key);
616
617 QDomElement profileEl = doc.createElement("color-profile");
618 profileEl.setAttribute("name", key);
619 QString val = profile->uniqueId().toHex();
620 profileEl.setAttribute("local", val);
621 profileEl.setAttribute("xlink:href", profile->fileName());
622 defs.appendChild(profileEl);
623 }
624 doc.documentElement().appendChild(defs);
625 }
626
627 doc.documentElement().appendChild(gradient);
628
629 return doc.toString();
630}
static const QString krita
Definition KoXmlNS.h:48
virtual QByteArray uniqueId() const =0

References KoColorProfile::fileName, KoXmlNS::krita, m_stops, KoResource::name, KoAbstractGradient::spread, and KoColorProfile::uniqueId().

◆ saveToDevice()

bool KoStopGradient::saveToDevice ( QIODevice * dev) const
overridevirtual

Reimplemented from KoResource.

Definition at line 632 of file KoStopGradient.cpp.

633{
634 QTextStream stream(dev);
636 stream << saveSvgGradient();
637
638 return true;
639}
QString saveSvgGradient() const
void setUtf8OnStream(QTextStream &stream)

References saveSvgGradient(), and KisPortingUtils::setUtf8OnStream().

◆ setStops()

void KoStopGradient::setStops ( QList< KoGradientStop > stops)

Sets the gradient stops.

Definition at line 230 of file KoStopGradient.cpp.

231{
232 m_stops.clear();
233 m_hasVariableStops = false;
234 KoColor color;
235 Q_FOREACH(const KoGradientStop & stop, stops) {
236 color = stop.color;
237 m_stops.append(KoGradientStop(stop.position, color, stop.type));
238 if (stop.type != COLORSTOP) {
239 m_hasVariableStops = true;
240 }
241 }
242 if (m_stops.count() >= 2) {
243 setValid(true);
244 } else {
245 setValid(false);
246 }
248}

References KoGradientStop::color, COLORSTOP, m_hasVariableStops, m_stops, KoGradientStop::position, KoResource::setValid(), stops(), KoGradientStop::type, and KoAbstractGradient::updatePreview().

◆ stops()

QList< KoGradientStop > KoStopGradient::stops ( ) const

Definition at line 250 of file KoStopGradient.cpp.

251{
252 return m_stops;
253}

References m_stops.

◆ stopsAt()

bool KoStopGradient::stopsAt ( KoGradientStop & leftStop,
KoGradientStop & rightStop,
qreal t ) const

Find stops surrounding position, returns false if position outside gradient.

Definition at line 122 of file KoStopGradient.cpp.

123{
124 if (!m_stops.count())
125 return false;
126
127 KIS_SAFE_ASSERT_RECOVER(!qIsNaN(t)) { // if it's nan, it would crash in the last 'else'
128 leftStop = m_stops.first();
129 rightStop = KoGradientStop(-std::numeric_limits<double>::infinity(), leftStop.color, leftStop.type);
130 return true;
131 }
132
133 if (t <= m_stops.first().position || m_stops.count() == 1) {
134 // we have only one stop or t is before the first stop
135 leftStop = m_stops.first();
136 rightStop = KoGradientStop(-std::numeric_limits<double>::infinity(), leftStop.color, leftStop.type);
137 return true;
138 } else if (t >= m_stops.last().position) {
139 // t is after the last stop
140 rightStop = m_stops.last();
141 leftStop = KoGradientStop(std::numeric_limits<double>::infinity(), rightStop.color, rightStop.type);
142 return true;
143 } else {
144 // we have at least two color stops
145 // -> find the two stops which frame our t
146 auto it = std::lower_bound(m_stops.begin(), m_stops.end(), KoGradientStop(t, KoColor(), COLORSTOP),
148 leftStop = *(it - 1);
149 rightStop = *(it);
150 return true;
151 }
152}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
auto mem_less(MemTypeNoRef Class::*ptr, MemType &&value)
mem_less is an unary functor that compares a member of the object to a given value
Definition KisMpl.h:269

References KoGradientStop::color, COLORSTOP, KIS_SAFE_ASSERT_RECOVER, m_stops, kismpl::mem_less(), KoGradientStop::position, and KoGradientStop::type.

◆ toQGradient()

QGradient * KoStopGradient::toQGradient ( ) const
overridevirtual

reimplemented

Reimplemented from KoAbstractGradient.

Definition at line 85 of file KoStopGradient.cpp.

86{
87 QGradient* gradient;
88
89 switch (type()) {
90 case QGradient::LinearGradient: {
91 gradient = new QLinearGradient(m_start, m_stop);
92 break;
93 }
94 case QGradient::RadialGradient: {
95 QPointF diff = m_stop - m_start;
96 qreal radius = sqrt(diff.x() * diff.x() + diff.y() * diff.y());
97 gradient = new QRadialGradient(m_start, radius, m_focalPoint);
98 break;
99 }
100 case QGradient::ConicalGradient: {
101 qreal angle = atan2(m_start.y(), m_start.x()) * 180.0 / M_PI;
102 if (angle < 0.0)
103 angle += 360.0;
104 gradient = new QConicalGradient(m_start, angle);
105 break;
106 }
107 default:
108 return 0;
109 }
110 QColor color;
111 for (QList<KoGradientStop>::const_iterator i = m_stops.begin(); i != m_stops.end(); ++i) {
112 i->color.toQColor(&color);
113 gradient->setColorAt(i->position, color);
114 }
115
116 gradient->setCoordinateMode(QGradient::ObjectBoundingMode);
117 gradient->setSpread(this->spread());
118
119 return gradient;
120}
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement

References m_focalPoint, M_PI, m_start, m_stop, m_stops, KoAbstractGradient::spread, and KoAbstractGradient::type.

◆ toXML()

void KoStopGradient::toXML ( QDomDocument & doc,
QDomElement & gradientElt ) const

toXML Convert the gradient to an XML string.

Definition at line 552 of file KoStopGradient.cpp.

553{
554 gradientElt.setAttribute("type", "stop");
555 for (int s = 0; s < m_stops.size(); s++) {
556 KoGradientStop stop = m_stops.at(s);
557 QDomElement stopElt = doc.createElement("stop");
558 stopElt.setAttribute("offset", KisDomUtils::toString(stop.position));
559 stopElt.setAttribute("bitdepth", stop.color.colorSpace()->colorDepthId().id());
560 stopElt.setAttribute("alpha", KisDomUtils::toString(stop.color.opacityF()));
561 stopElt.setAttribute("stoptype", KisDomUtils::toString(stop.type));
562 stop.color.toXML(doc, stopElt);
563 gradientElt.appendChild(stopElt);
564 }
565}
virtual KoID colorDepthId() const =0
qreal opacityF() const
Definition KoColor.cpp:345
void toXML(QDomDocument &doc, QDomElement &colorElt) const
Definition KoColor.cpp:304
QString toString(const QString &value)

References KoGradientStop::color, KoColorSpace::colorDepthId(), KoColor::colorSpace(), KoID::id(), m_stops, KoColor::opacityF(), KoGradientStop::position, KisDomUtils::toString(), KoColor::toXML(), and KoGradientStop::type.

◆ updateVariableColors()

void KoStopGradient::updateVariableColors ( KoCanvasResourcesInterfaceSP canvasResourcesInterface)
overridevirtual

Reimplemented from KoAbstractGradient.

Definition at line 285 of file KoStopGradient.cpp.

286{
287 const KoColor fgColor = canvasResourcesInterface->resource(KoCanvasResource::ForegroundColor).value<KoColor>();
288 const KoColor bgColor = canvasResourcesInterface->resource(KoCanvasResource::BackgroundColor).value<KoColor>();
289
290 for (auto it = m_stops.begin(); it != m_stops.end(); ++it) {
291 if (it->type == FOREGROUNDSTOP) {
292 it->color = fgColor;
293 } else if (it->type == BACKGROUNDSTOP) {
294 it->color = bgColor;
295 }
296 }
297}

References KoCanvasResource::BackgroundColor, BACKGROUNDSTOP, KoCanvasResource::ForegroundColor, FOREGROUNDSTOP, and m_stops.

Member Data Documentation

◆ m_focalPoint

QPointF KoStopGradient::m_focalPoint
protected

Definition at line 152 of file KoStopGradient.h.

◆ m_hasVariableStops

bool KoStopGradient::m_hasVariableStops = false
protected

Definition at line 149 of file KoStopGradient.h.

◆ m_start

QPointF KoStopGradient::m_start
protected

Definition at line 150 of file KoStopGradient.h.

◆ m_stop

QPointF KoStopGradient::m_stop
protected

Definition at line 151 of file KoStopGradient.h.

◆ m_stops

QList<KoGradientStop> KoStopGradient::m_stops
protected

Definition at line 148 of file KoStopGradient.h.


The documentation for this class was generated from the following files: