Krita Source Code Documentation
Loading...
Searching...
No Matches
KoMeshPatchesRenderer Struct Reference

#include <KoMeshPatchesRenderer.h>

Public Member Functions

void calculateAlpha (const SvgMeshArray *mesharray, const int row, const int col, const SvgMeshPatch *patch)
 
bool checkColorVariance (quint8 c[4][4])
 
void configure (QRectF gradientRect, const QTransform &painterTransform)
 
QVector< qreal > derivative (const SvgMeshStop &stop0, const SvgMeshStop &stop1, const SvgMeshStop &stop2)
 
QVector< QVector< qreal > > derivativeEdgeBeginX (const SvgMeshPatch *patch0, const SvgMeshPatch *patch1)
 Derivative in the X direction. The edge has to be in left-most column.
 
QVector< QVector< qreal > > derivativeEdgeBeginY (const SvgMeshPatch *patch0, const SvgMeshPatch *patch1)
 Derivative in the Y direction. The edge has to be in top row.
 
QVector< QVector< qreal > > derivativeEdgeEndX (const SvgMeshPatch *patch1, const SvgMeshPatch *patch0)
 
QVector< QVector< qreal > > derivativeEdgeEndY (const SvgMeshPatch *patch1, const SvgMeshPatch *patch0)
 
QVector< QVector< qreal > > derivativeX (const SvgMeshPatch *patch0, const SvgMeshPatch *patch1, const SvgMeshPatch *patch2)
 Derivative in the X direction, but the patch should not be on an edge.
 
QVector< QVector< qreal > > derivativeY (const SvgMeshPatch *patch0, const SvgMeshPatch *patch1, const SvgMeshPatch *patch2)
 Derivative in the Y direction, but the patch should not be on an edge.
 
QVector< qreal > difference (const QVector< qreal > &v1, const QVector< qreal > &v2)
 
void fillPatch (const SvgMeshPatch *patch, SvgMeshGradient::Shading type, const SvgMeshArray *mesharray=nullptr, const int row=-1, const int col=-1)
 
QVector< qreal > getAlpha (const QVector< qreal > &X)
 Naming convention adopted from: https://en.wikipedia.org/wiki/Bicubic_interpolation#Computation.
 
QVector< QColor > getColorsBicubic (const SvgMeshPatch *patch)
 
QVector< QColor > getColorsBilinear (const SvgMeshPatch *patch)
 
QColor getColorUsingAlpha (const QVector< QVector< qreal > > &alpha, QPointF p)
 
qreal getValue (const QVector< qreal > &alpha, const QPointF p)
 
 KoMeshPatchesRenderer ()
 
QColor midPointColor (QColor first, QColor second)
 
QVector< qreal > multiply (const QVector< qreal > &v1, qreal n)
 
QImage * patchImage ()
 
QVector< qreal > secant (const SvgMeshStop &stop1, const SvgMeshStop &stop2)
 
QVector< qreal > split (QColor c)
 

Private Attributes

QVector< QVector< qreal > > m_alpha
 
QImage m_patch
 
QPainter m_patchPainter
 

Detailed Description

Definition at line 21 of file KoMeshPatchesRenderer.h.

Constructor & Destructor Documentation

◆ KoMeshPatchesRenderer()

KoMeshPatchesRenderer::KoMeshPatchesRenderer ( )
inline

Definition at line 24 of file KoMeshPatchesRenderer.h.

25 {}

Member Function Documentation

◆ calculateAlpha()

void KoMeshPatchesRenderer::calculateAlpha ( const SvgMeshArray * mesharray,
const int row,
const int col,
const SvgMeshPatch * patch )
inline

Definition at line 458 of file KoMeshPatchesRenderer.h.

