Rev 23210 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
#include "colorwheelwidget.h"
#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
#define _USE_MATH_DEFINES
#endif
#include <cmath>
#include <QPainter>
#include "sccolor.h"
#include "sccolorengine.h"
ColorWheel::ColorWheel(QWidget * parent, const char * name) : QLabel(parent)
{
setObjectName(name);
pointList.clear();
currentDoc = nullptr;
currentColorSpace = colorModelRGB;
baseAngle = 0;
angleShift = 270;
widthH = heightH = 150;
// create color map
colorMap.clear();
// fit the colorMap 1st value with matrix beginning
int mapIndex = angleShift;
for (int i = 0; i < 360; ++i)
{
QColor c;
c.setHsv(i, 255, 255);
ScColor col;
col.fromQColor(c);
colorMap[mapIndex++] = col;
if (mapIndex > 359)
mapIndex = 0;
}
actualColor = colorMap[0];
trBaseColor = tr("Base Color");
}
void ColorWheel::mousePressEvent(QMouseEvent *e)
{
mouseReleaseEvent(e);
}
void ColorWheel::mouseMoveEvent(QMouseEvent *e)
{
mouseReleaseEvent(e);
}
void ColorWheel::mouseReleaseEvent(QMouseEvent *e)
{
baseAngle = valueFromPoint(e->pos());
actualColor = colorMap[baseAngle];
actualColor = ScColorEngine::convertToModel(actualColor, currentDoc, currentColorSpace);
emit clicked(e->button(), e->pos());
update();
}
void ColorWheel::paintEvent(QPaintEvent *)
{
paintWheel();
paintCenterSample();
makeColors();
// clear marks
for (int i = 0; i < 360; ++i)
drawBorderPoint(i, false, true);
for (auto it = pointList.constBegin(); it != pointList.constEnd(); ++it)
drawBorderPoint(it->angle, it->base);
}
void ColorWheel::makeColors()
{
if (currentType == Monochromatic)
makeMonochromatic();
if (currentType == Analogous)
makeAnalogous();
if (currentType == Complementary)
makeComplementary();
if (currentType == Split)
makeSplit();
if (currentType == Triadic)
makeTriadic();
if (currentType == Tetradic)
makeTetradic();
}
void ColorWheel::paintCenterSample()
{
QPainter p;
p.begin(this);
p.setRenderHint(QPainter::Antialiasing, true);
p.setPen(QPen(Qt::black, 2));
p.setBrush(ScColorEngine::getDisplayColor(actualColor, currentDoc ));
p.drawEllipse(widthH - 20, heightH - 20, 40, 40);
p.end();
}
void ColorWheel::paintWheel()
{
int h, s, v;
QColor col(ScColorEngine::getDisplayColor(actualColor, currentDoc ));
col.getHsv(&h, &s, &v);
int width = this->width();
int height = this->height();
QPainter p;
p.begin(this);
p.setWindow( 0, 0, width, height);
p.fillRect(0, 0, width, height, palette().color(QPalette::Base));
p.setPen(Qt::black);
p.drawRect(0, 0, width, height);
// Half sizes
heightH = height / 2;
widthH = width / 2;
for (int i = 0; i < 360; ++i)
{
QTransform matrix;
matrix.translate(widthH, heightH);
matrix.rotate((float) i);
p.setWorldTransform(matrix);
QColor c;
c.setHsv(i, 255, 255);
p.setPen(QPen(c, 7));
p.setBrush(c);
p.drawLine(0, 0, 130, 0);
}
}
QString ColorWheel::getTypeDescription(MethodType aType)
{
switch (aType)
{
case Monochromatic: return tr("Monochromatic");
case Analogous: return tr("Analogous");
case Complementary: return tr("Complementary");
case Split: return tr("Split Complementary");
case Triadic: return tr("Triadic");
case Tetradic: return tr("Tetradic (Double Complementary)");
}
return "n/a";
}
ScColor ColorWheel::colorByAngle(int angle)
{
while (angle > 359)
angle -= 359;
while (angle < 0)
angle += 359;
return colorSpaceColor(colorMap[angle]);
}
ScColor ColorWheel::sampleByAngle(int angle)
{
while (angle > 359)
angle -= 359;
while (angle < 0)
angle += 359;
//drawBorderPoint(angle);
PaintPoint p;
p.angle = angle;
p.base = false;
pointList.append(p);
return colorSpaceColor(colorMap[angle]);
}
ScColor ColorWheel::colorSpaceColor(ScColor col)
{
QColor newcol;
ScColor ret;
int h, s, v;
ScColorEngine::getRGBColor(col, currentDoc).getHsv(&h, &s, &v);
newcol.setHsv(h, s, v);
ret.fromQColor(newcol);
ret = ScColorEngine::convertToModel(ret, currentDoc, currentColorSpace);
return ret;
}
void ColorWheel::baseColor()
{
//clearBorder();
pointList.clear();
//drawBorderPoint(baseAngle, true);
PaintPoint p;
p.angle = baseAngle;
p.base = true;
pointList.append(p);
//paintCenterSample();
colorList.clear();
colorList[trBaseColor] = colorSpaceColor(actualColor);
}
void ColorWheel::makeMonochromatic()
{
baseColor();
QColor col(ScColorEngine::getRGBColor(actualColor, currentDoc));
ScColor l;
l.fromQColor(col.lighter());
l = ScColorEngine::convertToModel(l, currentDoc, currentColorSpace);
colorList[tr("Monochromatic Light")] = l;
l.fromQColor(col.darker());
l = ScColorEngine::convertToModel(l, currentDoc, currentColorSpace);
colorList[tr("Monochromatic Dark")] = l;
currentType = Monochromatic;
}
void ColorWheel::makeAnalogous()
{
baseColor();
colorList[tr("1st. Analogous")] = sampleByAngle(baseAngle + angle);
colorList[tr("2nd. Analogous")] = sampleByAngle(baseAngle - angle);
currentType = Analogous;
}
void ColorWheel::makeComplementary()
{
baseColor();
colorList[tr("Complementary")] = sampleByAngle(baseAngle + 180);
currentType = Complementary;
}
void ColorWheel::makeSplit()
{
baseColor();
colorList[tr("1st. Split")] = sampleByAngle(baseAngle + angle);
colorList[tr("2nd. Split")] = sampleByAngle(baseAngle - angle);
colorList[tr("3rd. Split")] = sampleByAngle(baseAngle + 180 + angle);
colorList[tr("4th. Split")] = sampleByAngle(baseAngle + 180 - angle);
currentType = Split;
}
void ColorWheel::makeTriadic()
{
baseColor();
colorList[tr("1st. Triadic")] = sampleByAngle(baseAngle + 120);
colorList[tr("2nd. Triadic")] = sampleByAngle(baseAngle - 120);
currentType = Triadic;
}
void ColorWheel::makeTetradic()
{
baseColor();
colorList[tr("1st. Tetradic (base opposite)")] = sampleByAngle(baseAngle + 180);
colorList[tr("2nd. Tetradic (angle)")] = sampleByAngle(baseAngle + angle);
colorList[tr("3rd. Tetradic (angle opposite)")] = sampleByAngle(baseAngle + angle + 180);
currentType = Tetradic;
}
// void ColorWheel::clearBorder()
// {
// for (int i = 0; i < 360; ++i)
// drawBorderPoint(i, false, true);
// }
void ColorWheel::drawBorderPoint(int angle, bool base, bool clear)
{
double r = 137.0;
angle -= angleShift;
double radang = M_PI * (double)angle/180.0;
int x = (int)(r * cos(radang)) + widthH;
int y = (int)(r * sin(radang)) + heightH;
// draw border mark
QPainter p;
p.begin(this);
if (clear)
{
QColor baseColor = palette().color(QPalette::Base);
p.setPen(QPen(baseColor, 1));
p.setBrush(baseColor);
}
else
{
QColor textColor = palette().color(QPalette::WindowText);
p.setPen(QPen(textColor, 1));
if (base)
p.setBrush(Qt::red);
else
p.setBrush(Qt::SolidPattern);
}
p.drawEllipse(x - 4, y - 4, 8, 8);
p.end();
}
int ColorWheel::valueFromPoint(const QPoint & p) const
{
double yy = (double)heightH - (double)p.y();
double xx = (double)p.x() - (double)widthH;
double a = (xx || yy) ? atan2(yy, xx) : 0.0;
if ( a < M_PI/-2 )
a = a + M_PI * 2;
int minv = 0, maxv = 359;
int r = maxv - minv;
int val;
val = (int)(0.5 + minv + r * (M_PI * 3/2 -a) / (2 * M_PI));
return val;
}
bool ColorWheel::recomputeColor(ScColor col)
{
int origh, origs, origv;
ColorMap::iterator it;
QColor c(ScColorEngine::getRGBColor(col, currentDoc));
QColor act(ScColorEngine::getRGBColor(actualColor, currentDoc));
c.getHsv(&origh, &origs, &origv);
angle = origh + angleShift;
if (angle > 359)
angle -= 360;
if (colorMap.contains(angle))
{
int tmph, tmps, tmpv;
QColor col(ScColorEngine::getRGBColor(colorMap[angle], currentDoc));
col.getHsv(&tmph, &tmps, &tmpv);
act.setHsv(tmph , origs, origv);
actualColor.fromQColor(act);
actualColor = ScColorEngine::convertToModel(actualColor, currentDoc, currentColorSpace);
baseAngle = angle;
return true;
}
return false;
}