44 LinearGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
46 double valueAt(
double x,
double y)
const override;
49 double m_normalisedVectorX;
50 double m_normalisedVectorY;
51 double m_vectorLength;
54LinearGradientStrategy::LinearGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
57 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
58 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
60 m_vectorLength = sqrt((dx * dx) + (dy * dy));
62 if (m_vectorLength < DBL_EPSILON) {
63 m_normalisedVectorX = 0;
64 m_normalisedVectorY = 0;
66 m_normalisedVectorX = dx / m_vectorLength;
67 m_normalisedVectorY = dy / m_vectorLength;
71double LinearGradientStrategy::valueAt(
double x,
double y)
const
73 double vx =
x - m_gradientVectorStart.x();
74 double vy =
y - m_gradientVectorStart.y();
77 double t = vx * m_normalisedVectorX + vy * m_normalisedVectorY;
79 if (m_vectorLength < DBL_EPSILON) {
90class BiLinearGradientStrategy :
public LinearGradientStrategy
94 BiLinearGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
96 double valueAt(
double x,
double y)
const override;
99BiLinearGradientStrategy::BiLinearGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
100 : LinearGradientStrategy(gradientVectorStart, gradientVectorEnd)
104double BiLinearGradientStrategy::valueAt(
double x,
double y)
const
106 double t = LinearGradientStrategy::valueAt(x, y);
109 if (t < -DBL_EPSILON) {
121 RadialGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
123 double valueAt(
double x,
double y)
const override;
129RadialGradientStrategy::RadialGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
132 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
133 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
135 m_radius = sqrt((dx * dx) + (dy * dy));
138double RadialGradientStrategy::valueAt(
double x,
double y)
const
140 double dx =
x - m_gradientVectorStart.x();
141 double dy =
y - m_gradientVectorStart.y();
143 double distance = sqrt((dx * dx) + (dy * dy));
147 if (m_radius < DBL_EPSILON) {
161 SquareGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
163 double valueAt(
double x,
double y)
const override;
166 double m_normalisedVectorX;
167 double m_normalisedVectorY;
168 double m_vectorLength;
171SquareGradientStrategy::SquareGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
174 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
175 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
177 m_vectorLength = sqrt((dx * dx) + (dy * dy));
179 if (m_vectorLength < DBL_EPSILON) {
180 m_normalisedVectorX = 0;
181 m_normalisedVectorY = 0;
183 m_normalisedVectorX = dx / m_vectorLength;
184 m_normalisedVectorY = dy / m_vectorLength;
188double SquareGradientStrategy::valueAt(
double x,
double y)
const
190 double px =
x - m_gradientVectorStart.x();
191 double py =
y - m_gradientVectorStart.y();
193 double distance1 = 0;
194 double distance2 = 0;
198 if (m_vectorLength > DBL_EPSILON) {
205 distance1 = -m_normalisedVectorY * px + m_normalisedVectorX * py;
206 distance1 = fabs(distance1);
209 distance2 = -m_normalisedVectorY * -py + m_normalisedVectorX * px;
210 distance2 = fabs(distance2);
212 t = qMax(distance1, distance2) / m_vectorLength;
225 ConicalGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
227 double valueAt(
double x,
double y)
const override;
230 double m_vectorAngle;
233ConicalGradientStrategy::ConicalGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
236 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
237 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
243double ConicalGradientStrategy::valueAt(
double x,
double y)
const
245 double px =
x - m_gradientVectorStart.x();
246 double py =
y - m_gradientVectorStart.y();
250 angle -= m_vectorAngle;
256 double t = angle / (2 *
M_PI);
265 ConicalSymetricGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
267 double valueAt(
double x,
double y)
const override;
270 double m_vectorAngle;
273ConicalSymetricGradientStrategy::ConicalSymetricGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
276 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
277 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
283double ConicalSymetricGradientStrategy::valueAt(
double x,
double y)
const
285 double px =
x - m_gradientVectorStart.x();
286 double py =
y - m_gradientVectorStart.y();
290 angle -= m_vectorAngle;
310 SpiralGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
312 double valueAt(
double x,
double y)
const override;
315 double m_vectorAngle;
319SpiralGradientStrategy::SpiralGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
322 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
323 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
327 m_radius = sqrt((dx * dx) + (dy * dy));
330double SpiralGradientStrategy::valueAt(
double x,
double y)
const
332 double dx =
x - m_gradientVectorStart.x();
333 double dy =
y - m_gradientVectorStart.y();
335 double distance = sqrt((dx * dx) + (dy * dy));
339 angle -= m_vectorAngle;
341 if (m_radius < DBL_EPSILON) {
351 t += angle / (2 *
M_PI);
360 ReverseSpiralGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd);
362 double valueAt(
double x,
double y)
const override;
365 double m_vectorAngle;
369ReverseSpiralGradientStrategy::ReverseSpiralGradientStrategy(
const QPointF& gradientVectorStart,
const QPointF& gradientVectorEnd)
372 double dx = gradientVectorEnd.x() - gradientVectorStart.x();
373 double dy = gradientVectorEnd.y() - gradientVectorStart.y();
377 m_radius = sqrt((dx * dx) + (dy * dy));
380double ReverseSpiralGradientStrategy::valueAt(
double x,
double y)
const
382 double dx =
x - m_gradientVectorStart.x();
383 double dy =
y - m_gradientVectorStart.y();
385 double distance = sqrt((dx * dx) + (dy * dy));
389 angle -= m_vectorAngle;
391 if (m_radius < DBL_EPSILON) {
402 t += 1 - (angle / (2 *
M_PI));
414 double valueAt(
double x,
double y)
const override;
426 , m_ditherSteps(ditherSteps)
427 , m_shapeStrategy(shapeStrategy)
431double DitheredGradientStrategy::valueAt(
double x,
double y)
const
433 double value = m_shapeStrategy->valueAt(x, y);
434 double ditherFactor = 0.0;
451 value *= m_ditherSteps - 1;
455 value /= m_ditherSteps - 1;
460class GradientRepeatStrategy
463 GradientRepeatStrategy() {}
464 virtual ~GradientRepeatStrategy() {}
466 virtual double valueAt(
double t)
const = 0;
470class GradientRepeatNoneStrategy :
public GradientRepeatStrategy
473 static GradientRepeatNoneStrategy *
instance();
475 double valueAt(
double t)
const override;
478 GradientRepeatNoneStrategy() {}
480 static GradientRepeatNoneStrategy *m_instance;
483GradientRepeatNoneStrategy *GradientRepeatNoneStrategy::m_instance = 0;
485GradientRepeatNoneStrategy *GradientRepeatNoneStrategy::instance()
487 if (m_instance == 0) {
488 m_instance =
new GradientRepeatNoneStrategy();
489 Q_CHECK_PTR(m_instance);
496double GradientRepeatNoneStrategy::valueAt(
double t)
const
500 if (t < DBL_EPSILON) {
502 }
else if (t > 1 - DBL_EPSILON) {
510class GradientRepeatForwardsStrategy :
public GradientRepeatStrategy
513 static GradientRepeatForwardsStrategy *
instance();
515 double valueAt(
double t)
const override;
518 GradientRepeatForwardsStrategy() {}
520 static GradientRepeatForwardsStrategy *m_instance;
523GradientRepeatForwardsStrategy *GradientRepeatForwardsStrategy::m_instance = 0;
525GradientRepeatForwardsStrategy *GradientRepeatForwardsStrategy::instance()
527 if (m_instance == 0) {
528 m_instance =
new GradientRepeatForwardsStrategy();
529 Q_CHECK_PTR(m_instance);
536double GradientRepeatForwardsStrategy::valueAt(
double t)
const
538 int i =
static_cast<int>(t);
540 if (t < DBL_EPSILON) {
544 double value = t - i;
550class GradientRepeatAlternateStrategy :
public GradientRepeatStrategy
553 static GradientRepeatAlternateStrategy *
instance();
555 double valueAt(
double t)
const override;
558 GradientRepeatAlternateStrategy() {}
560 static GradientRepeatAlternateStrategy *m_instance;
563GradientRepeatAlternateStrategy *GradientRepeatAlternateStrategy::m_instance = 0;
565GradientRepeatAlternateStrategy *GradientRepeatAlternateStrategy::instance()
567 if (m_instance == 0) {
568 m_instance =
new GradientRepeatAlternateStrategy();
569 Q_CHECK_PTR(m_instance);
576double GradientRepeatAlternateStrategy::valueAt(
double t)
const
582 int i =
static_cast<int>(t);
584 double value = t - i;
593class GradientRepeatModuloDivisiveContinuousHalfStrategy :
public GradientRepeatStrategy
596 static GradientRepeatModuloDivisiveContinuousHalfStrategy *
instance();
598 double valueAt(
double t)
const override;
601 GradientRepeatModuloDivisiveContinuousHalfStrategy() {}
603 static GradientRepeatModuloDivisiveContinuousHalfStrategy *m_instance;
606GradientRepeatModuloDivisiveContinuousHalfStrategy *GradientRepeatModuloDivisiveContinuousHalfStrategy::m_instance = 0;
608GradientRepeatModuloDivisiveContinuousHalfStrategy *GradientRepeatModuloDivisiveContinuousHalfStrategy::instance()
610 if (m_instance == 0) {
611 m_instance =
new GradientRepeatModuloDivisiveContinuousHalfStrategy();
612 Q_CHECK_PTR(m_instance);
619double GradientRepeatModuloDivisiveContinuousHalfStrategy::valueAt(
double t)
const
625 int i =
static_cast<int>(t*2);
626 int ti =
static_cast<int>(t);
628 double value = t - ti;
637class RepeatForwardsPaintPolicy
642 void setup(
const QPointF& gradientVectorStart,
643 const QPointF& gradientVectorEnd,
645 const GradientRepeatStrategy *repeatStrategy,
646 qreal antiAliasThreshold,
647 bool reverseGradient,
650 const quint8 *
colorAt(qreal x, qreal y)
const;
654 qreal m_antiAliasThresholdNormalized {0};
655 qreal m_antiAliasThresholdNormalizedRev {0};
656 qreal m_antiAliasThresholdNormalizedDbl {0};
658 const GradientRepeatStrategy *m_repeatStrategy {0};
659 bool m_reverseGradient {
false};
661 const quint8 *m_extremeColors[2];
670void RepeatForwardsPaintPolicy::setup(
const QPointF& gradientVectorStart,
671 const QPointF& gradientVectorEnd,
673 const GradientRepeatStrategy *repeatStrategy,
674 qreal antiAliasThreshold,
675 bool reverseGradient,
678 qreal dx = gradientVectorEnd.x() - gradientVectorStart.x();
679 qreal dy = gradientVectorEnd.y() - gradientVectorStart.y();
680 qreal distanceInPixels = sqrt(dx * dx + dy * dy);
683 m_antiAliasThresholdNormalized = antiAliasThreshold / distanceInPixels;
684 m_antiAliasThresholdNormalizedRev = 1. - m_antiAliasThresholdNormalized;
685 m_antiAliasThresholdNormalizedDbl = 2. * m_antiAliasThresholdNormalized;
687 m_shapeStrategy = shapeStrategy;
688 m_repeatStrategy = repeatStrategy;
690 m_reverseGradient = reverseGradient;
692 m_cachedGradient = cachedGradient;
693 m_extremeColors[0] = m_cachedGradient->
cachedAt(1.);
694 m_extremeColors[1] = m_cachedGradient->
cachedAt(0.);
696 m_colorSpace = m_cachedGradient->
colorSpace();
701const quint8 *RepeatForwardsPaintPolicy::colorAt(qreal x, qreal y)
const
703 qreal t = m_shapeStrategy->valueAt(x, y);
708 if (t <= m_antiAliasThresholdNormalized &&
712 if (m_reverseGradient) {
715 return m_cachedGradient->
cachedAt(t);
718 t = m_repeatStrategy->valueAt(t);
720 if (m_reverseGradient) {
726 if (t <= m_antiAliasThresholdNormalized || t >= m_antiAliasThresholdNormalizedRev) {
728 if (t <= m_antiAliasThresholdNormalized) {
729 s = .5 + t / m_antiAliasThresholdNormalizedDbl;
731 s = (t - m_antiAliasThresholdNormalizedRev) / m_antiAliasThresholdNormalizedDbl;
734 qint16 colorWeights[2];
735 colorWeights[0] = std::lround((1.0 - s) *
qint16_MAX);
736 colorWeights[1] =
qint16_MAX - colorWeights[0];
740 return m_resultColor.data();
743 return m_cachedGradient->
cachedAt(t);
746class ConicalGradientPaintPolicy
749 void setup(
const QPointF& gradientVectorStart,
750 const QPointF& gradientVectorEnd,
752 const GradientRepeatStrategy *repeatStrategy,
753 qreal antiAliasThreshold,
754 bool reverseGradient,
757 const quint8 *
colorAt(qreal x, qreal y)
const;
760 QPointF m_gradientVectorStart;
762 const GradientRepeatStrategy *m_repeatStrategy;
763 qreal m_singularityThreshold;
764 qreal m_antiAliasThreshold;
765 bool m_reverseGradient;
767 const quint8 *m_extremeColors[2];
772void ConicalGradientPaintPolicy::setup(
const QPointF& gradientVectorStart,
773 const QPointF& gradientVectorEnd,
775 const GradientRepeatStrategy *repeatStrategy,
776 qreal antiAliasThreshold,
777 bool reverseGradient,
780 Q_UNUSED(gradientVectorEnd);
782 m_gradientVectorStart = gradientVectorStart;
784 m_shapeStrategy = shapeStrategy;
785 m_repeatStrategy = repeatStrategy;
787 m_singularityThreshold = 8.;
788 m_antiAliasThreshold = antiAliasThreshold;
790 m_reverseGradient = reverseGradient;
792 m_cachedGradient = cachedGradient;
793 m_extremeColors[0] = m_cachedGradient->
cachedAt(1.);
794 m_extremeColors[1] = m_cachedGradient->
cachedAt(0.);
796 m_colorSpace = m_cachedGradient->
colorSpace();
801const quint8 *ConicalGradientPaintPolicy::colorAt(qreal x, qreal y)
const
804 qreal dx =
x - m_gradientVectorStart.x();
805 qreal dy =
y - m_gradientVectorStart.y();
806 qreal distanceInPixels = sqrt(dx * dx + dy * dy);
808 qreal perimeter = 2. *
M_PI * distanceInPixels;
813 qreal antiAliasThresholdNormalized;
814 if (distanceInPixels < m_singularityThreshold){
815 antiAliasThresholdNormalized = distanceInPixels * m_antiAliasThreshold / m_singularityThreshold;
817 antiAliasThresholdNormalized = m_antiAliasThreshold;
819 antiAliasThresholdNormalized = antiAliasThresholdNormalized / perimeter;
820 qreal antiAliasThresholdNormalizedRev = 1. - antiAliasThresholdNormalized;
821 qreal antiAliasThresholdNormalizedDbl = 2. * antiAliasThresholdNormalized;
823 qreal t = m_shapeStrategy->valueAt(x, y);
824 t = m_repeatStrategy->valueAt(t);
826 if (m_reverseGradient) {
832 if (t <= antiAliasThresholdNormalized || t >= antiAliasThresholdNormalizedRev) {
834 if (t <= antiAliasThresholdNormalized) {
835 s = .5 + t / antiAliasThresholdNormalizedDbl;
837 s = (t - antiAliasThresholdNormalizedRev) / antiAliasThresholdNormalizedDbl;
840 qint16 colorWeights[2];
841 colorWeights[0] = std::lround((1.0 - s) *
qint16_MAX);
842 colorWeights[1] =
qint16_MAX - colorWeights[0];
846 return m_resultColor.data();
849 return m_cachedGradient->
cachedAt(t);
852class SpyralGradientRepeatNonePaintPolicy
855 SpyralGradientRepeatNonePaintPolicy(
bool isReverseSpiral =
false);
857 void setup(
const QPointF& gradientVectorStart,
858 const QPointF& gradientVectorEnd,
860 const GradientRepeatStrategy *repeatStrategy,
861 qreal antiAliasThreshold,
862 bool reverseGradient,
865 const quint8 *
colorAt(qreal x, qreal y)
const;
868 QPointF m_gradientVectorStart;
869 qreal m_distanceInPixels {0};
870 qreal m_singularityThreshold {0};
873 const GradientRepeatStrategy *m_repeatStrategy {0};
874 qreal m_antiAliasThreshold {0};
875 bool m_reverseGradient {
false};
877 mutable const quint8 *m_extremeColors[2];
880 bool m_isReverseSpiral {
false};
883SpyralGradientRepeatNonePaintPolicy::SpyralGradientRepeatNonePaintPolicy(
bool isReverseSpiral)
884 : m_isReverseSpiral(isReverseSpiral)
888void SpyralGradientRepeatNonePaintPolicy::setup(
const QPointF& gradientVectorStart,
889 const QPointF& gradientVectorEnd,
891 const GradientRepeatStrategy *repeatStrategy,
892 qreal antiAliasThreshold,
893 bool reverseGradient,
896 m_gradientVectorStart = gradientVectorStart;
898 qreal dx = gradientVectorEnd.x() - gradientVectorStart.x();
899 qreal dy = gradientVectorEnd.y() - gradientVectorStart.y();
900 m_distanceInPixels = sqrt(dx * dx + dy * dy);
901 m_singularityThreshold = m_distanceInPixels / 32.;
904 m_shapeStrategy = shapeStrategy;
905 m_repeatStrategy = repeatStrategy;
907 m_antiAliasThreshold = antiAliasThreshold;
909 m_reverseGradient = reverseGradient;
911 m_cachedGradient = cachedGradient;
913 m_colorSpace = m_cachedGradient->
colorSpace();
918const quint8 *SpyralGradientRepeatNonePaintPolicy::colorAt(qreal x, qreal y)
const
921 qreal dx =
x - m_gradientVectorStart.x();
922 qreal dy =
y - m_gradientVectorStart.y();
923 qreal distanceInPixels = sqrt(dx * dx + dy * dy);
925 qreal perimeter = 2. *
M_PI * distanceInPixels;
930 qreal antiAliasThresholdNormalized;
931 if (distanceInPixels < m_singularityThreshold) {
932 antiAliasThresholdNormalized = distanceInPixels * m_antiAliasThreshold / m_singularityThreshold;
934 antiAliasThresholdNormalized = m_antiAliasThreshold;
936 antiAliasThresholdNormalized = antiAliasThresholdNormalized / perimeter;
937 qreal antiAliasThresholdNormalizedRev = 1. - antiAliasThresholdNormalized;
938 qreal antiAliasThresholdNormalizedDbl = 2. * antiAliasThresholdNormalized;
940 qreal t = m_shapeStrategy->valueAt(x, y);
941 t = m_repeatStrategy->valueAt(t);
943 if (m_reverseGradient) {
954 angle /= (2. *
M_PI);
956 angle = m_repeatStrategy->valueAt(angle);
960 if (distanceInPixels < m_distanceInPixels && (angle <= antiAliasThresholdNormalized || angle >= antiAliasThresholdNormalizedRev)) {
962 if (angle <= antiAliasThresholdNormalized) {
963 s = .5 + angle / antiAliasThresholdNormalizedDbl;
965 s = (angle - antiAliasThresholdNormalizedRev) / antiAliasThresholdNormalizedDbl;
968 if (m_reverseGradient) {
969 distanceInPixels = m_distanceInPixels - distanceInPixels;
970 m_extremeColors[0] = m_cachedGradient->
cachedAt(0.);
972 m_extremeColors[0] = m_cachedGradient->
cachedAt(1.);
975 if (m_isReverseSpiral) {
976 m_extremeColors[1] = m_extremeColors[0];
977 m_extremeColors[0] = (m_cachedGradient->
cachedAt(distanceInPixels / m_distanceInPixels));
979 m_extremeColors[1] = (m_cachedGradient->
cachedAt(distanceInPixels / m_distanceInPixels));
982 qint16 colorWeights[2];
983 colorWeights[0] = std::lround((1.0 - s) *
qint16_MAX);
984 colorWeights[1] =
qint16_MAX - colorWeights[0];
988 return m_resultColor.data();
991 return m_cachedGradient->
cachedAt(t);
994class NoAntialiasPaintPolicy
997 void setup(
const QPointF& gradientVectorStart,
998 const QPointF& gradientVectorEnd,
1000 const GradientRepeatStrategy *repeatStrategy,
1001 qreal antiAliasThreshold,
1002 bool reverseGradient,
1005 const quint8 *
colorAt(qreal x, qreal y)
const;
1009 const GradientRepeatStrategy *m_repeatStrategy {0};
1010 bool m_reverseGradient {
false};
1014void NoAntialiasPaintPolicy::setup(
const QPointF& gradientVectorStart,
1015 const QPointF& gradientVectorEnd,
1017 const GradientRepeatStrategy *repeatStrategy,
1018 qreal antiAliasThreshold,
1019 bool reverseGradient,
1022 Q_UNUSED(gradientVectorStart);
1023 Q_UNUSED(gradientVectorEnd);
1024 Q_UNUSED(antiAliasThreshold);
1025 m_shapeStrategy = shapeStrategy;
1026 m_repeatStrategy = repeatStrategy;
1027 m_reverseGradient = reverseGradient;
1028 m_cachedGradient = cachedGradient;
1031const quint8 *NoAntialiasPaintPolicy::colorAt(qreal x, qreal y)
const
1033 qreal t = m_shapeStrategy->valueAt(x, y);
1034 t = m_repeatStrategy->valueAt(t);
1036 if (m_reverseGradient) {
1040 return m_cachedGradient->
cachedAt(t);
1052 const QRect &_processRect)
1053 : precalculatedShapeStrategy(_precalculatedShapeStrategy),
1054 processRect(_processRect) {}
1092 const qreal exponent = 2.0;
1097 boundingRect.height() >= 3);
1110 if (!
m_d->processRegions.isEmpty())
return;
1115 if (!
selection()->outlineCacheValid()) {
1129 Q_FOREACH (
const QPainterPath &subpath, splitPaths) {
1130 QRect boundingRect = subpath.boundingRect().toAlignedRect();
1132 if (boundingRect.width() < 3 || boundingRect.height() < 3) {
1138 m_d->processRegions << r;
1143 const QPointF& gradientVectorEnd,
1145 double antiAliasThreshold,
1146 bool reverseGradient,
1159 QRect(startx, starty, width, height),
1165 const QPointF& gradientVectorEnd,
1167 double antiAliasThreshold,
1168 bool reverseGradient,
1169 const QRect &applyRect,
1178 if (antiAliasThreshold > DBL_EPSILON) {
1183 RepeatForwardsPaintPolicy paintPolicy(
m_d->shape);
1195 ConicalGradientPaintPolicy paintPolicy;
1222 NoAntialiasPaintPolicy paintPolicy;
1236 const QPointF& gradientVectorEnd,
1238 double antiAliasThreshold,
1239 bool reverseGradient,
1242 const QRect &applyRect,
1247 QRect requestedRect = applyRect;
1256 switch (
m_d->shape) {
1258 Private::ProcessRegion r(
toQShared(
new LinearGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1260 m_d->processRegions.clear();
1261 m_d->processRegions << r;
1265 Private::ProcessRegion r(
toQShared(
new BiLinearGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1267 m_d->processRegions.clear();
1268 m_d->processRegions << r;
1272 Private::ProcessRegion r(
toQShared(
new RadialGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1274 m_d->processRegions.clear();
1275 m_d->processRegions << r;
1279 Private::ProcessRegion r(
toQShared(
new SquareGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1281 m_d->processRegions.clear();
1282 m_d->processRegions << r;
1286 Private::ProcessRegion r(
toQShared(
new ConicalGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1288 m_d->processRegions.clear();
1289 m_d->processRegions << r;
1293 Private::ProcessRegion r(
toQShared(
new ConicalSymetricGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1295 m_d->processRegions.clear();
1296 m_d->processRegions << r;
1300 Private::ProcessRegion r(
toQShared(
new SpiralGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1302 m_d->processRegions.clear();
1303 m_d->processRegions << r;
1307 Private::ProcessRegion r(
toQShared(
new ReverseSpiralGradientStrategy(gradientVectorStart, gradientVectorEnd)),
1309 m_d->processRegions.clear();
1310 m_d->processRegions << r;
1321 for (Private::ProcessRegion& region :
m_d->processRegions) {
1322 region.precalculatedShapeStrategy =
toQShared(
new DitheredGradientStrategy(dither, ditherSteps, region.precalculatedShapeStrategy));
1326 GradientRepeatStrategy *repeatStrategy = 0;
1330 repeatStrategy = GradientRepeatNoneStrategy::instance();
1333 repeatStrategy = GradientRepeatForwardsStrategy::instance();
1337 else {repeatStrategy = GradientRepeatAlternateStrategy::instance();}
1340 Q_ASSERT(repeatStrategy != 0);
1355 const quint32 mixPixelSize = mixCs->
pixelSize();
1363 Q_FOREACH (
const Private::ProcessRegion &r,
m_d->processRegions) {
1364 QRect processRect = r.processRect;
1371 paintPolicy.setup(gradientVectorStart,
1380 const quint8 *
const pixel {paintPolicy.colorAt(it.
x(), it.
y())};
1381 memcpy(it.
rawData(), pixel, mixPixelSize);
1390 for (
int y = processRect.y(); y <= processRect.bottom(); y += rows) {
1393 for (
int x = processRect.x(); x <= processRect.right(); x += columns) {
1399 const qint32 srcRowStride = srcIt->
rowStride(x, y);
1400 const qint32 dstRowStride = dstIt->
rowStride(x, y);
1402 quint8 *dstPtr = dstIt->
rawData();
1404 op->
dither(srcPtr, srcRowStride, dstPtr, dstRowStride, x, y, columns, rows);
1409 bitBlt(requestedRect.topLeft(), dev, requestedRect);
float value(const T *src, size_t ch)
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
qreal distance(const QPointF &p1, const QPointF &p2)
PythonPluginManager * instance
virtual quint8 * rawData()=0
virtual const quint8 * rawDataConst() const =0
virtual void dither(const quint8 *src, quint8 *dst, int x, int y) const =0
KisPaintDeviceSP createCompositionSourceDevice() const
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
KisRandomAccessorSP createRandomAccessorNG()
KoUpdater * progressUpdater
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
KoAbstractGradientSP gradient
virtual qint32 rowStride(qint32 x, qint32 y) const =0
virtual qint32 numContiguousRows(qint32 y) const =0
virtual void moveTo(qint32 x, qint32 y)=0
virtual qint32 numContiguousColumns(qint32 x) const =0
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE int x() const
ALWAYS_INLINE int y() const
const quint8 * cachedAt(qreal t) const
gets the color data at position 0 <= t <= 1
const KoColorSpace * colorSpace() const
virtual quint32 pixelSize() const =0
virtual const KisDitherOp * ditherOp(const QString &depth, DitherType type) const
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
KoMixColorsOp * mixColorsOp
virtual const KoColorProfile * profile() const =0
virtual void mixColors(const quint8 *const *colors, const qint16 *weights, int nColors, quint8 *dst, int weightSum=255) const =0
#define KIS_ASSERT_RECOVER_RETURN(cond)
#define KIS_ASSERT_RECOVER_NOOP(cond)
T kisGrowRect(const T &rect, U offset)
KisGradientShapeStrategy * createPolygonShapeStrategy(const QPainterPath &path, const QRect &boundingRect)
QSharedPointer< T > toQShared(T *ptr)
float dither_factor_bayer_4_normalized(int x, int y)
float dither_factor_bayer_2_normalized(int x, int y)
float dither_factor_bayer_8_normalized(int x, int y)
KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x)
atan2 replacement
KRITAFLAKE_EXPORT QColor colorAt(qreal position, const QGradientStops &stops)
Calculates color at given position from given gradient stops.
qreal KRITAIMAGE_EXPORT maxDimensionPortion(const QRectF &bounds, qreal portion, qreal minValue)
QList< QPainterPath > splitDisjointPaths(const QPainterPath &path)
QSharedPointer< KisGradientShapeStrategy > precalculatedShapeStrategy
ProcessRegion(QSharedPointer< KisGradientShapeStrategy > _precalculatedShapeStrategy, const QRect &_processRect)
@ GradientShapeReverseSpiral
@ GradientShapeConicalSymetric
@ GradientRepeatAlternate
void setGradientShape(enumGradientShape shape)
static bool isBayerDither(enumDither dither)
const QScopedPointer< Private > m_d
bool paintGradient(const QPointF &gradientVectorStart, const QPointF &gradientVectorEnd, enumGradientRepeat repeat, double antiAliasThreshold, bool reverseGradient, qint32 startx, qint32 starty, qint32 width, qint32 height, enumDither dither=DitherNone, int ditherSteps=defaultDitherSteps)
~KisGradientPainter() override
QVector< ProcessRegion > processRegions
void recalculateOutlineCache()
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.
QPainterPath outlineCache() const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()