459 {
460 // This is the convention which is being followed:
461 //
462 // f00, f03, f30, f33 are corners and their respective derivatives are represented as
463 // d00, d03, d30, d33
464 //
465 // +-----> U/x (row)
466 // |
467 // | f00-------f01-------f02-------f03
468 // V | | | |
469 // V/y (col) | | | |
470 // | | | |
471 // f10-------f11-------f12-------f13
472 // | | | |
473 // | | | |
474 // | | | |
475 // f20-------f21-------f22-------f23
476 // | | | |
477 // | | | |
478 // | | | |
479 // f30-------f31-------f32-------f33
480 //
481
486
489
490 // dx
491 if (!mesharray || mesharray->numColumns() < 2) {
492
493 // NOTE: they're zero here: from trial and error
494 dx[0] = multiply(secant(f11, f12), 2);
495 dx[2] = multiply(secant(f21, f22), 2);
496 dx[1] = dx[3] = {0, 0, 0, 0};
497
498 } else if (col == 0) {
499 dx = derivativeEdgeBeginX(patch, mesharray->getPatch(row, col + 1));
500
501 } else if (col == mesharray->numColumns() - 1) {
502 dx = derivativeEdgeEndX(mesharray->getPatch(row, col),
503 mesharray->getPatch(row, col - 1));
504 } else {
505 dx = derivativeX(mesharray->getPatch(row, col - 1),
506 mesharray->getPatch(row, col),
507 mesharray->getPatch(row, col + 1));
508 }
509
510 // dy
511 if (!mesharray || mesharray->numRows() < 2) {
512
513 // NOTE: they're zero here: from trial and error
514 dy[0] = multiply(secant(f11, f21), 2);
515 dy[1] = multiply(secant(f12, f22), 2);
516 dy[2] = dy[3] = {0, 0, 0, 0};
517
518 } else if (row == 0) {
519 dy = derivativeEdgeBeginY(patch, mesharray->getPatch(row + 1, col));
520
521 } else if (row == mesharray->numRows() - 1) {
522 dy = derivativeEdgeEndY(mesharray->getPatch(row, col),
523 mesharray->getPatch(row - 1, col));
524 } else {
525 dy = derivativeY(mesharray->getPatch(row - 1, col),
526 mesharray->getPatch(row, col),
527 mesharray->getPatch(row + 1, col));
528 }
529
530 QVector<QVector<qreal>> c = {split(f11.color), split(f12.color), split(f21.color), split(f22.color)};
531 QVector<QVector<qreal>> alpha(4, QVector<qreal>(16, 0));
532
533 qreal width01 = QLineF(f11.point, f12.point).length();
534 qreal width23 = QLineF(f21.point, f22.point).length();
535
536 qreal height01 = QLineF(f11.point, f21.point).length();
537 qreal height23 = QLineF(f12.point, f22.point).length();
538
539 for (int i = 0; i < 4; ++i) {
541 c[0][i],
542 c[1][i],
543 c[2][i],
544 c[3][i],
545
546 dx[0][i] * width01,
547 dx[1][i] * width01,
548 dx[2][i] * width23,
549 dx[3][i] * width23,
550
551 dy[0][i] * height01,
552 dy[1][i] * height23,
553 dy[2][i] * height01,
554 dy[3][i] * height23,
555
556 // Specs says not to care about cross derivatives
557 0,
558 0,
559 0,
560 0};
561
562 alpha[i] = getAlpha(X);
563 }
564
565 m_alpha = alpha;
566 }
int numRows() const
int numColumns() const
SvgMeshPatch * getPatch(const int row, const int col) const
SvgMeshStop getStop(Type type) const
returns the starting point of the stop
const QString X
QVector< QVector< qreal > > derivativeY(const SvgMeshPatch *patch0, const SvgMeshPatch *patch1, const SvgMeshPatch *patch2)
Derivative in the Y direction, but the patch should not be on an edge.
QVector< qreal > multiply(const QVector< qreal > &v1, qreal n)
QVector< QVector< qreal > > derivativeEdgeBeginY(const SvgMeshPatch *patch0, const SvgMeshPatch *patch1)
Derivative in the Y direction. The edge has to be in top row.
QVector< QVector< qreal > > derivativeEdgeEndY(const SvgMeshPatch *patch1, const SvgMeshPatch *patch0)
QVector< QVector< qreal > > derivativeEdgeEndX(const SvgMeshPatch *patch1, const SvgMeshPatch *patch0)
QVector< QVector< qreal > > derivativeEdgeBeginX(const SvgMeshPatch *patch0, const SvgMeshPatch *patch1)
Derivative in the X direction. The edge has to be in left-most column.
QVector< qreal > split(QColor c)
QVector< qreal > secant(const SvgMeshStop &stop1, const SvgMeshStop &stop2)
QVector< QVector< qreal > > m_alpha
QVector< QVector< qreal > > derivativeX(const SvgMeshPatch *patch0, const SvgMeshPatch *patch1, const SvgMeshPatch *patch2)
Derivative in the X direction, but the patch should not be on an edge.
QVector< qreal > getAlpha(const QVector< qreal > &X)
Naming convention adopted from: https://en.wikipedia.org/wiki/Bicubic_interpolation#Computation.
QPointF point

