Rev 24661 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4430 | cbradney | 1 | /* |
2 | For general Scribus (>=1.3.2) copyright and licensing information please refer |
||
3 | to the COPYING file provided with the program. Following this notice may exist |
||
4 | a copyright and/or license notice that predates the release of Scribus 1.3.2 |
||
5 | for which a new license (GPL+exception) is in place. |
||
6 | */ |
||
6438 | subik | 7 | |
1809 | subik | 8 | #include "colorwheelwidget.h" |
9464 | subik | 9 | |
22936 | jghali | 10 | #if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES) |
10768 | jghali | 11 | #define _USE_MATH_DEFINES |
12 | #endif |
||
13 | #include <cmath> |
||
9464 | subik | 14 | #include <QPainter> |
1809 | subik | 15 | |
3253 | craig | 16 | #include "sccolor.h" |
7478 | jghali | 17 | #include "sccolorengine.h" |
3253 | craig | 18 | |
9464 | subik | 19 | |
10593 | fschmid | 20 | ColorWheel::ColorWheel(QWidget * parent, const char * name) : QLabel(parent) |
1809 | subik | 21 | { |
10593 | fschmid | 22 | setObjectName(name); |
8696 | subik | 23 | pointList.clear(); |
22528 | craig | 24 | currentDoc = nullptr; |
6438 | subik | 25 | currentColorSpace = colorModelRGB; |
3331 | subik | 26 | baseAngle = 0; |
27 | angleShift = 270; |
||
28 | widthH = heightH = 150; |
||
4979 | subik | 29 | // create color map |
30 | colorMap.clear(); |
||
31 | // fit the colorMap 1st value with matrix beginning |
||
32 | int mapIndex = angleShift; |
||
33 | for (int i = 0; i < 360; ++i) |
||
34 | { |
||
35 | QColor c; |
||
36 | c.setHsv(i, 255, 255); |
||
6438 | subik | 37 | ScColor col; |
38 | col.fromQColor(c); |
||
39 | colorMap[mapIndex++] = col; |
||
4979 | subik | 40 | if (mapIndex > 359) |
41 | mapIndex = 0; |
||
42 | } |
||
7895 | jghali | 43 | actualColor = colorMap[0]; |
7180 | subik | 44 | trBaseColor = tr("Base Color"); |
1809 | subik | 45 | } |
46 | |||
1812 | subik | 47 | void ColorWheel::mousePressEvent(QMouseEvent *e) |
48 | { |
||
3331 | subik | 49 | mouseReleaseEvent(e); |
1812 | subik | 50 | } |
51 | |||
52 | void ColorWheel::mouseMoveEvent(QMouseEvent *e) |
||
53 | { |
||
3331 | subik | 54 | mouseReleaseEvent(e); |
1812 | subik | 55 | } |
56 | |||
1809 | subik | 57 | void ColorWheel::mouseReleaseEvent(QMouseEvent *e) |
58 | { |
||
3331 | subik | 59 | baseAngle = valueFromPoint(e->pos()); |
60 | actualColor = colorMap[baseAngle]; |
||
7484 | jghali | 61 | actualColor = ScColorEngine::convertToModel(actualColor, currentDoc, currentColorSpace); |
1809 | subik | 62 | emit clicked(e->button(), e->pos()); |
8696 | subik | 63 | update(); |
1809 | subik | 64 | } |
65 | |||
4979 | subik | 66 | void ColorWheel::paintEvent(QPaintEvent *) |
67 | { |
||
68 | paintWheel(); |
||
69 | paintCenterSample(); |
||
6438 | subik | 70 | makeColors(); |
8696 | subik | 71 | // clear marks |
72 | for (int i = 0; i < 360; ++i) |
||
73 | drawBorderPoint(i, false, true); |
||
24661 | jghali | 74 | for (auto it = pointList.constBegin(); it != pointList.constEnd(); ++it) |
75 | drawBorderPoint(it->angle, it->base); |
||
6438 | subik | 76 | } |
77 | |||
78 | void ColorWheel::makeColors() |
||
79 | { |
||
4979 | subik | 80 | if (currentType == Monochromatic) |
81 | makeMonochromatic(); |
||
82 | if (currentType == Analogous) |
||
83 | makeAnalogous(); |
||
84 | if (currentType == Complementary) |
||
85 | makeComplementary(); |
||
86 | if (currentType == Split) |
||
87 | makeSplit(); |
||
88 | if (currentType == Triadic) |
||
89 | makeTriadic(); |
||
90 | if (currentType == Tetradic) |
||
91 | makeTetradic(); |
||
92 | } |
||
93 | |||
1812 | subik | 94 | void ColorWheel::paintCenterSample() |
95 | { |
||
3079 | fschmid | 96 | QPainter p; |
97 | p.begin(this); |
||
24661 | jghali | 98 | p.setRenderHint(QPainter::Antialiasing, true); |
3079 | fschmid | 99 | p.setPen(QPen(Qt::black, 2)); |
7478 | jghali | 100 | p.setBrush(ScColorEngine::getDisplayColor(actualColor, currentDoc )); |
4303 | subik | 101 | p.drawEllipse(widthH - 20, heightH - 20, 40, 40); |
3079 | fschmid | 102 | p.end(); |
1812 | subik | 103 | } |
104 | |||
3331 | subik | 105 | void ColorWheel::paintWheel() |
1809 | subik | 106 | { |
3353 | subik | 107 | int h, s, v; |
7478 | jghali | 108 | QColor col(ScColorEngine::getDisplayColor(actualColor, currentDoc )); |
10593 | fschmid | 109 | col.getHsv(&h, &s, &v); |
4979 | subik | 110 | int width = this->width(); |
111 | int height = this->height(); |
||
112 | QPainter p; |
||
113 | p.begin(this); |
||
114 | p.setWindow( 0, 0, width, height); |
||
24661 | jghali | 115 | p.fillRect(0, 0, width, height, palette().color(QPalette::Base)); |
4979 | subik | 116 | p.setPen(Qt::black); |
117 | p.drawRect(0, 0, width, height); |
||
3331 | subik | 118 | // Half sizes |
4979 | subik | 119 | heightH = height / 2; |
120 | widthH = width / 2; |
||
3331 | subik | 121 | for (int i = 0; i < 360; ++i) |
1809 | subik | 122 | { |
13951 | fschmid | 123 | QTransform matrix; |
3331 | subik | 124 | matrix.translate(widthH, heightH); |
24661 | jghali | 125 | matrix.rotate((float) i); |
13951 | fschmid | 126 | p.setWorldTransform(matrix); |
1809 | subik | 127 | QColor c; |
128 | c.setHsv(i, 255, 255); |
||
4979 | subik | 129 | p.setPen(QPen(c, 7)); |
130 | p.setBrush(c); |
||
131 | p.drawLine(0, 0, 130, 0); |
||
1809 | subik | 132 | } |
133 | } |
||
134 | |||
135 | QString ColorWheel::getTypeDescription(MethodType aType) |
||
136 | { |
||
137 | switch (aType) |
||
138 | { |
||
139 | case Monochromatic: return tr("Monochromatic"); |
||
140 | case Analogous: return tr("Analogous"); |
||
141 | case Complementary: return tr("Complementary"); |
||
142 | case Split: return tr("Split Complementary"); |
||
143 | case Triadic: return tr("Triadic"); |
||
144 | case Tetradic: return tr("Tetradic (Double Complementary)"); |
||
145 | } |
||
146 | return "n/a"; |
||
147 | } |
||
148 | |||
7895 | jghali | 149 | ScColor ColorWheel::colorByAngle(int angle) |
150 | { |
||
151 | while (angle > 359) |
||
152 | angle -= 359; |
||
153 | while (angle < 0) |
||
154 | angle += 359; |
||
155 | return colorSpaceColor(colorMap[angle]); |
||
156 | } |
||
157 | |||
3659 | subik | 158 | ScColor ColorWheel::sampleByAngle(int angle) |
1809 | subik | 159 | { |
3331 | subik | 160 | while (angle > 359) |
161 | angle -= 359; |
||
162 | while (angle < 0) |
||
163 | angle += 359; |
||
8696 | subik | 164 | //drawBorderPoint(angle); |
165 | PaintPoint p; |
||
166 | p.angle = angle; |
||
167 | p.base = false; |
||
168 | pointList.append(p); |
||
6438 | subik | 169 | return colorSpaceColor(colorMap[angle]); |
1809 | subik | 170 | } |
171 | |||
6438 | subik | 172 | ScColor ColorWheel::colorSpaceColor(ScColor col) |
1809 | subik | 173 | { |
6438 | subik | 174 | QColor newcol; |
175 | ScColor ret; |
||
176 | int h, s, v; |
||
7185 | subik | 177 | |
7478 | jghali | 178 | ScColorEngine::getRGBColor(col, currentDoc).getHsv(&h, &s, &v); |
6438 | subik | 179 | newcol.setHsv(h, s, v); |
180 | ret.fromQColor(newcol); |
||
7484 | jghali | 181 | ret = ScColorEngine::convertToModel(ret, currentDoc, currentColorSpace); |
6438 | subik | 182 | return ret; |
1809 | subik | 183 | } |
184 | |||
185 | void ColorWheel::baseColor() |
||
186 | { |
||
8696 | subik | 187 | //clearBorder(); |
188 | pointList.clear(); |
||
189 | //drawBorderPoint(baseAngle, true); |
||
190 | PaintPoint p; |
||
191 | p.angle = baseAngle; |
||
192 | p.base = true; |
||
193 | pointList.append(p); |
||
194 | //paintCenterSample(); |
||
1809 | subik | 195 | colorList.clear(); |
7180 | subik | 196 | colorList[trBaseColor] = colorSpaceColor(actualColor); |
1809 | subik | 197 | } |
198 | |||
199 | void ColorWheel::makeMonochromatic() |
||
200 | { |
||
201 | baseColor(); |
||
7478 | jghali | 202 | QColor col(ScColorEngine::getRGBColor(actualColor, currentDoc)); |
6438 | subik | 203 | ScColor l; |
23210 | craig | 204 | l.fromQColor(col.lighter()); |
7484 | jghali | 205 | l = ScColorEngine::convertToModel(l, currentDoc, currentColorSpace); |
3672 | subik | 206 | colorList[tr("Monochromatic Light")] = l; |
23210 | craig | 207 | l.fromQColor(col.darker()); |
7484 | jghali | 208 | l = ScColorEngine::convertToModel(l, currentDoc, currentColorSpace); |
6438 | subik | 209 | colorList[tr("Monochromatic Dark")] = l; |
4979 | subik | 210 | currentType = Monochromatic; |
1809 | subik | 211 | } |
212 | |||
213 | void ColorWheel::makeAnalogous() |
||
214 | { |
||
215 | baseColor(); |
||
3659 | subik | 216 | colorList[tr("1st. Analogous")] = sampleByAngle(baseAngle + angle); |
217 | colorList[tr("2nd. Analogous")] = sampleByAngle(baseAngle - angle); |
||
4979 | subik | 218 | currentType = Analogous; |
1809 | subik | 219 | } |
220 | |||
221 | void ColorWheel::makeComplementary() |
||
222 | { |
||
223 | baseColor(); |
||
3659 | subik | 224 | colorList[tr("Complementary")] = sampleByAngle(baseAngle + 180); |
4979 | subik | 225 | currentType = Complementary; |
1809 | subik | 226 | } |
227 | |||
228 | void ColorWheel::makeSplit() |
||
229 | { |
||
230 | baseColor(); |
||
3659 | subik | 231 | colorList[tr("1st. Split")] = sampleByAngle(baseAngle + angle); |
232 | colorList[tr("2nd. Split")] = sampleByAngle(baseAngle - angle); |
||
233 | colorList[tr("3rd. Split")] = sampleByAngle(baseAngle + 180 + angle); |
||
234 | colorList[tr("4th. Split")] = sampleByAngle(baseAngle + 180 - angle); |
||
4979 | subik | 235 | currentType = Split; |
1809 | subik | 236 | } |
237 | |||
238 | void ColorWheel::makeTriadic() |
||
239 | { |
||
240 | baseColor(); |
||
3659 | subik | 241 | colorList[tr("1st. Triadic")] = sampleByAngle(baseAngle + 120); |
242 | colorList[tr("2nd. Triadic")] = sampleByAngle(baseAngle - 120); |
||
4979 | subik | 243 | currentType = Triadic; |
1809 | subik | 244 | } |
245 | |||
246 | void ColorWheel::makeTetradic() |
||
247 | { |
||
248 | baseColor(); |
||
3659 | subik | 249 | colorList[tr("1st. Tetradic (base opposite)")] = sampleByAngle(baseAngle + 180); |
250 | colorList[tr("2nd. Tetradic (angle)")] = sampleByAngle(baseAngle + angle); |
||
251 | colorList[tr("3rd. Tetradic (angle opposite)")] = sampleByAngle(baseAngle + angle + 180); |
||
4979 | subik | 252 | currentType = Tetradic; |
1809 | subik | 253 | } |
3331 | subik | 254 | |
8696 | subik | 255 | // void ColorWheel::clearBorder() |
256 | // { |
||
257 | // for (int i = 0; i < 360; ++i) |
||
258 | // drawBorderPoint(i, false, true); |
||
259 | // } |
||
3331 | subik | 260 | |
4303 | subik | 261 | void ColorWheel::drawBorderPoint(int angle, bool base, bool clear) |
3331 | subik | 262 | { |
263 | double r = 137.0; |
||
264 | angle -= angleShift; |
||
265 | double radang = M_PI * (double)angle/180.0; |
||
266 | int x = (int)(r * cos(radang)) + widthH; |
||
267 | int y = (int)(r * sin(radang)) + heightH; |
||
268 | // draw border mark |
||
269 | QPainter p; |
||
270 | p.begin(this); |
||
24662 | jghali | 271 | p.setRenderHint(QPainter::Antialiasing, true); |
4303 | subik | 272 | if (clear) |
273 | { |
||
24661 | jghali | 274 | QColor baseColor = palette().color(QPalette::Base); |
275 | p.setPen(QPen(baseColor, 1)); |
||
276 | p.setBrush(baseColor); |
||
4303 | subik | 277 | } |
3331 | subik | 278 | else |
4303 | subik | 279 | { |
24661 | jghali | 280 | QColor textColor = palette().color(QPalette::WindowText); |
281 | p.setPen(QPen(textColor, 1)); |
||
4303 | subik | 282 | if (base) |
283 | p.setBrush(Qt::red); |
||
284 | else |
||
285 | p.setBrush(Qt::SolidPattern); |
||
286 | } |
||
24661 | jghali | 287 | p.drawEllipse(x - 4, y - 4, 8, 8); |
3331 | subik | 288 | p.end(); |
289 | } |
||
290 | |||
291 | int ColorWheel::valueFromPoint(const QPoint & p) const |
||
292 | { |
||
293 | double yy = (double)heightH - (double)p.y(); |
||
294 | double xx = (double)p.x() - (double)widthH; |
||
295 | double a = (xx || yy) ? atan2(yy, xx) : 0.0; |
||
296 | |||
297 | if ( a < M_PI/-2 ) |
||
298 | a = a + M_PI * 2; |
||
299 | |||
300 | int minv = 0, maxv = 359; |
||
301 | int r = maxv - minv; |
||
3353 | subik | 302 | int val; |
3331 | subik | 303 | |
3353 | subik | 304 | val = (int)(0.5 + minv + r * (M_PI * 3/2 -a) / (2 * M_PI)); |
3331 | subik | 305 | |
3353 | subik | 306 | return val; |
3331 | subik | 307 | } |
308 | |||
6438 | subik | 309 | bool ColorWheel::recomputeColor(ScColor col) |
3331 | subik | 310 | { |
3353 | subik | 311 | int origh, origs, origv; |
3331 | subik | 312 | ColorMap::iterator it; |
7478 | jghali | 313 | QColor c(ScColorEngine::getRGBColor(col, currentDoc)); |
314 | QColor act(ScColorEngine::getRGBColor(actualColor, currentDoc)); |
||
3331 | subik | 315 | |
10593 | fschmid | 316 | c.getHsv(&origh, &origs, &origv); |
16464 | jghali | 317 | angle = origh + angleShift; |
318 | if (angle > 359) |
||
319 | angle -= 360; |
||
320 | if (colorMap.contains(angle)) |
||
3331 | subik | 321 | { |
3353 | subik | 322 | int tmph, tmps, tmpv; |
16464 | jghali | 323 | QColor col(ScColorEngine::getRGBColor(colorMap[angle], currentDoc)); |
10593 | fschmid | 324 | col.getHsv(&tmph, &tmps, &tmpv); |
16464 | jghali | 325 | act.setHsv(tmph , origs, origv); |
326 | actualColor.fromQColor(act); |
||
327 | actualColor = ScColorEngine::convertToModel(actualColor, currentDoc, currentColorSpace); |
||
328 | baseAngle = angle; |
||
329 | return true; |
||
3331 | subik | 330 | } |
3353 | subik | 331 | return false; |
3331 | subik | 332 | } |