1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036 |
- /* GCSx
- ** COLOR.CPP
- **
- ** Color conversion and selection widget
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- // Color RGB<->HSL
- void color::RGBtoHSL() { start_func
- float r = R / (float)max;
- float g = G / (float)max;
- float b = B / (float)max;
-
- float minRGB = min(r, min(g, b));
- float maxRGB = std::max(r, std::max(g, b));
-
- L = (minRGB + maxRGB) / 2.0;
-
- if (minRGB == maxRGB) {
- S = H = 0.0;
- }
- else {
- if (L < 0.5) S = (maxRGB - minRGB) / (maxRGB + minRGB);
- else S = (maxRGB - minRGB) / (2.0 - maxRGB - minRGB);
-
- if (r == maxRGB) H = (g - b) / (maxRGB - minRGB);
- else if (g == maxRGB) H = 2.0 + (b - r) / (maxRGB - minRGB);
- else H = 4.0 + (r - g) / (maxRGB - minRGB);
-
- if (H < 0) H += 6.0;
- H /= 6.0;
- }
-
- Hi = (int)(H * 255.0 + 0.5);
- Si = (int)(S * 255.0 + 0.5);
- Li = (int)(L * 255.0 + 0.5);
- }
- void color::HSLtoRGB() { start_func
- float r, g, b;
-
- H = Hi / 255.0;
- S = Si / 255.0;
- L = Li / 255.0;
- if (S == 0.0) {
- r = g = b = L;
- }
- else {
- float t1, t2;
- float tR, tG, tB;
-
- if (L < 0.5) t2 = L * (1.0 + S);
- else t2 = L + S - L * S;
-
- t1 = 2.0 * L - t2;
-
- tR = H + 1.0 / 3.0;
- tG = H;
- tB = H - 1.0 / 3.0;
-
- if (tR > 1.0) tR -= 1.0;
- if (tB < 0) tB += 1.0;
-
- if (6.0 * tR < 1) r = t1 + (t2 - t1) * 6.0 * tR;
- else if (2.0 * tR < 1) r = t2;
- else if (3.0 * tR < 2) r = t1 + (t2 - t1) * (2.0 / 3.0 - tR) * 6.0;
- else r = t1;
-
- if (6.0 * tG < 1) g = t1 + (t2 - t1) * 6.0 * tG;
- else if (2.0 * tG < 1) g = t2;
- else if (3.0 * tG < 2) g = t1 + (t2 - t1) * (2.0 / 3.0 - tG) * 6.0;
- else g = t1;
-
- if (6.0 * tB < 1) b = t1 + (t2 - t1) * 6.0 * tB;
- else if (2.0 * tB < 1) b = t2;
- else if (3.0 * tB < 2) b = t1 + (t2 - t1) * (2.0 / 3.0 - tB) * 6.0;
- else b = t1;
- }
-
- R = (int)(r * max + 0.5);
- G = (int)(g * max + 0.5);
- B = (int)(b * max + 0.5);
- }
- // RGBHSL selection widget
- WRGBSelect::WRGBSelect(int wId, int w, int h, color* wSetting, int rgbBitDepth) : Widget(wId, blankString, wSetting) { start_func
- assert(wSetting);
- assert(w > 0);
- assert(h > 0);
-
- // Load immediately so we have a max
- currentColor = *((color*)wSetting);
-
- maxComponent = (1 << rgbBitDepth) - 1;
-
- innerWidth = w;
- innerHeight = h;
- zPanelX = innerWidth + WRGBSELECT_BORDER * 2 + WRGBSELECT_GUTTER;
-
- aX = AXIS_H;
- aY = AXIS_S;
- aZ = AXIS_L;
-
- fX = 0;
- fY = 1;
- fZ = 1;
- dependXYtoZ = 1;
-
- dragMode = WRGBSELECT_DRAG_NONE;
-
- // Attempt to allocate video surfaces
- xyPanel = NULL;
- zPanel = NULL;
-
- xyPanel = createSurface(w, h);
- zPanel = createSurface(WRGBSELECT_ZWIDTH, h);
- resize(w + WRGBSELECT_BORDER * 4 + WRGBSELECT_GUTTER + WRGBSELECT_ZWIDTH,
- h + WRGBSELECT_BORDER * 2);
- }
- WRGBSelect::~WRGBSelect() { start_func
- if (xyPanel) SDL_FreeSurface(xyPanel);
- if (zPanel) SDL_FreeSurface(zPanel);
- }
- void WRGBSelect::setMode(int axisX, int axisY, int axisZ, int flipX, int flipY, int flipZ, int setDependXYtoZ) { start_func
- // Must be a valid combination
- assert(((axisX == AXIS_R) && (axisY == AXIS_G) && (axisZ == AXIS_B)) ||
- ((axisX == AXIS_G) && (axisY == AXIS_R) && (axisZ == AXIS_B)) ||
- ((axisX == AXIS_R) && (axisY == AXIS_B) && (axisZ == AXIS_G)) ||
- ((axisX == AXIS_B) && (axisY == AXIS_G) && (axisZ == AXIS_R)) ||
- ((axisX == AXIS_G) && (axisY == AXIS_B) && (axisZ == AXIS_R)) ||
- ((axisX == AXIS_B) && (axisY == AXIS_R) && (axisZ == AXIS_G)) ||
- ((axisX == AXIS_H) && (axisY == AXIS_S) && (axisZ == AXIS_L)) ||
- ((axisX == AXIS_S) && (axisY == AXIS_H) && (axisZ == AXIS_L)) ||
- ((axisX == AXIS_H) && (axisY == AXIS_L) && (axisZ == AXIS_S)) ||
- ((axisX == AXIS_L) && (axisY == AXIS_S) && (axisZ == AXIS_H)) ||
- ((axisX == AXIS_L) && (axisY == AXIS_H) && (axisZ == AXIS_S)) ||
- ((axisX == AXIS_S) && (axisY == AXIS_L) && (axisZ == AXIS_H)));
- aX = axisX;
- aY = axisY;
- aZ = axisZ;
-
- fX = flipX;
- fY = flipY;
- fZ = flipZ;
-
- dependXYtoZ = setDependXYtoZ;
-
- locateColor(1);
- setDirty(1);
- }
- int* WRGBSelect::convertAxis(color* src, int axis) { start_func
- assert((axis == AXIS_R) || (axis == AXIS_G) || (axis == AXIS_B) ||
- (axis == AXIS_H) || (axis == AXIS_S) || (axis == AXIS_L));
- // Returns a pointer to the item that corresponds to the given axis
- if (axis == AXIS_R) return &(src->R);
- if (axis == AXIS_G) return &(src->G);
- if (axis == AXIS_B) return &(src->B);
- if (axis == AXIS_H) return &(src->Hi);
- if (axis == AXIS_S) return &(src->Si);
- return &(src->Li);
- }
- int WRGBSelect::convertMax(const color* src, int axis) { start_func
- assert((axis == AXIS_R) || (axis == AXIS_G) || (axis == AXIS_B) ||
- (axis == AXIS_H) || (axis == AXIS_S) || (axis == AXIS_L));
- // Returns a pointer to the item that corresponds to the given axis
- if (axis == AXIS_R) return src->max;
- if (axis == AXIS_G) return src->max;
- if (axis == AXIS_B) return src->max;
- return 255;
- }
- void WRGBSelect::redrawXYPanel() { start_func
- color workArea = currentColor;
- int* xAxis;
- int* yAxis;
- int xMax;
- int yMax;
- int HSLmode = 0;
- SDL_PixelFormat* format = xyPanel->format;
-
- if (dependXYtoZ) {
- // RGB mode?
- if ((aX == AXIS_R) || (aX == AXIS_G) || (aX == AXIS_B)) {
- workArea.R = workArea.G = workArea.B = 0;
- }
-
- // HSL mode
- else {
- workArea.Hi = 0;
- workArea.Si = 255;
- workArea.Li = 128;
- HSLmode = 1;
- }
- }
- else if ((aX == AXIS_H) || (aX == AXIS_S) || (aX == AXIS_L)) HSLmode = 1;
-
- xAxis = convertAxis(&workArea, aX);
- yAxis = convertAxis(&workArea, aY);
- xMax = convertMax(&workArea, aX);
- yMax = convertMax(&workArea, aY);
- for (int pY = 0; pY < innerHeight; ++pY) {
- for (int pX = 0; pX < innerWidth; ++pX) {
- // Always flip using w/h, not 255
- if (fX) *xAxis = (((innerWidth - 1) - pX) * xMax + ((innerWidth - 1) / 2)) / (innerWidth - 1);
- else *xAxis = (pX * xMax + ((innerWidth - 1) / 2)) / (innerWidth - 1);
- if (fY) *yAxis = (((innerHeight - 1) - pY) * yMax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
- else *yAxis = (pY * yMax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
- if (HSLmode) workArea.HSLtoRGB();
- assert(workArea.max);
- drawPixel(pX, pY, SDL_MapRGB(format,
- scaleComponent(workArea.R, workArea.max, 255),
- scaleComponent(workArea.G, workArea.max, 255),
- scaleComponent(workArea.B, workArea.max, 255)),
- xyPanel);
- }
- }
-
- dirtyXY = 1;
- setDirty();
- }
- void WRGBSelect::redrawZPanel() { start_func
- color workArea = currentColor;
-
- int* zAxis;
- int zMax;
- int HSLmode = 0;
- SDL_PixelFormat* format = zPanel->format;
-
- if (!dependXYtoZ) {
- // RGB mode?
- if ((aZ == AXIS_R) || (aZ == AXIS_G) || (aZ == AXIS_B)) {
- workArea.R = workArea.G = workArea.B = 0;
- }
-
- // HSL mode
- else {
- workArea.Hi = 0;
- workArea.Si = 255;
- workArea.Li = 128;
- HSLmode = 1;
- }
- }
- else if ((aZ == AXIS_H) || (aZ == AXIS_S) || (aZ == AXIS_L)) HSLmode = 1;
- zAxis = convertAxis(&workArea, aZ);
- zMax = convertMax(&workArea, aZ);
-
- for (int pZ = 0; pZ < innerHeight; ++pZ) {
- // Always flip using w/h, not 255
- if (fZ) *zAxis = (((innerHeight - 1) - pZ) * zMax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
- else *zAxis = (pZ * zMax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
- if (HSLmode) workArea.HSLtoRGB();
-
- assert(workArea.max);
- drawHLine(0, WRGBSELECT_ZWIDTH - 1, pZ, SDL_MapRGB(format,
- scaleComponent(workArea.R, workArea.max, 255),
- scaleComponent(workArea.G, workArea.max, 255),
- scaleComponent(workArea.B, workArea.max, 255)),
- zPanel);
- }
-
- dirtyZ = 1;
- setDirty();
- }
- void WRGBSelect::setXY(int newX, int newY) { start_func
- // Clip
- if (newX < 0) newX = 0;
- if (newY < 0) newY = 0;
- if (newX >= innerWidth) newX = innerWidth - 1;
- if (newY >= innerHeight) newY = innerHeight - 1;
- if ((newX != xSelected) || (newY != ySelected)) {
- xSelected = newX;
- ySelected = newY;
- // Always flip using w/h, not 255
- if (fX) newX = (innerWidth - 1) - newX;
- if (fY) newY = (innerHeight - 1) - newY;
-
- int xymax = convertMax(¤tColor, aX);
- int rgbX = (newX * xymax + ((innerWidth - 1) / 2)) / (innerWidth - 1);
- int rgbY = (newY * xymax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
-
- *(convertAxis(¤tColor, aX)) = rgbX;
- *(convertAxis(¤tColor, aY)) = rgbY;
- // HSL mode or RGB mode? Keep both halves current
- if ((aX == AXIS_H) || (aX == AXIS_S) || (aX == AXIS_L)) currentColor.HSLtoRGB();
- else currentColor.RGBtoHSL();
- if (dependXYtoZ) redrawZPanel();
- dirtyXY = 1;
- setDirty();
- // @TODO: 3 exceptions
- parent->childModified(this);
- }
- }
- void WRGBSelect::setZ(int newZ) { start_func
- // Clip
- if (newZ < 0) newZ = 0;
- if (newZ >= innerHeight) newZ = innerHeight - 1;
- if (newZ != zSelected) {
- zSelected = newZ;
- // Always flip using w/h, not 255
- if (fZ) newZ = (innerHeight - 1) - newZ;
-
- int zmax = convertMax(¤tColor, aZ);
- int rgbZ = (newZ * zmax + ((innerHeight - 1) / 2)) / (innerHeight - 1);
-
- *(convertAxis(¤tColor, aZ)) = rgbZ;
- // HSL mode or RGB mode? Keep both halves current
- if ((aZ == AXIS_H) || (aZ == AXIS_S) || (aZ == AXIS_L)) currentColor.HSLtoRGB();
- else currentColor.RGBtoHSL();
- if (!dependXYtoZ) redrawXYPanel();
- dirtyZ = 1;
- setDirty();
- // @TODO: 3 exceptions
- parent->childModified(this);
- }
- }
- void WRGBSelect::locateColor(int fullredraw) { start_func
- int newX = *(convertAxis(¤tColor, aX)) * (innerWidth - 1) / convertMax(¤tColor, aX);
- int newY = *(convertAxis(¤tColor, aY)) * (innerHeight - 1) / convertMax(¤tColor, aY);
- int newZ = *(convertAxis(¤tColor, aZ)) * (innerHeight - 1) / convertMax(¤tColor, aZ);
-
- // Always flip using w/h, not 255
- if (fX) newX = (innerWidth - 1) - newX;
- if (fY) newY = (innerHeight - 1) - newY;
- if (fZ) newZ = (innerHeight - 1) - newZ;
-
- if ((xSelected != newX) || (ySelected != newY)) {
- xSelected = newX;
- ySelected = newY;
- if ((dependXYtoZ) || (fullredraw)) redrawZPanel();
- dirtyXY = 1;
- setDirty();
- }
- else if (fullredraw) redrawZPanel();
-
- if (zSelected != newZ) {
- zSelected = newZ;
- if ((!dependXYtoZ) || (fullredraw)) redrawXYPanel();
- dirtyZ = 1;
- setDirty();
- }
- else if (fullredraw) redrawXYPanel();
- }
- int WRGBSelect::event(int hasFocus, const SDL_Event* event) { start_func
- assert(event);
- assert(parent);
- int amount;
-
- switch (event->type) {
- case SDL_INPUTFOCUS:
- if (event->user.code & 1) {
- if (!haveFocus) {
- haveFocus = 1;
- setDirty(1);
- }
- }
- else {
- if (haveFocus) {
- haveFocus = 0;
- setDirty(1);
- }
- }
- return 1;
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONDBL:
- if (event->button.button == SDL_BUTTON_LEFT) {
- dragMode = WRGBSELECT_DRAG_NONE;
- if ((event->button.y >= WRGBSELECT_BORDER) && (event->button.y < height - WRGBSELECT_BORDER)) {
- if ((event->button.x >= WRGBSELECT_BORDER) && (event->button.x < innerWidth + WRGBSELECT_BORDER)) {
- setXY(event->button.x - WRGBSELECT_BORDER, event->button.y - WRGBSELECT_BORDER);
- dragMode = WRGBSELECT_DRAG_XY;
- }
- if ((event->button.x >= zPanelX) && (event->button.x < zPanelX + WRGBSELECT_ZWIDTH)) {
- setZ(event->button.y - WRGBSELECT_BORDER);
- dragMode = WRGBSELECT_DRAG_Z;
- }
- }
-
- return 1;
- }
- break;
-
- case SDL_MOUSEBUTTONUP:
- if (event->button.button == SDL_BUTTON_LEFT) {
- dragMode = WRGBSELECT_DRAG_NONE;
- return 1;
- }
- break;
- case SDL_MOUSEMOTION:
- if (event->motion.state & SDL_BUTTON_LMASK) {
- if (dragMode == WRGBSELECT_DRAG_XY) {
- setXY((Sint16)event->motion.x - WRGBSELECT_BORDER, (Sint16)event->motion.y - WRGBSELECT_BORDER);
- }
- else if (dragMode == WRGBSELECT_DRAG_Z) {
- setZ((Sint16)event->button.y - WRGBSELECT_BORDER);
- }
-
- return 1;
- }
- break;
-
- case SDL_KEYDOWN:
- amount = (event->key.keysym.mod & KMOD_CTRL) ? 10 : 1;
-
- switch (combineKey(event->key.keysym.sym, event->key.keysym.mod & (~KMOD_CTRL))) {
- case SDLK_RIGHT:
- setXY(xSelected + amount, ySelected);
- return 1;
-
- case SDLK_DOWN:
- setXY(xSelected, ySelected + amount);
- return 1;
- case SDLK_LEFT:
- setXY(xSelected - amount, ySelected);
- return 1;
- case SDLK_UP:
- setXY(xSelected, ySelected - amount);
- return 1;
- case SDLK_PAGEUP:
- setZ(zSelected - amount);
- return 1;
- case SDLK_PAGEDOWN:
- setZ(zSelected + amount);
- return 1;
- }
- break;
- }
- return 0;
- }
- void WRGBSelect::load() { start_func
- currentColor = *((color*)setting);
- locateColor(0);
- }
- void WRGBSelect::apply() { start_func
- *((color*)setting) = currentColor;
- }
- void WRGBSelect::displayCursor(SDL_Surface* destSurface, int xCenter, int yCenter) { start_func
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2,
- WRGBSELECT_CURSOR_LENGTH, WRGBSELECT_CURSOR_THICK,
- guiPacked[COLOR_TEXT], destSurface);
- drawRect(xCenter + (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2,
- WRGBSELECT_CURSOR_LENGTH, WRGBSELECT_CURSOR_THICK,
- guiPacked[COLOR_TEXT], destSurface);
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH,
- WRGBSELECT_CURSOR_THICK, WRGBSELECT_CURSOR_LENGTH,
- guiPacked[COLOR_TEXT], destSurface);
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2,
- yCenter + (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- WRGBSELECT_CURSOR_THICK, WRGBSELECT_CURSOR_LENGTH,
- guiPacked[COLOR_TEXT], destSurface);
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH + 1,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- WRGBSELECT_CURSOR_LENGTH - 2, WRGBSELECT_CURSOR_THICK - 2,
- guiPacked[COLOR_LIGHT1], destSurface);
- drawRect(xCenter + (WRGBSELECT_CURSOR_THICK - 1) / 2 + 2,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- WRGBSELECT_CURSOR_LENGTH - 2, WRGBSELECT_CURSOR_THICK - 2,
- guiPacked[COLOR_LIGHT1], destSurface);
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH + 1,
- WRGBSELECT_CURSOR_THICK - 2, WRGBSELECT_CURSOR_LENGTH - 2,
- guiPacked[COLOR_LIGHT1], destSurface);
- drawRect(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 + 1,
- yCenter + (WRGBSELECT_CURSOR_THICK - 1) / 2 + 2,
- WRGBSELECT_CURSOR_THICK - 2, WRGBSELECT_CURSOR_LENGTH - 2,
- guiPacked[COLOR_LIGHT1], destSurface);
-
- if (haveFocus) {
- drawFocusBox(xCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH,
- yCenter - (WRGBSELECT_CURSOR_THICK - 1) / 2 - WRGBSELECT_CURSOR_LENGTH,
- WRGBSELECT_CURSOR_LENGTH * 2 + WRGBSELECT_CURSOR_THICK,
- WRGBSELECT_CURSOR_LENGTH * 2 + WRGBSELECT_CURSOR_THICK,
- destSurface);
- }
- }
- void WRGBSelect::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
- assert(destSurface);
- if (visible) {
- // This breaks redraw down into xy and z panels
- // Redraw all?
- if (totalDirty) {
- getRect(toDisplay);
- toDisplay.x += xOffset;
- toDisplay.y += yOffset;
- intersectRects(toDisplay, clipArea);
- }
-
- xOffset += x;
- yOffset += y;
-
- // Anything to draw so far?
- if (toDisplay.w) {
- SDL_SetClipRect(destSurface, &toDisplay);
-
- // Draw fill
- SDL_FillRect(destSurface, &toDisplay, guiPacked[COLOR_FILL]);
-
- // Borders
- drawGuiBoxInvert(xOffset, yOffset, innerWidth + WRGBSELECT_BORDER * 2, innerHeight + WRGBSELECT_BORDER * 2, WRGBSELECT_BORDER, destSurface);
- drawGuiBoxInvert(xOffset + zPanelX, yOffset, WRGBSELECT_ZWIDTH + WRGBSELECT_BORDER * 2, innerHeight + WRGBSELECT_BORDER * 2, WRGBSELECT_BORDER, destSurface);
- }
- // This will be the final displayed amount, we update it as we go but still work
- // off of the original dirtied area for efficiency
- Rect updatedArea = toDisplay;
- // Determine clip area for XY panel
- Rect xyClip = { xOffset + WRGBSELECT_BORDER, yOffset + WRGBSELECT_BORDER, innerWidth, innerHeight };
- intersectRects(xyClip, clipArea);
- // If we need to update XY panel, OR it intersects with the dirty area,
- // redraw it; note that if the second conditional is tested, xyClip will be reduced
- // to whatever portion intersects with the dirty area, which is what we want
- if ((dirtyXY) || (intersectRects(xyClip, toDisplay))) {
- // Add panel rect into updated area
- boundRects(updatedArea, xyClip);
- SDL_SetClipRect(destSurface, &xyClip);
-
- // Colorful area
- blit(0, 0, xyPanel, xOffset + WRGBSELECT_BORDER, yOffset + WRGBSELECT_BORDER, destSurface, innerWidth, innerHeight);
- // Selection cursor
- displayCursor(destSurface, xOffset + WRGBSELECT_BORDER + xSelected, yOffset + WRGBSELECT_BORDER + ySelected);
- }
- // Determine clip area for Z panel
- Rect zClip = { xOffset + zPanelX + WRGBSELECT_BORDER, yOffset+ WRGBSELECT_BORDER, WRGBSELECT_ZWIDTH, innerHeight };
- intersectRects(zClip, clipArea);
- // If we need to update Z panel, OR it intersects with the dirty area,
- // redraw it; note that if the second conditional is tested, zClip will be reduced
- // to whatever portion intersects with the dirty area, which is what we want
- if ((dirtyZ) || (intersectRects(zClip, toDisplay))) {
- // Add panel rect into updated area
- boundRects(updatedArea, zClip);
- SDL_SetClipRect(destSurface, &zClip);
-
- // Colorful area
- blit(0, 0, zPanel, xOffset + zPanelX + WRGBSELECT_BORDER, yOffset + WRGBSELECT_BORDER, destSurface, WRGBSELECT_ZWIDTH, innerHeight);
-
- // Selection cursor
- displayCursor(destSurface, xOffset + zPanelX + WRGBSELECT_BORDER + WRGBSELECT_ZWIDTH / 2, yOffset + WRGBSELECT_BORDER + zSelected);
- }
- toDisplay = updatedArea;
- }
-
- dirty = dirtyXY = dirtyZ = totalDirty = 0;
- }
- void WRGBSelect::resolutionChange(int fromW, int fromH, int fromBpp, int toW, int toH, int toBpp) { start_func
- Window::resolutionChange(fromW, fromH, fromBpp, toW, toH, toBpp);
- if (fromBpp != toBpp) {
- if (xyPanel) SDL_FreeSurface(xyPanel);
- xyPanel = NULL;
- if (zPanel) SDL_FreeSurface(zPanel);
- zPanel = NULL;
-
- xyPanel = createSurface(innerWidth, innerHeight);
- zPanel = createSurface(WRGBSELECT_ZWIDTH, innerHeight);
-
- redrawXYPanel();
- redrawZPanel();
- }
- }
- // Color display widget
- WShowColor::WShowColor(int wId, int w, int h, color* wSetting) : Widget(wId, blankString, wSetting) { start_func
- assert(wSetting);
- assert(w > 0);
- assert(h > 0);
-
- resize(w + SHOWCOLOR_BORDER * 2, h + SHOWCOLOR_BORDER * 2);
- }
- WShowColor::~WShowColor() { start_func
- }
- int WShowColor::event(int hasFocus, const SDL_Event* event) { start_func
- // (no events accepted)
- return 0;
- }
- int WShowColor::refuseAll() const { start_func
- // (no events accepted)
- return 1;
- }
- void WShowColor::load() { start_func
- currentColor = *((color*)setting);
- setDirty();
- }
- void WShowColor::apply() { start_func
- // (doesn't apply)
- }
- void WShowColor::display(SDL_Surface* destSurface, Rect& toDisplay, const Rect& clipArea, int xOffset, int yOffset) { start_func
- assert(destSurface);
- if (visible) {
- // If dirty, redraw all
- if (dirty) {
- getRect(toDisplay);
- toDisplay.x += xOffset;
- toDisplay.y += yOffset;
- dirty = 0;
- intersectRects(toDisplay, clipArea);
- }
-
- // Anything to draw?
- if (toDisplay.w) {
- SDL_SetClipRect(destSurface, &toDisplay);
- xOffset += x;
- yOffset += y;
-
- // 0 alpha shows different
- if ((currentColor.A == 0) && (currentColor.maxAlpha)) {
- SDL_FillRect(destSurface, &toDisplay, guiPacked[COLOR_TRANSPARENT1]);
- drawLine(xOffset, yOffset, xOffset + width - 1, yOffset + height - 1,
- guiPacked[COLOR_TRANSPARENT2], destSurface);
- drawLine(xOffset + width - 1, yOffset, xOffset, yOffset + height - 1,
- guiPacked[COLOR_TRANSPARENT2], destSurface);
- }
- else {
- assert(currentColor.max);
- SDL_FillRect(destSurface, &toDisplay, SDL_MapRGB(destSurface->format,
- scaleComponent(currentColor.R, currentColor.max, 255),
- scaleComponent(currentColor.G, currentColor.max, 255),
- scaleComponent(currentColor.B, currentColor.max, 255)));
-
- if ((currentColor.A < currentColor.maxAlpha) && (currentColor.maxAlpha)) {
- drawRect(xOffset, yOffset + height / 2, width, height / 2,
- SDL_MapRGB(destSurface->format,
- scaleComponent(currentColor.R * currentColor.A / currentColor.maxAlpha, currentColor.max, 255),
- scaleComponent(currentColor.G * currentColor.A / currentColor.maxAlpha, currentColor.max, 255),
- scaleComponent(currentColor.B * currentColor.A / currentColor.maxAlpha, currentColor.max, 255)),
- destSurface);
- }
- }
- // @TODO: Corners of inverted box aren't grey
- drawGuiBoxInvert(xOffset, yOffset, width, height, SHOWCOLOR_BORDER, destSurface);
- }
- }
- }
- // RGB selection dialog
- RGBSelect* RGBSelect::dialog = NULL;
- RGBSelect* RGBSelect::create() { start_func
- if (!dialog) {
- dialog = new RGBSelect();
- }
- return dialog;
- }
- void RGBSelect::destroy() { start_func
- if (dialog) {
- delete dialog;
- dialog = NULL;
- }
- }
- const string RGBSelect::resourceError("Error loading resource/coloricon.bmp");
- RGBSelect::RGBSelect() : Dialog("Select Color", 1) { start_func
- initializedH = 0;
- iconSurface = NULL;
- }
- void RGBSelect::applyRGBMethod() { start_func
- WRGBSelect* widget = dynamic_cast<WRGBSelect*>(findWidget(ID_RGBSELECT));
- switch (method) {
- case ID_METHOD_HS:
- widget->setMode(WRGBSelect::AXIS_H, WRGBSelect::AXIS_S, WRGBSelect::AXIS_L,
- 0, 1, 1);
- break;
-
- case ID_METHOD_LH:
- widget->setMode(WRGBSelect::AXIS_H, WRGBSelect::AXIS_L, WRGBSelect::AXIS_S,
- 0, 1, 1);
- break;
-
- case ID_METHOD_SL:
- widget->setMode(WRGBSelect::AXIS_S, WRGBSelect::AXIS_L, WRGBSelect::AXIS_H,
- 1, 1, 0, 0);
- break;
-
- case ID_METHOD_RG:
- widget->setMode(WRGBSelect::AXIS_R, WRGBSelect::AXIS_G, WRGBSelect::AXIS_B,
- 0, 1, 1);
- break;
-
- case ID_METHOD_GB:
- widget->setMode(WRGBSelect::AXIS_G, WRGBSelect::AXIS_B, WRGBSelect::AXIS_R,
- 0, 1, 1);
- break;
- case ID_METHOD_BR:
- widget->setMode(WRGBSelect::AXIS_B, WRGBSelect::AXIS_R, WRGBSelect::AXIS_G,
- 0, 1, 1);
- break;
- }
- }
- int RGBSelect::run(unsigned char& r, unsigned char& g, unsigned char& b, unsigned char& a, int bitDepthAlpha, int bitDepth) { start_func
- method = config->readNum(RGBSELECT_METHOD);
- if ((method < ID_METHOD_HS) || (method > ID_METHOD_BR)) method = ID_METHOD_HS;
- rgbBitDepth = bitDepth;
- alphaBitDepth = bitDepthAlpha;
- int maxComponent = (1 << bitDepth) - 1;
- int maxAlpha = (1 << bitDepthAlpha) - 1;
- theColor.R = r;
- theColor.G = g;
- theColor.B = b;
- theColor.A = a;
- theColor.max = maxComponent;
- theColor.maxAlpha = maxAlpha;
- theColor.RGBtoHSL();
- if (initializedH) {
- initializedH = 0;
- clearWidgets();
- }
- else {
- string iconFile;
- createFilename(resourceDir->c_str(), FILENAME_COLORICONS, iconFile);
- iconSurface = SDL_LoadBMP(iconFile.c_str());
- if (iconSurface == NULL) {
- guiErrorBox(resourceError, errorTitleResourceLoad);
- }
- }
- Widget* w = NULL;
- WNumberBox* n = NULL;
-
- // We hide the top row and resize the color selection area as needed
- // to fit within current resolution
- if (screenHeight >= 350) {
- w = new WShowColor(ID_DEMOCOLOR, 30, 30, &theColor);
- w->setToolTip("Current color");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 0, 0, 20, 20, &method, ID_METHOD_HS);
- w->setToolTip("Select by hue/saturation");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 20, 0, 20, 20, &method, ID_METHOD_LH);
- w->setToolTip("Select by hue/luminance");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 40, 0, 20, 20, &method, ID_METHOD_SL);
- w->setToolTip("Select by saturation/luminance");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 60, 0, 20, 20, &method, ID_METHOD_RG);
- w->setToolTip("Select by red/green");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 80, 0, 20, 20, &method, ID_METHOD_GB);
- w->setToolTip("Select by green/blue");
- w->addTo(this);
- w = new WRadioButton(ID_METHOD, iconSurface, 100, 0, 20, 20, &method, ID_METHOD_BR);
- w->setToolTip("Select by red/blue");
- w->addTo(this);
- arrangeRow();
- w = new WRGBSelect(ID_RGBSELECT, 208, min(208, screenHeight - 220), &theColor, rgbBitDepth);
- w->addTo(this);
-
- arrangeRow();
- }
- else {
- w = new WRGBSelect(ID_RGBSELECT, 208, screenHeight - 180, &theColor, rgbBitDepth);
- w->addTo(this);
-
- arrangeRow();
- }
- applyRGBMethod();
- w = new WStatic(ID_R_LABEL, "\tR:");
- w->addTo(this);
- w = n = new WNumberBox(ID_R_N, &theColor.R, 0, maxComponent);
- w->setToolTip("Red");
- w->addTo(this);
-
- w = new WSlider(ID_R_S, 0, maxComponent, &theColor.R);
- w->setToolTip("Red");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_H_LABEL, "\tH:");
- w->addTo(this);
- w = n = new WNumberBox(ID_H_N, &theColor.Hi, 0, 255);
- w->setToolTip("Hue (what color)");
- w->addTo(this);
-
- w = new WSlider(ID_H_S, 0, 255, &theColor.Hi);
- w->setToolTip("Hue (what color)");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_G_LABEL, "\tG:");
- w->addTo(this);
- w = n = new WNumberBox(ID_G_N, &theColor.G, 0, maxComponent);
- w->setToolTip("Green");
- w->addTo(this);
-
- w = new WSlider(ID_G_S, 0, maxComponent, &theColor.G);
- w->setToolTip("Green");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_S_LABEL, "\tS:");
- w->addTo(this);
- w = n = new WNumberBox(ID_S_N, &theColor.Si, 0, 255);
- w->setToolTip("Saturation (how colorful or grey)");
- w->addTo(this);
-
- w = new WSlider(ID_S_S, 0, 255, &theColor.Si);
- w->setToolTip("Saturation (how colorful or grey)");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_B_LABEL, "\tB:");
- w->addTo(this);
- w = n = new WNumberBox(ID_B_N, &theColor.B, 0, maxComponent);
- w->setToolTip("Blue");
- w->addTo(this);
-
- w = new WSlider(ID_B_S, 0, maxComponent, &theColor.B);
- w->setToolTip("Blue");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_L_LABEL, "\tL:");
- w->addTo(this);
- w = n = new WNumberBox(ID_L_N, &theColor.Li, 0, 255);
- w->setToolTip("Luminance (how bright)");
- w->addTo(this);
-
- w = new WSlider(ID_L_S, 0, 255, &theColor.Li);
- w->setToolTip("Luminance (how bright)");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WStatic(ID_A_LABEL, "\tA:");
- w->addTo(this);
- w = n = new WNumberBox(ID_A_N, &theColor.A, 0, maxAlpha);
- w->setToolTip("Alpha (blend percent)");
- w->addTo(this);
-
- w = new WSlider(ID_A_S, 0, maxAlpha, &theColor.A);
- w->setToolTip("Alpha (blend percent)");
- dynamic_cast<WSlider*>(w)->linkTo(n);
- w->addTo(this);
- w = new WButton(ID_OK, messageBoxOK, Dialog::BUTTON_OK);
- w->addTo(this);
- w = new WButton(ID_CANCEL, messageBoxCancel, Dialog::BUTTON_CANCEL);
- w->addTo(this);
-
- makePretty(6, 1, 1, 1);
-
- initializedH = screenHeight;
-
- if (bitDepthAlpha) {
- findWidget(ID_A_LABEL)->enable();
- findWidget(ID_A_N)->enable();
- findWidget(ID_A_S)->enable();
- }
- else {
- findWidget(ID_A_LABEL)->disable();
- findWidget(ID_A_N)->disable();
- findWidget(ID_A_S)->disable();
- }
- int result = runModal();
-
- if (result == ID_OK) {
- config->write(RGBSELECT_METHOD, method);
- r = theColor.R;
- g = theColor.G;
- b = theColor.B;
- a = theColor.A;
-
- return 1;
- }
-
- return 0;
- }
- void RGBSelect::childModified(Window* modified) { start_func
- Dialog::childModified(modified);
-
- Widget* widget = dynamic_cast<Widget*>(modified);
- if (widget) {
- if ((!inSiblingModify) && (initializedH)) {
- Dialog::childModified(modified);
- inSiblingModify = 1;
- int id = widget->getId();
- // If method changed, update RGB control
- if (id == ID_METHOD) {
- applyRGBMethod();
- }
- // If selector updated, other stuff reloads
- if (id == ID_RGBSELECT) {
- for (int pos = ID_R_N; pos <= ID_L_S; ++pos) {
- findWidget(pos)->load();
- }
- }
- // If RGB updated, copy to HSL
- if ((id >= ID_R_N) && (id <= ID_B_S)) {
- theColor.RGBtoHSL();
- findWidget(ID_H_N)->load();
- findWidget(ID_S_N)->load();
- findWidget(ID_L_N)->load();
- findWidget(ID_H_S)->load();
- findWidget(ID_S_S)->load();
- findWidget(ID_L_S)->load();
- findWidget(ID_RGBSELECT)->load();
- }
- // If HSL updated, copy to RGB
- if ((id >= ID_H_N) && (id <= ID_L_S)) {
- theColor.HSLtoRGB();
- findWidget(ID_R_N)->load();
- findWidget(ID_G_N)->load();
- findWidget(ID_B_N)->load();
- findWidget(ID_R_S)->load();
- findWidget(ID_G_S)->load();
- findWidget(ID_B_S)->load();
- findWidget(ID_RGBSELECT)->load();
- }
- // Update sample, if present
- if (initializedH >= 350) findWidget(ID_DEMOCOLOR)->load();
- inSiblingModify = 0;
- }
- }
- }
|