References SvgMeshPatch::Bottom, SvgMeshStop::color, derivativeEdgeBeginX(), derivativeEdgeBeginY(), derivativeEdgeEndX(), derivativeEdgeEndY(), derivativeX(), derivativeY(), getAlpha(), SvgMeshArray::getPatch(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, m_alpha, multiply(), SvgMeshArray::numColumns(), SvgMeshArray::numRows(), SvgMeshStop::point, SvgMeshPatch::Right, secant(), split(), and SvgMeshPatch::Top.

◆ checkColorVariance()

bool KoMeshPatchesRenderer::checkColorVariance ( quint8 c[4][4])
inline

Definition at line 150 of file KoMeshPatchesRenderer.h.

151 {
153 const quint8 tolerance = 0;
154
155 for (int i = 0; i < 3; ++i) {
156 if (cs->difference(c[i], c[i + 1]) > tolerance) {
157 return true;
158 }
159
160 if (c[i][3] != c[i + 1][3] && cs->differenceA(c[i], c[i + 1]) > tolerance) {
161 return true;
162 }
163 }
164
165 return false;
166 }
virtual quint8 difference(const quint8 *src1, const quint8 *src2) const =0
virtual quint8 differenceA(const quint8 *src1, const quint8 *src2) const =0
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())

References KoColorSpace::difference(), KoColorSpace::differenceA(), KoColorSpaceRegistry::instance(), and KoColorSpaceRegistry::rgb8().

◆ configure()

void KoMeshPatchesRenderer::configure ( QRectF gradientRect,
const QTransform & painterTransform )
inline

Definition at line 27 of file KoMeshPatchesRenderer.h.

27 {
28
29 // NOTE: This is a necessary step to prevent loss of quality, because painterTransform is scaled.
30
31 // we wish to scale the patch, but not translate, because patch should stay inside
32 // the boundingRect
33 QTransform painterTransformShifted = painterTransform *
34 QTransform::fromTranslate(painterTransform.dx(), painterTransform.dy()).inverted();
35
36 // we are applying transformation on a Unit rect, so we can extract scaling info only
37 QRectF unitRectScaled = painterTransformShifted.mapRect(QRectF(gradientRect.topLeft(), QSize(1, 1)));
38 QTransform scaledTransform = QTransform::fromScale(unitRectScaled.width(), unitRectScaled.height());
39
40 // boundingRect of the scaled version
41 QRectF scaledGradientRect = scaledTransform.mapRect(gradientRect);
42
43 m_patch = QImage(scaledGradientRect.size().toSize(), QImage::Format_ARGB32);
44 m_patch.fill(Qt::transparent);
45
46 m_patchPainter.begin(&m_patch);
47
48 // this ensures that the patch renders inside the boundingRect
49 m_patchPainter.translate(-scaledGradientRect.topLeft());
50
51 // upscale the patch to the same scaling factor as the painterTransform
52 m_patchPainter.setTransform(scaledTransform, true);
53 m_patchPainter.setCompositionMode(QPainter::CompositionMode_Source);
54 }

References m_patch, and m_patchPainter.

◆ derivative()

QVector< qreal > KoMeshPatchesRenderer::derivative ( const SvgMeshStop & stop0,
const SvgMeshStop & stop1,
const SvgMeshStop & stop2 )
inline

Definition at line 303 of file KoMeshPatchesRenderer.h.

