29#include <tqtextstream.h>
33#include <kogradientmanager.h>
38#include "kis_gradient.h"
40#define PREVIEW_WIDTH 64
41#define PREVIEW_HEIGHT 64
43KisGradientSegment::RGBColorInterpolationStrategy *KisGradientSegment::RGBColorInterpolationStrategy::m_instance = 0;
44KisGradientSegment::HSVCWColorInterpolationStrategy *KisGradientSegment::HSVCWColorInterpolationStrategy::m_instance = 0;
45KisGradientSegment::HSVCCWColorInterpolationStrategy *KisGradientSegment::HSVCCWColorInterpolationStrategy::m_instance = 0;
47KisGradientSegment::LinearInterpolationStrategy *KisGradientSegment::LinearInterpolationStrategy::m_instance = 0;
48KisGradientSegment::CurvedInterpolationStrategy *KisGradientSegment::CurvedInterpolationStrategy::m_instance = 0;
49KisGradientSegment::SineInterpolationStrategy *KisGradientSegment::SineInterpolationStrategy::m_instance = 0;
50KisGradientSegment::SphereIncreasingInterpolationStrategy *KisGradientSegment::SphereIncreasingInterpolationStrategy::m_instance = 0;
51KisGradientSegment::SphereDecreasingInterpolationStrategy *KisGradientSegment::SphereDecreasingInterpolationStrategy::m_instance = 0;
53KisGradient::KisGradient(
const TQString& file) : super(file)
57KisGradient::~KisGradient()
59 for (uint i = 0; i < m_segments.count(); i++) {
65bool KisGradient::load()
70bool KisGradient::save()
75TQImage KisGradient::img()
80bool KisGradient::init()
82 KoGradientManager gradLoader;
83 KoGradient* grad = gradLoader.loadGradient(filename());
90 if( grad->colorStops.count() > 1 ) {
92 for(colstop = grad->colorStops.first(); colstop; colstop = grad->colorStops.next()) {
93 KoColorStop *colstopNext = grad->colorStops.next();
96 KoColor leftRgb((
int)(colstop->color1 * 255 + 0.5), (
int)(colstop->color2 * 255 + 0.5), (
int)(colstop->color3 * 255 + 0.5));
97 KoColor rightRgb((
int)(colstopNext->color1 * 255 + 0.5), (
int)(colstopNext->color2 * 255 + 0.5), (
int)(colstopNext->color3 * 255 + 0.5));
99 double midp = colstop->midpoint;
100 midp = colstop->offset + ((colstopNext->offset - colstop->offset) * midp);
102 Color leftColor(leftRgb.color(), colstop->opacity);
103 Color rightColor(rightRgb.color(), colstopNext->opacity);
105 KisGradientSegment *segment =
new KisGradientSegment(colstop->interpolation, colstop->colorType, colstop->offset, midp, colstopNext->offset, leftColor, rightColor);
106 TQ_CHECK_PTR(segment);
108 if ( !segment->isValid() ) {
113 m_segments.push_back(segment);
114 grad->colorStops.prev();
117 grad->colorStops.prev();
125 if (!m_segments.isEmpty()) {
126 m_img = generatePreview(PREVIEW_WIDTH, PREVIEW_HEIGHT);
135void KisGradient::setImage(
const TQImage& img)
143KisGradientSegment *KisGradient::segmentAt(
double t)
const
145 Q_ASSERT(t >= 0 || t <= 1);
146 Q_ASSERT(!m_segments.empty());
148 for(TQValueVector<KisGradientSegment *>::const_iterator it = m_segments.begin(); it!= m_segments.end(); ++it)
150 if (t > (*it)->startOffset() - DBL_EPSILON && t < (*it)->endOffset() + DBL_EPSILON) {
158void KisGradient::colorAt(
double t, TQColor *color, TQ_UINT8 *opacity)
const
160 const KisGradientSegment *segment = segmentAt(t);
161 Q_ASSERT(segment != 0);
164 Color col = segment->colorAt(t);
165 *color = col.color();
166 *opacity =
static_cast<TQ_UINT8
>(col.alpha() * OPACITY_OPAQUE + 0.5);
170TQImage KisGradient::generatePreview(
int width,
int height)
const
172 TQImage img(width, height, 32);
174 for (
int y = 0; y < img.height(); y++) {
175 for (
int x = 0; x < img.width(); x++) {
177 int backgroundRed = 128 + 63 * ((x / 4 + y / 4) % 2);
178 int backgroundGreen = backgroundRed;
179 int backgroundBlue = backgroundRed;
183 double t =
static_cast<double>(x) / (img.width() - 1);
185 colorAt(t, &color, &opacity);
187 double alpha =
static_cast<double>(opacity) / OPACITY_OPAQUE;
189 int red =
static_cast<int>((1 - alpha) * backgroundRed + alpha * color.red() + 0.5);
190 int green =
static_cast<int>((1 - alpha) * backgroundGreen + alpha * color.green() + 0.5);
191 int blue =
static_cast<int>((1 - alpha) * backgroundBlue + alpha * color.blue() + 0.5);
193 img.setPixel(x, y, tqRgb(red, green, blue));
200KisGradientSegment::KisGradientSegment(
int interpolationType,
int colorInterpolationType,
double startOffset,
double middleOffset,
double endOffset,
const Color& startColor,
const Color& endColor)
204 switch (interpolationType) {
206 m_interpolator = LinearInterpolationStrategy::instance();
209 m_interpolator = CurvedInterpolationStrategy::instance();
212 m_interpolator = SineInterpolationStrategy::instance();
214 case INTERP_SPHERE_INCREASING:
215 m_interpolator = SphereIncreasingInterpolationStrategy::instance();
217 case INTERP_SPHERE_DECREASING:
218 m_interpolator = SphereDecreasingInterpolationStrategy::instance();
222 m_colorInterpolator = 0;
224 switch (colorInterpolationType) {
225 case COLOR_INTERP_RGB:
226 m_colorInterpolator = RGBColorInterpolationStrategy::instance();
228 case COLOR_INTERP_HSV_CCW:
229 m_colorInterpolator = HSVCCWColorInterpolationStrategy::instance();
231 case COLOR_INTERP_HSV_CW:
232 m_colorInterpolator = HSVCWColorInterpolationStrategy::instance();
236 if (startOffset < DBL_EPSILON) {
240 if (startOffset > 1 - DBL_EPSILON) {
244 m_startOffset = startOffset;
247 if (middleOffset < m_startOffset + DBL_EPSILON) {
248 m_middleOffset = m_startOffset;
251 if (middleOffset > 1 - DBL_EPSILON) {
255 m_middleOffset = middleOffset;
258 if (endOffset < m_middleOffset + DBL_EPSILON) {
259 m_endOffset = m_middleOffset;
262 if (endOffset > 1 - DBL_EPSILON) {
266 m_endOffset = endOffset;
269 m_length = m_endOffset - m_startOffset;
271 if (m_length < DBL_EPSILON) {
275 m_middleT = (m_middleOffset - m_startOffset) / m_length;
278 m_startColor = startColor;
279 m_endColor = endColor;
282const Color& KisGradientSegment::startColor()
const
287const Color& KisGradientSegment::endColor()
const
292double KisGradientSegment::startOffset()
const
294 return m_startOffset;
297double KisGradientSegment::middleOffset()
const
299 return m_middleOffset;
302double KisGradientSegment::endOffset()
const
307void KisGradientSegment::setStartOffset(
double t)
310 m_length = m_endOffset - m_startOffset;
312 if (m_length < DBL_EPSILON) {
316 m_middleT = (m_middleOffset - m_startOffset) / m_length;
319void KisGradientSegment::setMiddleOffset(
double t)
323 if (m_length < DBL_EPSILON) {
327 m_middleT = (m_middleOffset - m_startOffset) / m_length;
331void KisGradientSegment::setEndOffset(
double t)
334 m_length = m_endOffset - m_startOffset;
336 if (m_length < DBL_EPSILON) {
340 m_middleT = (m_middleOffset - m_startOffset) / m_length;
344int KisGradientSegment::interpolation()
const
346 return m_interpolator->type();
349void KisGradientSegment::setInterpolation(
int interpolationType)
351 switch (interpolationType) {
353 m_interpolator = LinearInterpolationStrategy::instance();
356 m_interpolator = CurvedInterpolationStrategy::instance();
359 m_interpolator = SineInterpolationStrategy::instance();
361 case INTERP_SPHERE_INCREASING:
362 m_interpolator = SphereIncreasingInterpolationStrategy::instance();
364 case INTERP_SPHERE_DECREASING:
365 m_interpolator = SphereDecreasingInterpolationStrategy::instance();
370int KisGradientSegment::colorInterpolation()
const
372 return m_colorInterpolator->type();
375void KisGradientSegment::setColorInterpolation(
int colorInterpolationType)
377 switch (colorInterpolationType) {
378 case COLOR_INTERP_RGB:
379 m_colorInterpolator = RGBColorInterpolationStrategy::instance();
381 case COLOR_INTERP_HSV_CCW:
382 m_colorInterpolator = HSVCCWColorInterpolationStrategy::instance();
384 case COLOR_INTERP_HSV_CW:
385 m_colorInterpolator = HSVCWColorInterpolationStrategy::instance();
390Color KisGradientSegment::colorAt(
double t)
const
392 Q_ASSERT(t > m_startOffset - DBL_EPSILON && t < m_endOffset + DBL_EPSILON);
396 if (m_length < DBL_EPSILON) {
400 segmentT = (t - m_startOffset) / m_length;
403 double colorT = m_interpolator->valueAt(segmentT, m_middleT);
405 Color color = m_colorInterpolator->colorAt(colorT, m_startColor, m_endColor);
410bool KisGradientSegment::isValid()
const
412 if (m_interpolator == 0 || m_colorInterpolator ==0)
417KisGradientSegment::RGBColorInterpolationStrategy *KisGradientSegment::RGBColorInterpolationStrategy::instance()
419 if (m_instance == 0) {
420 m_instance =
new RGBColorInterpolationStrategy();
421 TQ_CHECK_PTR(m_instance);
427Color KisGradientSegment::RGBColorInterpolationStrategy::colorAt(
double t, Color start, Color end)
const
429 int startRed = start.color().red();
430 int startGreen = start.color().green();
431 int startBlue = start.color().blue();
432 double startAlpha = start.alpha();
433 int red =
static_cast<int>(startRed + t * (end.color().red() - startRed) + 0.5);
434 int green =
static_cast<int>(startGreen + t * (end.color().green() - startGreen) + 0.5);
435 int blue =
static_cast<int>(startBlue + t * (end.color().blue() - startBlue) + 0.5);
436 double alpha = startAlpha + t * (end.alpha() - startAlpha);
438 return Color(TQColor(red, green, blue), alpha);
441KisGradientSegment::HSVCWColorInterpolationStrategy *KisGradientSegment::HSVCWColorInterpolationStrategy::instance()
443 if (m_instance == 0) {
444 m_instance =
new HSVCWColorInterpolationStrategy();
445 TQ_CHECK_PTR(m_instance);
451Color KisGradientSegment::HSVCWColorInterpolationStrategy::colorAt(
double t, Color start, Color end)
const
453 KoColor sc = KoColor(start.color());
454 KoColor ec = KoColor(end.color());
456 int s =
static_cast<int>(sc.S() + t * (ec.S() - sc.S()) + 0.5);
457 int v =
static_cast<int>(sc.V() + t * (ec.V() - sc.V()) + 0.5);
460 if (ec.H() < sc.H()) {
461 h =
static_cast<int>(ec.H() + (1 - t) * (sc.H() - ec.H()) + 0.5);
464 h =
static_cast<int>(ec.H() + (1 - t) * (360 - ec.H() + sc.H()) + 0.5);
471 double alpha = start.alpha() + t * (end.alpha() - start.alpha());
473 return Color(KoColor(h, s, v, KoColor::csHSV).color(), alpha);
476KisGradientSegment::HSVCCWColorInterpolationStrategy *KisGradientSegment::HSVCCWColorInterpolationStrategy::instance()
478 if (m_instance == 0) {
479 m_instance =
new HSVCCWColorInterpolationStrategy();
480 TQ_CHECK_PTR(m_instance);
486Color KisGradientSegment::HSVCCWColorInterpolationStrategy::colorAt(
double t, Color start, Color end)
const
488 KoColor sc = KoColor(start.color());
489 KoColor se = KoColor(end.color());
491 int s =
static_cast<int>(sc.S() + t * (se.S() - sc.S()) + 0.5);
492 int v =
static_cast<int>(sc.V() + t * (se.V() - sc.V()) + 0.5);
495 if (sc.H() < se.H()) {
496 h =
static_cast<int>(sc.H() + t * (se.H() - sc.H()) + 0.5);
499 h =
static_cast<int>(sc.H() + t * (360 - sc.H() + se.H()) + 0.5);
506 double alpha = start.alpha() + t * (end.alpha() - start.alpha());
508 return Color(KoColor(h, s, v, KoColor::csHSV).color(), alpha);
511KisGradientSegment::LinearInterpolationStrategy *KisGradientSegment::LinearInterpolationStrategy::instance()
513 if (m_instance == 0) {
514 m_instance =
new LinearInterpolationStrategy();
515 TQ_CHECK_PTR(m_instance);
521double KisGradientSegment::LinearInterpolationStrategy::calcValueAt(
double t,
double middle)
523 Q_ASSERT(t > -DBL_EPSILON && t < 1 + DBL_EPSILON);
524 Q_ASSERT(middle > -DBL_EPSILON && middle < 1 + DBL_EPSILON);
529 if (middle < DBL_EPSILON) {
533 value = (t / middle) * 0.5;
537 if (middle > 1 - DBL_EPSILON) {
541 value = ((t - middle) / (1 - middle)) * 0.5 + 0.5;
548double KisGradientSegment::LinearInterpolationStrategy::valueAt(
double t,
double middle)
const
550 return calcValueAt(t, middle);
553KisGradientSegment::CurvedInterpolationStrategy::CurvedInterpolationStrategy()
555 m_logHalf = log(0.5);
558KisGradientSegment::CurvedInterpolationStrategy *KisGradientSegment::CurvedInterpolationStrategy::instance()
560 if (m_instance == 0) {
561 m_instance =
new CurvedInterpolationStrategy();
562 TQ_CHECK_PTR(m_instance);
568double KisGradientSegment::CurvedInterpolationStrategy::valueAt(
double t,
double middle)
const
570 Q_ASSERT(t > -DBL_EPSILON && t < 1 + DBL_EPSILON);
571 Q_ASSERT(middle > -DBL_EPSILON && middle < 1 + DBL_EPSILON);
575 if (middle < DBL_EPSILON) {
576 middle = DBL_EPSILON;
579 value = pow(t, m_logHalf / log(middle));
584KisGradientSegment::SineInterpolationStrategy *KisGradientSegment::SineInterpolationStrategy::instance()
586 if (m_instance == 0) {
587 m_instance =
new SineInterpolationStrategy();
588 TQ_CHECK_PTR(m_instance);
594double KisGradientSegment::SineInterpolationStrategy::valueAt(
double t,
double middle)
const
596 double lt = LinearInterpolationStrategy::calcValueAt(t, middle);
597 double value = (sin(-M_PI_2 + M_PI * lt) + 1.0) / 2.0;
602KisGradientSegment::SphereIncreasingInterpolationStrategy *KisGradientSegment::SphereIncreasingInterpolationStrategy::instance()
604 if (m_instance == 0) {
605 m_instance =
new SphereIncreasingInterpolationStrategy();
606 TQ_CHECK_PTR(m_instance);
612double KisGradientSegment::SphereIncreasingInterpolationStrategy::valueAt(
double t,
double middle)
const
614 double lt = LinearInterpolationStrategy::calcValueAt(t, middle) - 1;
615 double value = sqrt(1 - lt * lt);
620KisGradientSegment::SphereDecreasingInterpolationStrategy *KisGradientSegment::SphereDecreasingInterpolationStrategy::instance()
622 if (m_instance == 0) {
623 m_instance =
new SphereDecreasingInterpolationStrategy();
624 TQ_CHECK_PTR(m_instance);
630double KisGradientSegment::SphereDecreasingInterpolationStrategy::valueAt(
double t,
double middle)
const
632 double lt = LinearInterpolationStrategy::calcValueAt(t, middle);
633 double value = 1 - sqrt(1 - lt * lt);
638#include "kis_gradient.moc"