58 #include <QtCore/QEvent>
59 #include <QtCore/QMap>
60 #include <QtCore/QVarLengthArray>
61 #include <QtGui/QConicalGradient>
62 #include <QtGui/QFrame>
63 #include <QtGui/QImage>
64 #include <QtGui/QKeyEvent>
65 #include <QtGui/QLayout>
66 #include <QtGui/QMouseEvent>
67 #include <QtGui/QPainter>
68 #include <QtGui/QPainterPath>
69 #include <QtGui/QPixmap>
70 #include <QtGui/QResizeEvent>
71 #include <QtGui/QToolTip>
72 #include <QtGui/QVBoxLayout>
98 const double PI = 3.14159265358979323846264338327950288419717;
109 DoubleColor(
double red,
double green,
double blue) :
r(red),
g(green),
b(blue) {}
123 (double) c.blue())),
point(p) {}
141 :
QWidget(parent), bg(sizeHint(),
QImage::Format_RGB32), selMode(Idle)
144 setFocusPolicy(Qt::StrongFocus);
146 mustGenerateBackground =
true;
171 penWidth = (int) floor(outerRadius / 50.0);
172 ellipseSize = (int) floor(outerRadius / 12.5);
177 pa =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))),
178 cy - (sin(a) * (outerRadius - (outerRadius / 5.0))));
179 pb =
QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))),
180 cy - (sin(b) * (outerRadius - (outerRadius / 5.0))));
181 pc =
QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))),
182 cy - (sin(c) * (outerRadius - (outerRadius / 5.0))));
183 pd =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))),
184 cy - (sin(a) * (outerRadius - (outerRadius / 10.0))));
187 selectorPos = pointFromColor(curColor);
196 return QSize(100, 100);
214 void QtColorTriangle::genBackground()
217 double innerRadius = outerRadius - outerRadius / 5;
221 bg.
fill(qRgba(0,0,0,0));
223 p.setRenderHint(QPainter::Antialiasing);
227 for (
double i = 0; i <= 1.0; i += 0.1) {
228 #if QT_VERSION < 0x040100
229 color.
setHsv(
int(i * 360.0), 255, 255);
231 color.setHsv(
int(360.0 - (i * 360.0)), 255, 255);
233 gradient.setColorAt(i, color);
236 QRectF innerRadiusRect(bg.
rect().center().x() - innerRadius, bg.
rect().center().y() - innerRadius,
237 innerRadius * 2 + 1, innerRadius * 2 + 1);
238 QRectF outerRadiusRect(bg.
rect().center().x() - outerRadius, bg.
rect().center().y() - outerRadius,
239 outerRadius * 2 + 1, outerRadius * 2 + 1);
242 path.addEllipse(outerRadiusRect);
246 p.fillRect(bg.
rect(), gradient);
249 double penThickness = bg.
width() / 400.0;
250 for (
int f = 0; f <= 5760; f += 20) {
251 int value = int((0.5 + cos(((f - 1800) / 5760.0) *
TWOPI) / 2) * 255.0);
253 color.setHsv(
int((f / 5760.0) * 360.0), 128 + (255 - value)/2, 255 - (255 - value)/4);
254 p.setPen(
QPen(color, penThickness));
255 p.drawArc(innerRadiusRect, 1440 - f, 20);
257 color.setHsv(
int((f / 5760.0) * 360.0), 128 + value/2, 255 - value/4);
258 p.setPen(
QPen(color, penThickness));
259 p.drawArc(outerRadiusRect, 2880 - 1440 - f, 20);
273 if ((e->buttons() & Qt::LeftButton) == 0)
277 bool newColor =
false;
279 if (selMode == SelectingHue) {
289 double am = a -
PI/2;
290 if (am < 0) am +=
TWOPI;
292 curHue = 360 - (int) (((am) * 360.0) /
TWOPI);
294 curColor.
getHsv(&h, &s, &v);
304 pa =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))),
305 cy - (sin(a) * (outerRadius - (outerRadius / 5.0))));
306 pb =
QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))),
307 cy - (sin(b) * (outerRadius - (outerRadius / 5.0))));
308 pc =
QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))),
309 cy - (sin(c) * (outerRadius - (outerRadius / 5.0))));
310 pd =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))),
311 cy - (sin(a) * (outerRadius - (outerRadius / 10.0))));
313 selectorPos = pointFromColor(curColor);
326 selectorPos = movePointToTriangle(depos.x(), depos.y(), aa, bb, cc);
327 QColor col = colorFromPoint(selectorPos);
328 if (col != curColor) {
332 col.getHsv(&h, &s, &v);
355 if (e->button() != Qt::LeftButton)
360 bool newColor =
false;
364 if (rad > (outerRadius - (outerRadius / 5))) {
365 selMode = SelectingHue;
373 double am = a -
PI/2;
374 if (am < 0) am +=
TWOPI;
376 curHue = 360 - (int) ((am * 360.0) /
TWOPI);
378 curColor.
getHsv(&h, &s, &v);
388 pa =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))),
389 cy - (sin(a) * (outerRadius - (outerRadius / 5.0))));
390 pb =
QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))),
391 cy - (sin(b) * (outerRadius - (outerRadius / 5.0))));
392 pc =
QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))),
393 cy - (sin(c) * (outerRadius - (outerRadius / 5.0))));
394 pd =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))),
395 cy - (sin(a) * (outerRadius - (outerRadius / 10.0))));
397 selectorPos = pointFromColor(curColor);
400 selMode = SelectingSatValue;
413 selectorPos = movePointToTriangle(depos.x(), depos.y(), aa, bb, cc);
414 QColor col = colorFromPoint(selectorPos);
415 if (col != curColor) {
416 int tempalpha = curColor.
alpha();
436 if (e->button() == Qt::LeftButton)
448 if (curHue < 0) curHue += 360;
450 curColor.
getHsv(&h, &s, &v);
456 case Qt::Key_Right: {
458 if (curHue > 359) curHue -= 360;
460 curColor.
getHsv(&h, &s, &v);
468 curColor.
getHsv(&h, &s, &v);
470 if (e->modifiers() & Qt::ShiftModifier) {
483 curColor.
getHsv(&h, &s, &v);
485 if (e->modifiers() & Qt::ShiftModifier) {
510 penWidth = (int) floor(outerRadius / 50.0);
511 ellipseSize = (int) floor(outerRadius / 12.5);
516 pa =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))),
517 cy - (sin(a) * (outerRadius - (outerRadius / 5.0))));
518 pb =
QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))),
519 cy - (sin(b) * (outerRadius - (outerRadius / 5.0))));
520 pc =
QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))),
521 cy - (sin(c) * (outerRadius - (outerRadius / 5.0))));
522 pd =
QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))),
523 cy - (sin(a) * (outerRadius - (outerRadius / 10.0))));
526 selectorPos = pointFromColor(curColor);
528 mustGenerateBackground =
true;
543 if (mustGenerateBackground) {
545 mustGenerateBackground =
false;
554 curColor.
getHsv(&h, &s, &v);
558 hueColor.
setHsv(curHue, 255, 255);
569 QColor halfAlpha(0, 0, 0, 128);
576 hueColor.
getRgb(&ri, &gi, &bi);
577 if ((ri * 30) + (gi * 59) + (bi * 11) > 12800)
582 (int) (pd.
y() - ellipseSize / 2.0),
583 ellipseSize, ellipseSize);
585 curColor.
getRgb(&ri, &gi, &bi);
589 if ((ri * 30) + (gi * 59) + (bi * 11) > 12800)
596 selectorPos.
y() - ellipseSize / 2.0,
597 ellipseSize + 0.5, ellipseSize + 0.5));
652 bool lefty = p1p2xdist < 0;
673 double rdelta, gdelta, bdelta;
685 y1 = (int) floor(p1->
point.
y());
686 y2 = (int) floor(p3->
point.
y());
690 xdelta = p1p3ydist == 0.0 ? 0.0 : p1p3xdist / p1p3ydist;
691 rdelta = p1p3ydist == 0.0 ? 0.0 : (dest.
r - r) / p1p3ydist;
692 gdelta = p1p3ydist == 0.0 ? 0.0 : (dest.
g - g) / p1p3ydist;
693 bdelta = p1p3ydist == 0.0 ? 0.0 : (dest.
b - b) / p1p3ydist;
697 for (y = y1; y < y2; ++y) {
720 y1 = (int) floor(p1->
point.
y());
721 y2 = (int) floor(p2->
point.
y());
725 xdelta = p1p2ydist == 0.0 ? 0.0 : p1p2xdist / p1p2ydist;
726 rdelta = p1p2ydist == 0.0 ? 0.0 : (dest.
r - r) / p1p2ydist;
727 gdelta = p1p2ydist == 0.0 ? 0.0 : (dest.
g - g) / p1p2ydist;
728 bdelta = p1p2ydist == 0.0 ? 0.0 : (dest.
b - b) / p1p2ydist;
731 for (y = y1; y < y2; ++y) {
754 y1 = (int) floor(p2->
point.
y());
755 y2 = (int) floor(p3->
point.
y());
759 xdelta = p2p3ydist == 0.0 ? 0.0 : p2p3xdist / p2p3ydist;
760 rdelta = p2p3ydist == 0.0 ? 0.0 : (dest.
r - r) / p2p3ydist;
761 gdelta = p2p3ydist == 0.0 ? 0.0 : (dest.
g - g) / p2p3ydist;
762 bdelta = p2p3ydist == 0.0 ? 0.0 : (dest.
b - b) / p2p3ydist;
765 for (y = y1; y < y2; ++y) {
782 const int p3yfloor = int(floor(p3->
point.
y()));
783 for (
int y =
int(floor(p1->
point.
y())); y < p3yfloor; ++y) {
784 double lx = leftX[y];
785 double rx = rightX[y];
787 int lxi = (int) floor(lx);
788 int rxi = (int) floor(rx);
793 double xdist = rx - lx;
798 double rdelta = (rc.
r - r) / xdist;
799 double gdelta = (rc.
g - g) / xdist;
800 double bdelta = (rc.
b - b) / xdist;
802 QRgb *scanline =
reinterpret_cast<QRgb *
>(buf->
scanLine(y));
806 for (
int i = lxi; i < rxi; ++i) {
807 *scanline++ = qRgb((
int) r, (
int) g, (
int) b);
828 curColor.
getHsv(&h, &s, &v);
834 a = (((360 - curHue) *
TWOPI) / 360.0);
846 double innerRadius = outerRadius - (outerRadius / 5.0);
847 double pointerRadius = outerRadius - (outerRadius / 10.0);
849 pa =
QPointF(cx + (cos(a) * innerRadius), cy - (sin(a) * innerRadius));
850 pb =
QPointF(cx + (cos(b) * innerRadius), cy - (sin(b) * innerRadius));
851 pc =
QPointF(cx + (cos(c) * innerRadius), cy - (sin(c) * innerRadius));
852 pd =
QPointF(cx + (cos(a) * pointerRadius), cy - (sin(a) * pointerRadius));
854 selectorPos = pointFromColor(curColor);
874 double QtColorTriangle::radiusAt(
const QPointF &pos,
const QRect &rect)
const
876 double mousexdist = pos.
x() - (double) rect.
center().x();
877 double mouseydist = pos.
y() - (double) rect.
center().y();
878 return sqrt(mousexdist * mousexdist + mouseydist * mouseydist);
888 double QtColorTriangle::angleAt(
const QPointF &pos,
const QRect &rect)
const
890 double mousexdist = pos.
x() - (double) rect.
center().x();
891 double mouseydist = pos.
y() - (double) rect.
center().y();
892 double mouserad = sqrt(mousexdist * mousexdist + mouseydist * mouseydist);
896 double angle = acos(mousexdist / mouserad);
898 angle =
TWOPI - angle;
916 inline double vlen(
double x,
double y)
925 inline double vprod(
double x1,
double y1,
double x2,
double y2)
927 return x1 * x2 + y1 * y2;
942 return p >= a1 && p < a2;
963 double ax,
double ay,
double bx,
double by)
967 if (floor(ax) > floor(bx)) {
968 if (floor(ay) < floor(by)) {
970 if (floor(x) < floor(px) || floor(y) < floor(py))
972 }
else if (floor(ay) > floor(by)) {
974 if (floor(x) > floor(px) || floor(y) < floor(py))
978 if (y < ay) result =
true;
980 }
else if (floor(ax) < floor(bx)) {
981 if (floor(ay) < floor(by)) {
983 if (floor(x) < floor(px) || floor(y) > floor(py))
985 }
else if (floor(ay) > floor(by)) {
987 if (floor(x) > floor(px) || floor(y) > floor(py))
996 if (floor(ay) < floor(by)) {
997 if (x < ax) result =
true;
998 }
else if (floor(ay) > floor(by)) {
999 if (x > ax) result =
true;
1001 if (!(x == ax && y == ay))
1017 double bx,
double by)
1025 if (y <= ay && x >= ax)
1030 if (y >= by && x <= bx)
1036 if (floor(ay) == floor(by)) {
1047 if (y >= ay && x >= ax)
1052 if (y <= by && x <= bx)
1062 if (y <= ay && x <= ax)
1067 if (y >= by && x >= bx)
1073 if (floor(ay) == floor(by)) {
1081 if (y >= ay && x <= ax)
1086 if (y <= by && x >= bx)
1112 QPointF QtColorTriangle::movePointToTriangle(
double x,
double y,
const Vertex &a,
1118 double v1xA = x - a.
point.
x();
1119 double v1yA = y - a.
point.
y();
1122 double vpA =
vprod(v1xA, v1yA, v2xA, v2yA);
1123 double cosA = vpA / (
vlen(v1xA, v1yA) *
vlen(v2xA, v2yA));
1124 double alphaA = acos(cosA);
1128 double v1xB = x - b.
point.
x();
1129 double v1yB = y - b.
point.
y();
1132 double vpB =
vprod(v1xB, v1yB, v2xB, v2yB);
1133 double cosB = vpB / (
vlen(v1xB, v1yB) *
vlen(v2xB, v2yB));
1134 double alphaB = acos(cosB);
1138 double v1xC = x - c.
point.
x();
1139 double v1yC = y - c.
point.
y();
1142 double vpC =
vprod(v1xC, v1yC, v2xC, v2yC);
1143 double cosC = vpC / (
vlen(v1xC, v1yC) *
vlen(v2xC, v2yC));
1144 double alphaC = acos(cosC);
1231 QPointF QtColorTriangle::pointFromColor(
const QColor &col)
const
1234 if (col == Qt::black)
1236 else if (col == Qt::white)
1240 double ab_deltax = pb.
x() - pa.
x();
1241 double ab_deltay = pb.
y() - pa.
y();
1242 double bc_deltax = pc.
x() - pb.
x();
1243 double bc_deltay = pc.
y() - pb.
y();
1244 double ac_deltax = pc.
x() - pa.
x();
1245 double ac_deltay = pc.
y() - pa.
y();
1249 col.
getHsv(&hue, &sat, &val);
1253 double p1 = pa.
x() + (ab_deltax * (double) (255 - val)) / 255.0;
1254 double q1 = pa.
y() + (ab_deltay * (double) (255 - val)) / 255.0;
1255 double p2 = pb.
x() + (bc_deltax * (double) val) / 255.0;
1256 double q2 = pb.
y() + (bc_deltay * (double) val) / 255.0;
1260 double p3 = pa.
x() + (ac_deltax * (double) (255 - sat)) / 255.0;
1261 double q3 = pa.
y() + (ac_deltay * (double) (255 - sat)) / 255.0;
1269 double a = (q2 - q1) / (p2 - p1);
1270 double c = (q4 - q3) / (p4 - p3);
1271 double b = q1 - a * p1;
1272 double d = q3 - c * p3;
1274 x = (d - b) / (a - c);
1279 y = q3 + (x - p3) * (q4 - q3) / (p4 - p3);
1292 QColor QtColorTriangle::colorFromPoint(
const QPointF &p)
const
1305 QPointF pa(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))),
1306 cy - (sin(a) * (outerRadius - (outerRadius / 5.0))));
1307 QPointF pb(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))),
1308 cy - (sin(b) * (outerRadius - (outerRadius / 5.0))));
1309 QPointF pc(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))),
1310 cy - (sin(c) * (outerRadius - (outerRadius / 5.0))));
1313 double angle = a -
PI/2.0;
1314 if (angle < 0) angle +=
TWOPI;
1315 double hue = (360.0 * angle) /
TWOPI;
1320 color.
setHsv(360 - (
int) floor(hue), 255, 255);
1325 Vertex bb(Qt::black, pb);
1326 Vertex cc(Qt::white, pc);
1350 bool lefty = p1p2xdist < 0;
1355 bool firstshorty = (p.
y() >= p1->
point.
y() && p.
y() < p2->
point.
y());
1364 if (floor(p1p2ydist) != 0.0) {
1365 leftx += (p1p2xdist * (p.
y() - p1->
point.
y())) / p1p2ydist;
1371 if (floor(p2p3ydist) != 0.0) {
1372 leftx += (p2p3xdist * (p.
y() - p2->
point.
y())) / p2p3ydist;
1379 rightx += (p1p3xdist * (p.
y() - p1->
point.
y())) / p1p3ydist;
1382 leftx += (p1p3xdist * (p.
y() - p1->
point.
y())) / p1p3ydist;
1386 if (floor(p1p2ydist) != 0.0) {
1387 rightx += (p1p2xdist * (p.
y() - p1->
point.
y())) / p1p2ydist;
1393 if (floor(p2p3ydist) != 0.0) {
1394 rightx += (p2p3xdist * (p.
y() - p2->
point.
y())) / p2p3ydist;
1403 double rshort = 0, gshort = 0, bshort = 0;
1404 double rlong = 0, glong = 0, blong = 0;
1406 if (floor(p1p2ydist) != 0.0) {
1410 rshort += p1->
color.
r * (p2->
point.
y() - p.
y()) / p1p2ydist;
1411 gshort += p1->
color.
g * (p2->
point.
y() - p.
y()) / p1p2ydist;
1412 bshort += p1->
color.
b * (p2->
point.
y() - p.
y()) / p1p2ydist;
1437 if (floor(p2p3ydist) != 0.0) {
1441 rshort += p2->
color.
r * (p3->
point.
y() - p.
y()) / p2p3ydist;
1442 gshort += p2->
color.
g * (p3->
point.
y() - p.
y()) / p2p3ydist;
1443 bshort += p2->
color.
b * (p3->
point.
y() - p.
y()) / p2p3ydist;
1481 double rl, gl, bl, rr, gr, br;
1483 rl = rshort; gl = gshort; bl = bshort;
1484 rr = rlong; gr = glong; br = blong;
1486 rl = rlong; gl = glong; bl = blong;
1487 rr = rshort; gr = gshort; br = bshort;
1494 double xdist = rightx - leftx;
1495 double saxdist = p.
x() - leftx;
1496 double saxdist2 = xdist - saxdist;
1502 r = (saxdist2 * rl / xdist) + (saxdist * rr / xdist);
1503 g = (saxdist2 * gl / xdist) + (saxdist * gr / xdist);
1504 b = (saxdist2 * bl / xdist) + (saxdist * br / xdist);
1519 int ri = (int) floor(r);
1520 int gi = (int) floor(g);
1521 int bi = (int) floor(b);
1523 else if (ri > 255) ri = 255;
1525 else if (gi > 255) gi = 255;
1527 else if (bi > 255) bi = 255;
1530 return QColor(ri, gi, bi);
addEllipse(const QRectF &boundingRectangle)
Vertex(const QColor &c, const QPointF &p)
void keyPressEvent(QKeyEvent *e)
setRenderHint(RenderHint hint, bool on=true)
static int pointInLine(double x, double y, double ax, double ay, double bx, double by)
void setColor(const QColor &col)
void resizeEvent(QResizeEvent *)
void internalSetNewColor(const QColor &color)
double vlen(double x, double y)
fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
DoubleColor(double red, double green, double blue)
void colorChanged(const QColor &col)
setClipRegion(const QRegion ®ion, Qt::ClipOperation operation=Qt::ReplaceClip)
static void swap(Vertex **a, Vertex **b)
drawLine(const QLineF &line)
copy(const QRect &rectangle=QRect()
getHsv(int *h, int *s, int *v, int *a=0)
void paintEvent(QPaintEvent *)
void mouseReleaseEvent(QMouseEvent *)
void mousePressEvent(QMouseEvent *)
drawEllipse(const QRectF &rectangle)
drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
static bool pointAbovePoint(double x, double y, double px, double py, double ax, double ay, double bx, double by)
DoubleColor(const DoubleColor &c)
QtColorTriangle(QWidget *parent=0)
double vprod(double x1, double y1, double x2, double y2)
getRgb(int *r, int *g, int *b, int *a=0)
setHsv(int h, int s, int v, int a=255)
int heightForWidth(int w) const
void mouseMoveEvent(QMouseEvent *)
bool angleBetweenAngles(double p, double a1, double a2)
void drawTrigon(QImage *p, const QPointF &a, const QPointF &b, const QPointF &c, const QColor &color)
Vertex(const DoubleColor &c, const QPointF &p)