306 {
307 QVector<qreal> delta0 = secant(stop0, stop1);
308 QVector<qreal> delta1 = secant(stop1, stop2);
309
310 QVector<qreal> result(4);
311
312 for (int i = 0; i < 4; ++i) {
313 qreal slope = (delta0[i] + delta1[i]) / 2;
314
315 // if sign changes
316 if ((delta0[i] * delta1[i]) < 0 && delta0[i] > 0) {
317 slope = 0;
318 } else if (abs(slope) > 3 * abs(delta0[i])) {
319 slope = 3 * delta0[i];
320 } else if (abs(slope) > 3 * abs(delta1[i])) {
321 slope = 3 * delta1[i];
322 }
323
324 result.push_back(slope);
325 }
326 return result;
327 }
Point abs(const Point &pt)

References secant().

◆ derivativeEdgeBeginX()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeEdgeBeginX ( const SvgMeshPatch * patch0,
const SvgMeshPatch * patch1 )
inline

Derivative in the X direction. The edge has to be in left-most column.

Definition at line 378 of file KoMeshPatchesRenderer.h.

380 {
385
388
389 QVector<qreal> d01 = derivative(f00, f01, f02);
390 QVector<qreal> d11 = derivative(f10, f11, f12);
391 QVector<qreal> d00 = difference(multiply(secant(f00, f01), 2), d01);
392 QVector<qreal> d10 = difference(multiply(secant(f10, f11), 2), d11);
393
394 return {d00, d01, d10, d11};
395 }
QVector< qreal > derivative(const SvgMeshStop &stop0, const SvgMeshStop &stop1, const SvgMeshStop &stop2)
QVector< qreal > difference(const QVector< qreal > &v1, const QVector< qreal > &v2)

References SvgMeshPatch::Bottom, derivative(), difference(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, multiply(), SvgMeshPatch::Right, secant(), and SvgMeshPatch::Top.

◆ derivativeEdgeBeginY()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeEdgeBeginY ( const SvgMeshPatch * patch0,
const SvgMeshPatch * patch1 )
inline

Derivative in the Y direction. The edge has to be in top row.

Definition at line 398 of file KoMeshPatchesRenderer.h.

400 {
405
408
409 QVector<qreal> d10 = derivative(f00, f10, f20);
410 QVector<qreal> d11 = derivative(f01, f11, f21);
411 QVector<qreal> d00 = difference(multiply(secant(f00, f10), 2), d10);
412 QVector<qreal> d01 = difference(multiply(secant(f01, f11), 2), d11);
413
414 return {d00, d01, d10, d11};
415 }

References SvgMeshPatch::Bottom, derivative(), difference(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, multiply(), SvgMeshPatch::Right, secant(), and SvgMeshPatch::Top.

◆ derivativeEdgeEndX()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeEdgeEndX ( const SvgMeshPatch * patch1,
const SvgMeshPatch * patch0 )
inline

Definition at line 418 of file KoMeshPatchesRenderer.h.

420 {
425
428
429 QVector<qreal> d02 = derivative(f01, f02, f03);
430 QVector<qreal> d12 = derivative(f11, f12, f13);
431 QVector<qreal> d03 = difference(multiply(secant(f02, f03), 2), d02);
432 QVector<qreal> d13 = difference(multiply(secant(f12, f13), 2), d12);
433
434 return {d02, d03, d12, d13};
435 }

References SvgMeshPatch::Bottom, derivative(), difference(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, multiply(), SvgMeshPatch::Right, secant(), and SvgMeshPatch::Top.

◆ derivativeEdgeEndY()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeEdgeEndY ( const SvgMeshPatch * patch1,
const SvgMeshPatch * patch0 )
inline

Definition at line 438 of file KoMeshPatchesRenderer.h.

440 {
445
448
449 QVector<qreal> d22 = derivative(f12, f22, f32);
450 QVector<qreal> d23 = derivative(f13, f23, f33);
451 QVector<qreal> d32 = difference(multiply(secant(f22, f32), 2), d22);
452 QVector<qreal> d33 = difference(multiply(secant(f23, f33), 2), d23);
453
454 return {d22, d23, d32, d33};
455 }

References SvgMeshPatch::Bottom, derivative(), difference(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, multiply(), SvgMeshPatch::Right, secant(), and SvgMeshPatch::Top.

◆ derivativeX()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeX ( const SvgMeshPatch * patch0,
const SvgMeshPatch * patch1,
const SvgMeshPatch * patch2 )
inline

Derivative in the X direction, but the patch should not be on an edge.

Definition at line 330 of file KoMeshPatchesRenderer.h.

333 {
336
341
344
345 QVector<qreal> d11 = derivative(f10, f11, f12);
346 QVector<qreal> d12 = derivative(f11, f12, f13);
347 QVector<qreal> d21 = derivative(f20, f21, f22);
348 QVector<qreal> d22 = derivative(f21, f22, f23);
349
350 return {d11, d12, d21, d22};
351 }

References SvgMeshPatch::Bottom, derivative(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ derivativeY()

QVector< QVector< qreal > > KoMeshPatchesRenderer::derivativeY ( const SvgMeshPatch * patch0,
const SvgMeshPatch * patch1,
const SvgMeshPatch * patch2 )
inline

Derivative in the Y direction, but the patch should not be on an edge.

Definition at line 354 of file KoMeshPatchesRenderer.h.

357 {
360
365
368
369 QVector<qreal> d11 = derivative(f01, f11, f21);
370 QVector<qreal> d12 = derivative(f02, f12, f22);
371 QVector<qreal> d21 = derivative(f11, f21, f31);
372 QVector<qreal> d22 = derivative(f12, f22, f32);
373
374 return {d11, d12, d21, d22};
375 }

References SvgMeshPatch::Bottom, derivative(), SvgMeshPatch::getStop(), SvgMeshPatch::Left, SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ difference()

QVector< qreal > KoMeshPatchesRenderer::difference ( const QVector< qreal > & v1,
const QVector< qreal > & v2 )
inline

Definition at line 168 of file KoMeshPatchesRenderer.h.

169 {
170 QVector<qreal> v3(4, 0);
171 for (int i = 0; i < 4; ++i) {
172 v3[i] = v1[i] - v2[i];
173 }
174 return v3;
175 }

◆ fillPatch()

void KoMeshPatchesRenderer::fillPatch ( const SvgMeshPatch * patch,
SvgMeshGradient::Shading type,
const SvgMeshArray * mesharray = nullptr,
const int row = -1,
const int col = -1 )
inline

Definition at line 56 of file KoMeshPatchesRenderer.h.

60 {
61
62 QColor color0 = patch->getStop(SvgMeshPatch::Top).color;
63 QColor color1 = patch->getStop(SvgMeshPatch::Right).color;
64 QColor color2 = patch->getStop(SvgMeshPatch::Bottom).color;
65 QColor color3 = patch->getStop(SvgMeshPatch::Left).color;
66
68
69 quint8 c[4][4];
70 cs->fromQColor(color0, c[0]);
71 cs->fromQColor(color1, c[1]);
72 cs->fromQColor(color2, c[2]);
73 cs->fromQColor(color3, c[3]);
74
75 bool verticalDiv = patch->isDivisibleVertically();
76 bool horizontalDiv = patch->isDivisibleHorizontally();
77 bool colorVariationExists = checkColorVariance(c);
78
79 if (colorVariationExists && (verticalDiv || horizontalDiv)) {
80 QVector<QColor> colors;
81 if (type == SvgMeshGradient::BICUBIC) {
82
83 // it is a parent patch, so calculate coefficients aka alpha
84 if (mesharray) {
85 calculateAlpha(mesharray, row, col, patch);
86 }
87
88 colors = getColorsBicubic(patch);
89 } else {
90 colors = getColorsBilinear(patch);
91 }
92
93 if (verticalDiv && horizontalDiv) {
95 patches.reserve(4);
96
97 patch->subdivide(patches, colors);
98 for (const auto& p: patches) {
99 fillPatch(p, type);
100 delete p;
101 }
102 } else if (verticalDiv) {
104 patches.reserve(2);
105
106 patch->subdivideVertically(patches, colors);
107 for (const auto& p: patches) {
108 fillPatch(p, type);
109 delete p;
110 }
111 } else if (horizontalDiv) {
113 patches.reserve(2);
114
115 patch->subdivideHorizontally(patches, colors);
116 for (const auto& p: patches) {
117 fillPatch(p, type);
118 delete p;
119 }
120 }
121
122 } else {
123 const QPainterPath outline = patch->getPath();
124 const QRectF patchRect = outline.boundingRect();
125
126 quint8 mixed[4];
127 cs->mixColorsOp()->mixColors(c[0], 4, mixed);
128
129 QColor average;
130 cs->toQColor(mixed, &average);
131
132 QPen pen(average);
133 pen.setWidth(0);
134 m_patchPainter.setPen(pen);
135
136 if (patchRect.width() <= 1 && patchRect.height() <= 1) {
137 m_patchPainter.drawPoint(patchRect.topLeft());
138 m_patchPainter.fillPath(outline, average);
139
140 } else {
141 m_patchPainter.setBrush(average);
142 m_patchPainter.drawPath(outline);
143 }
144 }
145 }
const Params2D p
virtual void toQColor(const quint8 *src, QColor *c) const =0
virtual void fromQColor(const QColor &color, quint8 *dst) const =0
KoMixColorsOp * mixColorsOp
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
QPainterPath getPath() const
Get full (closed) meshpath.
void subdivideVertically(QVector< SvgMeshPatch * > &subdivided, const QVector< QColor > &colors) const
void subdivideHorizontally(QVector< SvgMeshPatch * > &subdivided, const QVector< QColor > &colors) const
bool isDivisibleHorizontally() const
void subdivide(QVector< SvgMeshPatch * > &subdivided, const QVector< QColor > &colors) const
bool isDivisibleVertically() const
void calculateAlpha(const SvgMeshArray *mesharray, const int row, const int col, const SvgMeshPatch *patch)
QVector< QColor > getColorsBilinear(const SvgMeshPatch *patch)
QVector< QColor > getColorsBicubic(const SvgMeshPatch *patch)
bool checkColorVariance(quint8 c[4][4])
void fillPatch(const SvgMeshPatch *patch, SvgMeshGradient::Shading type, const SvgMeshArray *mesharray=nullptr, const int row=-1, const int col=-1)

References SvgMeshGradient::BICUBIC, SvgMeshPatch::Bottom, calculateAlpha(), checkColorVariance(), SvgMeshStop::color, fillPatch(), KoColorSpace::fromQColor(), getColorsBicubic(), getColorsBilinear(), SvgMeshPatch::getPath(), SvgMeshPatch::getStop(), KoColorSpaceRegistry::instance(), SvgMeshPatch::isDivisibleHorizontally(), SvgMeshPatch::isDivisibleVertically(), SvgMeshPatch::Left, m_patchPainter, KoMixColorsOp::mixColors(), KoColorSpace::mixColorsOp, p, KoColorSpaceRegistry::rgb8(), SvgMeshPatch::Right, SvgMeshPatch::subdivide(), SvgMeshPatch::subdivideHorizontally(), SvgMeshPatch::subdivideVertically(), SvgMeshPatch::Top, and KoColorSpace::toQColor().

◆ getAlpha()

QVector< qreal > KoMeshPatchesRenderer::getAlpha ( const QVector< qreal > & X)
inline

Naming convention adopted from: https://en.wikipedia.org/wiki/Bicubic_interpolation#Computation.

Definition at line 251 of file KoMeshPatchesRenderer.h.

252 {
253 const static qreal A[16][16] = {
254 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
255 { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
256 {-3, 3, 0, 0, -2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
257 { 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
258 { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
259 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
260 { 0, 0, 0, 0, 0, 0, 0, 0, -3, 3, 0, 0, -2,-1, 0, 0},
261 { 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0},
262 {-3, 0, 3, 0, 0, 0, 0, 0, -2, 0,-1, 0, 0, 0, 0, 0},
263 { 0, 0, 0, 0, -3, 0, 3, 0, 0, 0, 0, 0, -2, 0,-1, 0},
264 { 9,-9,-9, 9, 6, 3,-6,-3, 6,-6, 3,-3, 4, 2, 2, 1},
265 {-6, 6, 6,-6, -3,-3, 3, 3, -4, 4,-2, 2, -2,-2,-1,-1},
266 { 2, 0,-2, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0},
267 { 0, 0, 0, 0, 2, 0,-2, 0, 0, 0, 0, 0, 1, 0, 1, 0},
268 {-6, 6, 6,-6, -4,-2, 4, 2, -3, 3,-3, 3, -2,-1,-2,-1},
269 { 4,-4,-4, 4, 2, 2,-2,-2, 2,-2, 2,-2, 1, 1, 1, 1}};
270
271
272 QVector<qreal> alpha(16, 0);
273 for (int i = 0; i < 16; ++i) {
274 alpha[i] = 0;
275 for (int j = 0; j < 16; ++j) {
276 alpha[i] += A[i][j] * X[j];
277 }
278 }
279
280 return alpha;
281 }

References A.

◆ getColorsBicubic()

QVector< QColor > KoMeshPatchesRenderer::getColorsBicubic ( const SvgMeshPatch * patch)
inline

Definition at line 568 of file KoMeshPatchesRenderer.h.

569 {
570 QPointF midTop = patch->getMidpointParametric(SvgMeshPatch::Top);
571 QPointF midRight = patch->getMidpointParametric(SvgMeshPatch::Right);
572 QPointF midBottom = patch->getMidpointParametric(SvgMeshPatch::Bottom);
573 QPointF midLeft = patch->getMidpointParametric(SvgMeshPatch::Left);
574 QPointF center = (midTop + midBottom) / 2;
575
576 QVector<QColor> result(5);
577 result[0] = getColorUsingAlpha(m_alpha, midTop);
578 result[1] = getColorUsingAlpha(m_alpha, midRight);
579 result[2] = getColorUsingAlpha(m_alpha, midBottom);
580 result[3] = getColorUsingAlpha(m_alpha, midLeft);
581 result[4] = getColorUsingAlpha(m_alpha, center);
582
583 return result;
584 }
QPointF getMidpointParametric(Type type) const
returns the midPoint in parametric space
QColor getColorUsingAlpha(const QVector< QVector< qreal > > &alpha, QPointF p)

References SvgMeshPatch::Bottom, getColorUsingAlpha(), SvgMeshPatch::getMidpointParametric(), SvgMeshPatch::Left, m_alpha, SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ getColorsBilinear()

QVector< QColor > KoMeshPatchesRenderer::getColorsBilinear ( const SvgMeshPatch * patch)
inline

Definition at line 598 of file KoMeshPatchesRenderer.h.

599 {
600 QVector<QColor> result(5);
601
602 QColor c1 = patch->getStop(SvgMeshPatch::Top).color;
603 QColor c2 = patch->getStop(SvgMeshPatch::Right).color;
604 QColor c3 = patch->getStop(SvgMeshPatch::Bottom).color;
605 QColor c4 = patch->getStop(SvgMeshPatch::Left).color;
606
607 result[0] = midPointColor(c1, c2);
608 result[1] = midPointColor(c2, c3);
609 result[2] = midPointColor(c3, c4);
610 result[3] = midPointColor(c4, c1);
611 result[4] = midPointColor(midPointColor(result[0], result[2]), midPointColor(result[1], result[3]));
612
613 return result;
614 }
QColor midPointColor(QColor first, QColor second)

References SvgMeshPatch::Bottom, SvgMeshStop::color, SvgMeshPatch::getStop(), SvgMeshPatch::Left, midPointColor(), SvgMeshPatch::Right, and SvgMeshPatch::Top.

◆ getColorUsingAlpha()

QColor KoMeshPatchesRenderer::getColorUsingAlpha ( const QVector< QVector< qreal > > & alpha,
QPointF p )
inline

Definition at line 226 of file KoMeshPatchesRenderer.h.

227 {
228 qreal r = getValue(alpha[0], p);
229 qreal g = getValue(alpha[1], p);
230 qreal b = getValue(alpha[2], p);
231 qreal a = getValue(alpha[3], p);
232
233 // Clamp
234 r = r > 1.0 ? 1.0 : r;
235 g = g > 1.0 ? 1.0 : g;
236 b = b > 1.0 ? 1.0 : b;
237 a = a > 1.0 ? 1.0 : a;
238
239 r = r < 0.0 ? 0.0 : r;
240 g = g < 0.0 ? 0.0 : g;
241 b = b < 0.0 ? 0.0 : b;
242 a = a < 0.0 ? 0.0 : a;
243
244 QColor result;
245 result.setRgbF(r, g, b);
246 result.setAlphaF(a);
247 return result;
248 }

References getValue, and p.

◆ getValue()

qreal KoMeshPatchesRenderer::getValue ( const QVector< qreal > & alpha,
const QPointF p )
inline

Definition at line 192 of file KoMeshPatchesRenderer.h.

193 {
194 KIS_ASSERT(alpha.size() == 16);
195 qreal x = p.x(), y = p.y();
196 qreal result = 0;
197
198 qreal xx = x * x;
199 qreal xxx = xx * x;
200 qreal yy = y * y;
201 qreal yyy = yy * y;
202
203 result += alpha[0];
204 result += alpha[1] * x;
205 result += alpha[2] * xx;
206 result += alpha[3] * xxx;
207
208 result += alpha[4] * y;
209 result += alpha[5] * y * x;
210 result += alpha[6] * y * xx;
211 result += alpha[7] * y * xxx;
212
213 result += alpha[ 8] * yy;
214 result += alpha[ 9] * yy * x;
215 result += alpha[10] * yy * xx;
216 result += alpha[11] * yy * xxx;
217
218 result += alpha[12] * yyy;
219 result += alpha[13] * yyy * x;
220 result += alpha[14] * yyy * xx;
221 result += alpha[15] * yyy * xxx;
222
223 return result;
224 }
#define KIS_ASSERT(cond)
Definition kis_assert.h:33

References KIS_ASSERT, and p.

◆ midPointColor()

QColor KoMeshPatchesRenderer::midPointColor ( QColor first,
QColor second )
inline

Definition at line 586 of file KoMeshPatchesRenderer.h.

587 {
588 qreal a = (first.alphaF() + second.alphaF()) / 2;
589 qreal r = (first.redF() + second.redF()) / 2;
590 qreal g = (first.greenF() + second.greenF()) / 2;
591 qreal b = (first.blueF() + second.blueF()) / 2;
592
593 QColor c;
594 c.setRgbF(r, g, b, a);
595 return c;
596 }

◆ multiply()

QVector< qreal > KoMeshPatchesRenderer::multiply ( const QVector< qreal > & v1,
qreal n )
inline

Definition at line 178 of file KoMeshPatchesRenderer.h.

179 {
180 QVector<qreal> v3(4, 0);
181 for (int i = 0; i < 4; ++i) {
182 v3[i] = v1[i] * n;
183 }
184 return v3;
185 }

◆ patchImage()

QImage * KoMeshPatchesRenderer::patchImage ( )
inline

Definition at line 616 of file KoMeshPatchesRenderer.h.

616 {
617 return &m_patch;
618 }

References m_patch.

◆ secant()

QVector< qreal > KoMeshPatchesRenderer::secant ( const SvgMeshStop & stop1,
const SvgMeshStop & stop2 )
inline

Definition at line 283 of file KoMeshPatchesRenderer.h.

284 {
285 qreal distance = QLineF(stop1.point, stop2.point).length();
286
287 if (distance == 0.0) { // NaN
288 return {0.0, 0.0, 0.0, 0.0};
289 }
290
291 qreal c1[4] = {stop1.color.redF(), stop1.color.greenF(), stop1.color.blueF(), stop1.color.alphaF()};
292 qreal c2[4] = {stop2.color.redF(), stop2.color.greenF(), stop2.color.blueF(), stop2.color.alphaF()};
293
294 QVector<qreal> result(4, 0.0);
295
296 for (int i = 0; i < 4; ++i) {
297 result[i] = (c2[i] - c1[i]) / distance;
298 }
299
300 return result;
301 }
qreal distance(const QPointF &p1, const QPointF &p2)

References SvgMeshStop::color, distance(), and SvgMeshStop::point.

◆ split()

QVector< qreal > KoMeshPatchesRenderer::split ( QColor c)
inline

Definition at line 187 of file KoMeshPatchesRenderer.h.

188 {
189 return {c.redF(), c.greenF(), c.blueF(), c.alphaF()};
190 }

Member Data Documentation

◆ m_alpha

QVector<QVector<qreal> > KoMeshPatchesRenderer::m_alpha
private

Definition at line 624 of file KoMeshPatchesRenderer.h.

◆ m_patch

QImage KoMeshPatchesRenderer::m_patch
private

Definition at line 621 of file KoMeshPatchesRenderer.h.

◆ m_patchPainter

QPainter KoMeshPatchesRenderer::m_patchPainter
private

Definition at line 622 of file KoMeshPatchesRenderer.h.


The documentation for this struct was generated from the following file: