diff options
Diffstat (limited to 'lib/kopainter')
26 files changed, 6414 insertions, 0 deletions
diff --git a/lib/kopainter/Makefile.am b/lib/kopainter/Makefile.am new file mode 100644 index 00000000..8143db4d --- /dev/null +++ b/lib/kopainter/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES= $(KOFFICECORE_INCLUDES) $(KOFFICEUI_INCLUDES) $(all_includes) + +lib_LTLIBRARIES = libkopainter.la +libkopainter_la_SOURCES = svgpathparser.cc \ + koColor.cc \ + koFrameButton.cc \ + koColorSlider.cc \ + koColorChooser.cc \ + koIconChooser.cc \ + kogradientmanager.cc \ + ko_color_wheel.cc \ + ko_gray_widget.cc \ + ko_hsv_widget.cc \ + ko_rgb_widget.cc \ + ko_cmyk_widget.cc + +libkopainter_la_LDFLAGS = $(all_libraries) -version-info 2:0:0 -no-undefined + +libkopainter_la_LIBADD = $(LIB_KOFFICEUI) + +METASOURCES = AUTO diff --git a/lib/kopainter/koColor.cc b/lib/kopainter/koColor.cc new file mode 100644 index 00000000..e808ca8b --- /dev/null +++ b/lib/kopainter/koColor.cc @@ -0,0 +1,742 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "koColor.h" +#include "kdebug.h" +#include <cmath> + +KoColor::KoColor() +{ + // initialise to black + mNative = csRGB; + // RGB + mR = 0; + mG = 0; + mB = 0; + // HSV + mH = mV = 0; + mS = 100; + // CMYK + mC = 0; + mY = 0; + mM = 0; + mK = 0; + // Lab + mL = 0; + ma = 0; + mB = 0; + rgbChanged(); +} + +KoColor::KoColor(int a, int b, int c, cSpace m) +{ + switch(m) + { + case csRGB: + mR = a; + mG = b; + mB = c; + mNative = csRGB; + rgbChanged(); + break; + case csHSV: + mH = a; + mS = b; + mV = c; + mNative = csHSV; + hsvChanged(); + break; + case csLab: + mL = a; + ma = b; + mB = c; + mNative = csLab; + labChanged(); + break; + default: + mR = 0; + mG = 0; + mB = 0; + mNative = csRGB; + rgbChanged(); + } +} + +KoColor::KoColor(int c, int m, int y, int k) +{ + mC = c; + mM = m; + mY = y; + mK = k; + mNative = csCMYK; + cmykChanged(); +} + +KoColor::KoColor(const QColor &c) +{ + mR = c.red(); + mG = c.green(); + mB = c.blue(); + mNative = csRGB; + rgbChanged(); +} + +KoColor::KoColor(const QString &name) +{ + setNamedColor(name); +} + +int KoColor::R() const +{ + if(!mRGBvalid) + calcRGB(); + return mR; +} + +int KoColor::G() const +{ + if(!mRGBvalid) + calcRGB(); + return mG; +} + +int KoColor::B() const +{ + if(!mRGBvalid) + calcRGB(); + return mB; +} + +int KoColor::H() const +{ + if(!mHSVvalid) + calcHSV(); + return mH; +} + +int KoColor::S() const +{ + if(!mHSVvalid) + calcHSV(); + return mS; +} + +int KoColor::V() const +{ + if(!mHSVvalid) + calcHSV(); + return mV; +} + +int KoColor::C() const +{ + if(!mCMYKvalid) + calcCMYK(); + return mC; +} + +int KoColor::M() const +{ + if(!mCMYKvalid) + calcCMYK(); + return mM; +} + +int KoColor::Y() const +{ + if(!mCMYKvalid) + calcCMYK(); + return mY; +} + +int KoColor::K() const +{ + if(!mCMYKvalid) + calcCMYK(); + return mK; +} + +int KoColor::L() const +{ + if(!mLABvalid) + calcLAB(); + return mL; +} + +int KoColor::a() const +{ + if(!mLABvalid) + calcLAB(); + return ma; +} + +int KoColor::b() const +{ + if(!mLABvalid) + calcLAB(); + return mB; +} + +void KoColor::rgb(int *R, int *G, int *B) const +{ + if(!mRGBvalid) + calcRGB(); + *R = mR; + *G = mG; + *B = mB; +} + +void KoColor::hsv(int *H, int *S, int *V) const +{ + if(!mHSVvalid) + calcHSV(); + *H = mH; + *S = mS; + *V = mV; +} + +void KoColor::lab(int *L, int *a, int *b) const +{ + if(!mLABvalid) + calcLAB(); + *L = mL; + *a = ma; + *b = mB; +} + +void KoColor::cmyk(int *C, int *M, int *Y, int *K) const +{ + if(!mCMYKvalid) + calcCMYK(); + *C = mC; + *M = mM; + *Y = mY; + *K = mK; +} + +QString KoColor::name() const +{ + QString s; + switch(mNative) + { + case csRGB: + s.sprintf("#%02x%02x%02x", R(), G(), B()); + break; + case csHSV: + s.sprintf("$%02x%02x%02x", H(), S(), V()); + break; + case csCMYK: + s.sprintf("@%02x%02x%02x%02x", C(), M(), Y(), K()); + break; + case csLab: + s.sprintf("*%02x%02x%02x", L(), a(), b()); + break; + default: + s.sprintf("#%02x%02x%02x", R(), G(), B()); + } + return s; +} + +QColor KoColor::color() const +{ + if(!mRGBvalid) + calcRGB(); + return QColor(mR, mG, mB); +} + +void KoColor::setRGB(int R, int G, int B) +{ + mR = R; + mG = G; + mB = B; + mNative = csRGB; + rgbChanged(); +} + +void KoColor::setHSV(int H, int S, int V) +{ + mH = H; + mS = S; + mV = V; + mNative = csHSV; + hsvChanged(); +} + +void KoColor::setLab(int L, int a, int b) +{ + mL = L; + ma = a; + mB = b; + mNative = csLab; + labChanged(); +} + +void KoColor::setCMYK(int C, int M, int Y, int K) +{ + mC = C; + mM = M; + mY = Y; + mK = K; + mNative = csCMYK; + cmykChanged(); +} + +void KoColor::setNamedColor(const QString &name) +{ + switch(name[0]) + { + case '#': + mR = (hex2int(name[1]) << 4) + hex2int(name[2]); + mG = (hex2int(name[3]) << 4) + hex2int(name[4]); + mB = (hex2int(name[5]) << 4) + hex2int(name[6]); + mNative = csRGB; + rgbChanged(); + break; + case '$': + mH = (hex2int(name[1]) << 4) + hex2int(name[2]); + mS = (hex2int(name[3]) << 4) + hex2int(name[4]); + mV = (hex2int(name[5]) << 4) + hex2int(name[6]); + mNative = csHSV; + hsvChanged(); + break; + case '@': + mC = (hex2int(name[1]) << 4) + hex2int(name[2]); + mM = (hex2int(name[3]) << 4) + hex2int(name[4]); + mY = (hex2int(name[5]) << 4) + hex2int(name[6]); + mK = (hex2int(name[7]) << 4) + hex2int(name[8]); + mNative = csCMYK; + cmykChanged(); + break; + case '*': + mL = (hex2int(name[1]) << 4) + hex2int(name[2]); + ma = (hex2int(name[3]) << 4) + hex2int(name[4]); + mb = (hex2int(name[5]) << 4) + hex2int(name[6]); + mNative = csLab; + labChanged(); + break; + default: + mR = 0; + mG = 0; + mB = 0; + mNative = csRGB; + rgbChanged(); + } +} + +void KoColor::setColor(const QColor &c) +{ + mR = c.red(); + mG = c.green(); + mB = c.blue(); + mNative = csRGB; + rgbChanged(); +} + +void KoColor::RGBtoHSV(int R, int G, int B, int *H, int *S, int *V) +{ + unsigned int max = R; + unsigned int min = R; + unsigned char maxValue = 0; // r = 0, g = 1, b = 2 + + // find maximum and minimum RGB values + if(static_cast<unsigned int>(G) > max) + { + max = G; + maxValue = 1; + } + if(static_cast<unsigned int>(B) > max) + { + max = B; + maxValue = 2; + } + + if(static_cast<unsigned int>(G) < min) + min = G; + if(static_cast<unsigned int>(B) < min ) + min = B; + + int delta = max - min; + *V = max; // value + *S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation + + // calc hue + if(*S == 0) + *H = -1; // undefined hue + else + { + switch(maxValue) + { + case 0: // red + if(G >= B) + *H = (120 * (G - B) + delta) / (2 * delta); + else + *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300; + break; + case 1: // green + if(B > R) + *H = 120 + (120 * (B - R) + delta) / (2 * delta); + else + *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta); + break; + case 2: // blue + if(R > G) + *H = 240 + (120 * (R - G) + delta) / (2 * delta); + else + *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta); + break; + } + } +} + +void KoColor::RGBtoLAB(int R, int G, int B, int *L, int *a, int *b) +{ + // Convert between RGB and CIE-Lab color spaces + // Uses ITU-R recommendation BT.709 with D65 as reference white. + // algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU> + + double X, Y, Z, fX, fY, fZ; + + X = 0.412453 * R + 0.357580 * G + 0.180423 * B; + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B; + Z = 0.019334 * R + 0.119193 * G + 0.950227 * B; + + X /= (255 * 0.950456); + Y /= 255; + Z /= (255 * 1.088754); + + if(Y > 0.008856) + { + fY = pow(Y, 1.0 / 3.0); + *L = static_cast<int>(116.0 * fY - 16.0 + 0.5); + } + else + { + fY = 7.787 * Y + 16.0 / 116.0; + *L = static_cast<int>(903.3 * Y + 0.5); + } + + if(X > 0.008856) + fX = pow(X, 1.0 / 3.0); + else + fX = 7.787 * X + 16.0 / 116.0; + + if(Z > 0.008856) + fZ = pow(Z, 1.0 / 3.0); + else + fZ = 7.787 * Z + 16.0 / 116.0; + + *a = static_cast<int>(500.0 * (fX - fY) + 0.5); + *b = static_cast<int>(200.0 * (fY - fZ) + 0.5); +} + +void KoColor::RGBtoCMYK(int R, int G, int B, int *C, int *M, int *Y, int *K) +{ + // XXX: these algorithms aren't the best. See www.littlecms.com + // for a suitable library, or the posting by Leo Rosenthol for + // a better, but slower algorithm at + // http://lists.kde.org/?l=koffice-devel&m=106698241227054&w=2 + + *C = 255 - R; + *M = 255 - G; + *Y = 255 - B; + + int min = (*C < *M) ? *C : *M; + *K = (min < *Y) ? min : *Y; + + *C -= *K; + *M -= *K; + *Y -= *K; + +} + + +void KoColor::HSVtoRGB(int H, int S, int V, int *R, int *G, int *B) +{ + *R = *G = *B = V; + + if(S != 0 && H != -1) // chromatic + { + if(H >= 360) // angle > 360 + H %= 360; + + unsigned int f = H % 60; + H /= 60; + unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510; + unsigned int q, t; + + if(H & 1) + { + q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600; + switch(H) + { + case 1: + *R = static_cast<int>(q); + *G = static_cast<int>(V); + *B = static_cast<int>(p); + break; + case 3: + *R = static_cast<int>(p); + *G = static_cast<int>(q); + *B = static_cast<int>(V); + break; + case 5: + *R = static_cast<int>(V); + *G = static_cast<int>(p); + *B = static_cast<int>(q); + break; + } + } + else + { + t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600; + switch(H) + { + case 0: + *R = static_cast<int>(V); + *G = static_cast<int>(t); + *B = static_cast<int>(p); + break; + case 2: + *R = static_cast<int>(p); + *G = static_cast<int>(V); + *B = static_cast<int>(t); + break; + case 4: + *R = static_cast<int>(t); + *G = static_cast<int>(p); + *B = static_cast<int>(V); + break; + } + } + } +} + +void KoColor::HSVtoLAB(int H, int S, int V, int *L, int *a, int *b) +{ + int R, G, B; + HSVtoRGB(H, S, V, &R, &G, &B); + RGBtoLAB(R, G, B, L, a, b); +} + +void KoColor::HSVtoCMYK(int H, int S, int V, int *C, int *M, int *Y, int*K) +{ + int R, G, B; + HSVtoRGB(H, S, V, &R, &G, &B); + RGBtoCMYK(R, G, B, C, M, Y, K); +} + +void KoColor::LABtoRGB(int L, int a, int b, int *R, int *G, int *B) +{ + // Convert between RGB and CIE-Lab color spaces + // Uses ITU-R recommendation BT.709 with D65 as reference white. + // algorithm contributed by "Mark A. Ruzon" <ruzon@CS.Stanford.EDU> + + double X, Y, Z, fX, fY, fZ; + int RR, GG, BB; + + fY = pow((L + 16.0) / 116.0, 3.0); + if(fY < 0.008856) + fY = L / 903.3; + Y = fY; + + if(fY > 0.008856) + fY = pow(fY, 1.0 / 3.0); + else + fY = 7.787 * fY + 16.0 / 116.0; + + fX = a / 500.0 + fY; + if(fX > 0.206893) + X = pow(fX, 3.0); + else + X = (fX - 16.0 / 116.0) / 7.787; + + fZ = fY - b / 200.0; + if(fZ > 0.206893) + Z = pow(fZ, 3.0); + else + Z = (fZ - 16.0/116.0) / 7.787; + + X *= 0.950456 * 255; + Y *= 255; + Z *= 1.088754 * 255; + + RR = static_cast<int>(3.240479 * X - 1.537150 * Y - 0.498535 * Z + 0.5); + GG = static_cast<int>(-0.969256 * X + 1.875992 * Y + 0.041556 * Z + 0.5); + BB = static_cast<int>(0.055648 * X - 0.204043 * Y + 1.057311 * Z + 0.5); + + *R = RR < 0 ? 0 : RR > 255 ? 255 : RR; + *G = GG < 0 ? 0 : GG > 255 ? 255 : GG; + *B = BB < 0 ? 0 : BB > 255 ? 255 : BB; +} + +void KoColor::LABtoHSV(int L, int a, int b, int *H, int *S, int *V) +{ + int R, G, B; + LABtoRGB(L, a, b, &R, &G, &B); + RGBtoHSV(R, G, B, H, S, V); +} + +void KoColor::LABtoCMYK(int L, int a, int b, int *C, int *M, int *Y, int*K) +{ + int R, G, B; + LABtoRGB(L, a, b, &R, &G, &B); + RGBtoCMYK(R, G, B, C, M, Y, K); +} + +void KoColor::CMYKtoRGB(int C, int M, int Y, int K, int *R, int *G, int *B) +{ + *R = 255 - (C + K); + *G = 255 - (M + K); + *B = 255 - (Y + K); +} + +void KoColor::CMYKtoHSV(int C, int M, int Y, int K, int *H, int *S, int *V) +{ + int R, G, B; + CMYKtoRGB(C, M, Y, K, &R, &G, &B); + RGBtoHSV(R, G, B, H, S, V); +} + +void KoColor::CMYKtoLAB(int C, int M, int Y, int K, int *L, int *a, int *b) +{ + int R, G, B; + CMYKtoRGB(C, M, Y, K, &R, &G, &B); + RGBtoLAB(R, G, B, L, a, b); +} + +int KoColor::hex2int(QChar c) +{ + if(c.isDigit()) + return c.digitValue(); + else if('A' <= c && c <= 'F') + return c - 'A' + 10; + else if('a' <= c && c <= 'f') + return c - 'a' + 10; + else + return 0; +} + +void KoColor::calcRGB() const +{ + switch(mNative) + { + case csHSV: + HSVtoRGB(mH, mS, mV, &mR, &mG, &mB); + break; + case csLab: + LABtoRGB(mL, ma, mB, &mR, &mG, &mB); + break; + case csCMYK: + CMYKtoRGB(mC, mM, mY, mK, &mR, &mG, &mB); + break; + default: + break; + } + mRGBvalid = true; +} + +void KoColor::calcHSV() const +{ + switch(mNative) + { + case csRGB: + RGBtoHSV(mR, mG, mB, &mH, &mS, &mV); + break; + case csLab: + LABtoHSV(mL, ma, mB, &mH, &mS, &mV); + break; + case csCMYK: + CMYKtoHSV(mC, mM, mY, mK, &mH, &mS, &mV); + break; + default: + break; + } + mHSVvalid = true; +} + +void KoColor::calcCMYK() const +{ + switch(mNative) + { + case csRGB: + RGBtoCMYK(mR, mG, mB, &mC, &mM, &mY, &mK); + break; + case csLab: + LABtoCMYK(mL, ma, mB, &mC, &mM, &mY, &mK); + break; + case csHSV: + HSVtoCMYK(mH, mS, mV, &mC, &mM, &mY, &mK); + break; + default: + break; + } + mCMYKvalid = true; +} + +void KoColor::calcLAB() const +{ + switch(mNative) + { + case csRGB: + RGBtoLAB(mR, mG, mB, &mL, &ma, &mB); + break; + case csHSV: + HSVtoLAB(mH, mS, mV, &mL, &ma, &mB); + break; + case csCMYK: + CMYKtoLAB(mC, mM, mY, mK, &mL, &ma, &mB); + break; + default: + break; + } + mLABvalid = true; +} + +void KoColor::rgbChanged() const +{ + mRGBvalid = true; + mHSVvalid = false; + mCMYKvalid = false; + mLABvalid = false; +} + +void KoColor::hsvChanged() const +{ + mRGBvalid = false; + mHSVvalid = true; + mCMYKvalid = false; + mLABvalid = false; +} + +void KoColor::cmykChanged() const +{ + mRGBvalid = false; + mHSVvalid = false; + mCMYKvalid = true; + mLABvalid = false; +} + +void KoColor::labChanged() const +{ + mRGBvalid = false; + mHSVvalid = false; + mCMYKvalid = false; + mLABvalid = true; +} diff --git a/lib/kopainter/koColor.h b/lib/kopainter/koColor.h new file mode 100644 index 00000000..f955754f --- /dev/null +++ b/lib/kopainter/koColor.h @@ -0,0 +1,217 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_color_h__ +#define __ko_color_h__ + +#include <qcolor.h> +#include <koffice_export.h> +class KOPAINTER_EXPORT KoColor +{ +public: + enum cSpace{ csIndexed, csRGB, csHSV, csCMYK, csLab }; + + KoColor(); + KoColor(int a, int b, int c, cSpace m = csRGB); + KoColor(int c, int m, int y, int k); + KoColor(const QString &name); + KoColor(const QColor &c); + + cSpace native() const {return mNative; } + + int R() const; + int G() const; + int B() const; + int H() const; + int S() const; + int V() const; + int L() const; + int a() const; + int b() const; + int C() const; + int M() const; + int Y() const; + int K() const; + + void rgb(int *R, int *G, int *B) const; + void hsv(int *H, int *S, int *V) const; + void lab(int *L, int *a, int *b) const; + void cmyk(int *C, int *M, int *Y, int *K) const; + QString name() const; + QColor color() const; + + void setRGB(int R, int G, int B); + void setHSV(int H, int S, int V); + void setLab(int L, int a, int b); + void setCMYK(int C, int M, int Y, int K); + void setNamedColor(const QString &name); + void setColor(const QColor &c); + + static void RGBtoHSV(int R, int G, int B, int *H, int *S, int *V); + static void RGBtoLAB(int R, int G, int B, int *L, int *a, int *b); + static void RGBtoCMYK(int R, int G, int B, int *C, int *M, int *Y, int *K); + + static void HSVtoRGB(int H, int S, int V, int *R, int *G, int *B); + static void HSVtoLAB(int H, int S, int V, int *L, int *a, int *b); + static void HSVtoCMYK(int H, int S, int V, int *C, int *M, int *Y, int*K); + + static void LABtoRGB(int L, int a, int b, int *R, int *G, int *B); + static void LABtoHSV(int L, int a, int b, int *H, int *S, int *V); + static void LABtoCMYK(int L, int a, int b, int *C, int *M, int *Y, int*K); + + static void CMYKtoRGB(int C, int M, int Y, int K, int *R, int *G, int *B); + static void CMYKtoHSV(int C, int M, int Y, int K, int *H, int *S, int *V); + static void CMYKtoLAB(int C, int M, int Y, int K, int *L, int *a, int *b); + + static const KoColor black(); + static const KoColor white(); + static const KoColor gray(); + static const KoColor lightGray(); + static const KoColor darkGray(); + static const KoColor red(); + static const KoColor darkRed(); + static const KoColor green(); + static const KoColor darkGreen(); + static const KoColor blue(); + static const KoColor darkBlue(); + static const KoColor cyan(); + static const KoColor darkCyan(); + static const KoColor magenta(); + static const KoColor darkMagenta(); + static const KoColor yellow(); + static const KoColor darkYellow(); + +protected: + int hex2int(QChar c); + + void calcRGB() const; + void calcHSV() const; + void calcCMYK() const; + void calcLAB() const; + + void rgbChanged() const; + void hsvChanged() const; + void cmykChanged() const; + void labChanged() const; + +private: + /* + * Mutable to make it possible for const objects to transform the native cModel + * in functions like KoColor::rgb(...) to the requested. + */ + mutable int mR, mG, mB; // RGB + mutable int mC, mM, mY, mK; // CMYK + mutable int mH, mS, mV; // HSV + mutable int mL, ma, mb; // LAB + + mutable bool mRGBvalid; + mutable bool mHSVvalid; + mutable bool mCMYKvalid; + mutable bool mLABvalid; + + cSpace mNative; +}; + +inline const KoColor KoColor::white() +{ + return KoColor(255, 255, 255, csRGB); +} + +inline const KoColor KoColor::black() +{ + return KoColor(0, 0, 0, csRGB); +} + +inline const KoColor KoColor::gray() +{ + return KoColor(160, 160, 164, csRGB); +} + +inline const KoColor KoColor::lightGray() +{ + return KoColor(192, 192, 192, csRGB); +} + +inline const KoColor KoColor::darkGray() +{ + return KoColor(128, 128, 128, csRGB); +} + +inline const KoColor KoColor::red() +{ + return KoColor(255, 0, 0, csRGB); +} + +inline const KoColor KoColor::darkRed() +{ + return KoColor(128, 0, 0, csRGB); +} + +inline const KoColor KoColor::green() +{ + return KoColor(0, 255, 0, csRGB); +} + +inline const KoColor KoColor::darkGreen() +{ + return KoColor(0, 128, 0, csRGB); +} + +inline const KoColor KoColor::blue() +{ + return KoColor(0, 0, 255, csRGB); +} + +inline const KoColor KoColor::darkBlue() +{ + return KoColor(0, 0, 128, csRGB); +} + +inline const KoColor KoColor::cyan() +{ + return KoColor(0, 255, 255, csRGB); +} + +inline const KoColor KoColor::darkCyan() +{ + return KoColor(0, 128, 128, csRGB); +} + +inline const KoColor KoColor::magenta() +{ + return KoColor(255, 0, 255, csRGB); +} + +inline const KoColor KoColor::darkMagenta() +{ + return KoColor(128, 0, 128, csRGB); +} + +inline const KoColor KoColor::yellow() +{ + return KoColor(255, 255, 0, csRGB); +} + +inline const KoColor KoColor::darkYellow() +{ + return KoColor(128, 128, 0, csRGB); +} + +#endif diff --git a/lib/kopainter/koColorChooser.cc b/lib/kopainter/koColorChooser.cc new file mode 100644 index 00000000..e321123a --- /dev/null +++ b/lib/kopainter/koColorChooser.cc @@ -0,0 +1,675 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "koColorChooser.h" + +#include <qcolor.h> +#include <qlayout.h> +#include <qspinbox.h> +#include <qtabwidget.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kcolordialog.h> +#include <ktabctl.h> +#include <koFrameButton.h> +#include <koColorSlider.h> + +KoColorChooser::KoColorChooser(QWidget *parent, const char *name) : QWidget(parent, name) +{ + m_current = 0; + m_tab = new QTabWidget(this, "KoColorChooser tab"); + mGrid = new QGridLayout(this, 3, 5); + mRGBWidget = new RGBWidget(m_tab); + m_current = mRGBWidget; + m_tab -> addTab(mRGBWidget, "RGB"); + mHSVWidget = new HSVWidget(m_tab); + m_tab -> addTab(mHSVWidget, "HSV"); +#if 0 + mCMYKWidget = new QWidget(m_tab); + m_tab -> addTab(mCMYKWidget, "CMYK"); + mLABWidget = new LABWidget(m_tab); + m_tab -> addTab(mLABWidget, "LAB"); +#endif + mGreyWidget = new GreyWidget(m_tab); + m_tab -> addTab(mGreyWidget, i18n("Gray")); + mColorSelector = new KHSSelector(this); + mColorSelector->setFixedHeight(20); + mGrid->addMultiCellWidget(m_tab, 0, 1, 0, 4); + mGrid->addMultiCellWidget(mColorSelector, 2, 2, 0, 4); + connect(mRGBWidget, SIGNAL(colorChanged(const KoColor &)), this, SLOT(childColorChanged(const KoColor &))); + connect(mHSVWidget, SIGNAL(colorChanged(const KoColor &)), this, SLOT(childColorChanged(const KoColor &))); +// connect(mLABWidget, SIGNAL(colorChanged(const KoColor &)), this, SLOT(childColorChanged(const KoColor &))); + connect(mGreyWidget, SIGNAL(colorChanged(const KoColor &)), this, SLOT(childColorChanged(const KoColor &))); + connect(mColorSelector, SIGNAL(valueChanged(int, int)), this, SLOT(slotChangeXY(int, int))); + connect(m_tab, SIGNAL(currentChanged(QWidget*)), this, SLOT(slotCurrentChanged(QWidget*))); + slotChangeColor(KoColor::black()); +} + +void KoColorChooser::slotCurrentChanged(QWidget *current) +{ + m_current = static_cast<ColorWidget*>(current); + m_current -> slotChangeColor(mColor); +} + +void KoColorChooser::slotChangeXY(int h, int s) +{ + KoColor c(h, s, 192, KoColor::csHSV); + + m_current -> slotChangeColor(c); +} + +void KoColorChooser::slotChangeColor(const QColor &c) +{ + slotChangeColor(KoColor(c)); +} + +void KoColorChooser::childColorChanged(const KoColor& c) +{ + mColor.setRGB(c.R(), c.G(), c.B()); + emit colorChanged(mColor); +} + +void KoColorChooser::slotChangeColor(const KoColor &c) +{ + mColor = c; + m_current -> slotChangeColor(mColor); + mColorSelector->setValues(c.H(), c.S()); +} + +/* RGBWidget */ +RGBWidget::RGBWidget(QWidget *parent) : ColorWidget(parent) +{ + QGridLayout *mGrid = new QGridLayout(this, 4, 5); + + mColorPatch = new KColorPatch(this); + + /* setup color sliders */ + mRSlider = new KoColorSlider(this); + mRSlider->setMaximumHeight(20); + mRSlider->slotSetRange(0, 255); + + mGSlider = new KoColorSlider(this); + mGSlider->setMaximumHeight(20); + mGSlider->slotSetRange(0, 255); + + mBSlider = new KoColorSlider(this); + mBSlider->setMaximumHeight(20); + mBSlider->slotSetRange(0, 255); + + /* setup slider labels */ + mRLabel = new QLabel("R", this); + mRLabel->setFixedWidth(16); + mRLabel->setFixedHeight(20); + mGLabel = new QLabel("G", this); + mGLabel->setFixedWidth(16); + mGLabel->setFixedHeight(20); + mBLabel = new QLabel("B", this); + mBLabel->setFixedWidth(16); + mBLabel->setFixedHeight(20); + + /* setup spin box */ + mRIn = new QSpinBox(0, 255, 1, this); + mRIn->setFixedWidth(42); + mRIn->setFixedHeight(20); + mGIn = new QSpinBox(0, 255, 1, this); + mGIn->setFixedWidth(42); + mGIn->setFixedHeight(20); + mBIn = new QSpinBox(0, 255, 1, this); + mBIn->setFixedWidth(42); + mBIn->setFixedHeight(20); + + mGrid->addMultiCellWidget(mColorPatch, 0, 4, 0, 0); + mGrid->addWidget(mRLabel, 1, 1); + mGrid->addWidget(mGLabel, 2, 1); + mGrid->addWidget(mBLabel, 3, 1); + mGrid->addMultiCellWidget(mRSlider, 1, 1, 2, 3); + mGrid->addMultiCellWidget(mGSlider, 2, 2, 2, 3); + mGrid->addMultiCellWidget(mBSlider, 3, 3, 2, 3); + mGrid->addWidget(mRIn, 1, 4); + mGrid->addWidget(mGIn, 2, 4); + mGrid->addWidget(mBIn, 3, 4); + + connect(mColorPatch, SIGNAL(colorChanged(const QColor &)), this, SLOT(slotPatchChanged(const QColor &))); + + /* connect color sliders */ + connect(mRSlider, SIGNAL(valueChanged(int)), this, SLOT(slotRSliderChanged(int))); + connect(mGSlider, SIGNAL(valueChanged(int)), this, SLOT(slotGSliderChanged(int))); + connect(mBSlider, SIGNAL(valueChanged(int)), this, SLOT(slotBSliderChanged(int))); + + /* connect spin box */ + connect(mRIn, SIGNAL(valueChanged(int)), this, SLOT(slotRInChanged(int))); + connect(mGIn, SIGNAL(valueChanged(int)), this, SLOT(slotGInChanged(int))); + connect(mBIn, SIGNAL(valueChanged(int)), this, SLOT(slotBInChanged(int))); +} + +ColorWidget::ColorWidget(QWidget *parent) : QWidget(parent) +{ +} + +ColorWidget::~ColorWidget() +{ +} + +void ColorWidget::slotChangeColor(const KoColor& c) +{ + mColor.setRGB(c.R(), c.G(), c.B()); + slotRefreshColor(); +} + +void ColorWidget::slotChangeColor(const QColor& c) +{ + mColor.setColor(c); + slotRefreshColor(); +} + +void RGBWidget::slotRefreshColor() +{ + int r = mColor.R(); + int g = mColor.G(); + int b = mColor.B(); + + mRSlider->slotSetColor1(QColor(0, g, b)); + mRSlider->slotSetColor2(QColor(255, g, b)); + mRSlider->slotSetValue(r); + mRIn->setValue(r); + + mGSlider->slotSetColor1(QColor(r, 0, b)); + mGSlider->slotSetColor2(QColor(r, 255, b)); + mGSlider->slotSetValue(g); + mGIn->setValue(g); + + mBSlider->slotSetColor1(QColor(r, g, 0)); + mBSlider->slotSetColor2(QColor(r, g, 255)); + mBSlider->slotSetValue(b); + mBIn->setValue(b); + mColorPatch -> setColor(mColor.color()); +} + +void RGBWidget::slotRSliderChanged(int r) +{ + int g = mColor.G(); + int b = mColor.B(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotGSliderChanged(int g) +{ + int r = mColor.R(); + int b = mColor.B(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor( r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotBSliderChanged(int b) +{ + int r = mColor.R(); + int g = mColor.G(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotRInChanged(int r) +{ + int g = mColor.G(); + int b = mColor.B(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotGInChanged(int g) +{ + int r = mColor.R(); + int b = mColor.B(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotBInChanged(int b) +{ + int r = mColor.R(); + int g = mColor.G(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +void RGBWidget::slotPatchChanged(const QColor& clr) +{ + int r = clr.red(); + int g = clr.green(); + int b = clr.blue(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(KoColor(r, g, b, KoColor::csRGB)); +} + +/* HSVWidget */ + +HSVWidget::HSVWidget(QWidget *parent): ColorWidget(parent) +{ + QGridLayout *mGrid = new QGridLayout(this, 3, 3); + + mColorPatch = new KColorPatch(this); + + /* setup color sliders */ + mHSlider = new KoColorSlider(this); + mHSlider->setMaximumHeight(20); + mHSlider->slotSetRange(0, 359); + + mSSlider = new KoColorSlider(this); + mSSlider->setMaximumHeight(20); + mSSlider->slotSetRange(0, 255); + + mVSlider = new KoColorSlider(this); + mVSlider->setMaximumHeight(20); + mVSlider->slotSetRange(0, 255); + + /* setup slider labels */ + mHLabel = new QLabel("H", this); + mHLabel->setFixedWidth(16); + mHLabel->setFixedHeight(20); + mSLabel = new QLabel("S", this); + mSLabel->setFixedWidth(16); + mSLabel->setFixedHeight(20); + mVLabel = new QLabel("V", this); + mVLabel->setFixedWidth(16); + mVLabel->setFixedHeight(20); + + /* setup spin box */ + mHIn = new QSpinBox(0, 359, 1, this); + mHIn->setFixedWidth(42); + mHIn->setFixedHeight(20); + mSIn = new QSpinBox(0, 255, 1, this); + mSIn->setFixedWidth(42); + mSIn->setFixedHeight(20); + mVIn = new QSpinBox(0, 255, 1, this); + mVIn->setFixedWidth(42); + mVIn->setFixedHeight(20); + + mGrid->addMultiCellWidget(mColorPatch, 0, 4, 0, 0); + mGrid->addWidget(mHLabel, 1, 1); + mGrid->addWidget(mSLabel, 2, 1); + mGrid->addWidget(mVLabel, 3, 1); + mGrid->addMultiCellWidget(mHSlider, 1, 1, 2, 3); + mGrid->addMultiCellWidget(mSSlider, 2, 2, 2, 3); + mGrid->addMultiCellWidget(mVSlider, 3, 3, 2, 3); + mGrid->addWidget(mHIn, 1, 4); + mGrid->addWidget(mSIn, 2, 4); + mGrid->addWidget(mVIn, 3, 4); + + connect(mColorPatch, SIGNAL(colorChanged(const QColor &)), this, SLOT(slotPatchChanged(const QColor &))); + + /* connect color sliders */ + connect(mHSlider, SIGNAL(valueChanged(int)), this, SLOT(slotHSliderChanged(int))); + connect(mSSlider, SIGNAL(valueChanged(int)), this, SLOT(slotSSliderChanged(int))); + connect(mVSlider, SIGNAL(valueChanged(int)), this, SLOT(slotVSliderChanged(int))); + + /* connect spin box */ + connect(mHIn, SIGNAL(valueChanged(int)), this, SLOT(slotHInChanged(int))); + connect(mSIn, SIGNAL(valueChanged(int)), this, SLOT(slotSInChanged(int))); + connect(mVIn, SIGNAL(valueChanged(int)), this, SLOT(slotVInChanged(int))); +} + +void HSVWidget::slotRefreshColor() +{ + int h = mColor.H(); + int s = mColor.S(); + int v = mColor.V(); + + mHSlider->slotSetColor1(KoColor(0, s, v, KoColor::csHSV).color()); + mHSlider->slotSetColor2(KoColor(359, s, v, KoColor::csHSV).color()); + mHSlider->slotSetValue(h); + mHIn->setValue(h); + + mSSlider->slotSetColor1(KoColor(h, 0, v, KoColor::csHSV).color()); + mSSlider->slotSetColor2(KoColor(h, 255, v, KoColor::csHSV).color()); + mSSlider->slotSetValue(s); + mSIn->setValue(s); + + mVSlider->slotSetColor1(KoColor(h, s, 0, KoColor::csHSV).color()); + mVSlider->slotSetColor2(KoColor(h, s, 255, KoColor::csHSV).color()); + mVSlider->slotSetValue(v); + mVIn->setValue(v); + mColorPatch -> setColor(mColor.color()); +} + +void HSVWidget::slotHSliderChanged(int h) +{ + int v = mColor.V(); + int s = mColor.S(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotSSliderChanged(int s) +{ + int h = mColor.H(); + int v = mColor.V(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotVSliderChanged(int v) +{ + int h = mColor.H(); + int s = mColor.S(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotHInChanged(int h) +{ + int s = mColor.S(); + int v = mColor.V(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotSInChanged(int s) +{ + int h = mColor.H(); + int v = mColor.V(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotVInChanged(int v) +{ + int h = mColor.H(); + int s = mColor.S(); + + mColor.setHSV(h, s, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void HSVWidget::slotPatchChanged(const QColor& clr) +{ + int r = clr.red(); + int g = clr.green(); + int b = clr.blue(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +/* GreyWidget */ + +GreyWidget::GreyWidget(QWidget *parent): ColorWidget(parent) +{ + QGridLayout *mGrid = new QGridLayout(this, 3, 3); + + mColorPatch = new KColorPatch(this); + + /* setup slider */ + mVSlider = new KoColorSlider(this); + mVSlider->setMaximumHeight(20); + mVSlider->slotSetRange(0, 255); + mVSlider->slotSetColor1(QColor(255, 255, 255)); + mVSlider->slotSetColor2(QColor(0, 0, 0)); + + /* setup slider label */ + mVLabel = new QLabel("K", this); + mVLabel->setFixedWidth(18); + mVLabel->setFixedHeight(20); + + /* setup spin box */ + mVIn = new QSpinBox(0, 255, 1, this); + mVIn->setFixedWidth(42); + mVIn->setFixedHeight(20); + + mGrid->addMultiCellWidget(mColorPatch, 0, 4, 0, 0); + mGrid->addWidget(mVLabel, 1, 1); + mGrid->addMultiCellWidget(mVSlider, 1, 1, 2, 3); + mGrid->addWidget(mVIn, 1, 4); + + connect(mColorPatch, SIGNAL(colorChanged(const QColor &)), this, SLOT(slotPatchChanged(const QColor &))); + + /* connect color slider */ + connect(mVSlider, SIGNAL(valueChanged(int)), this, SLOT(slotVSliderChanged(int))); + + /* connect spin box */ + connect(mVIn, SIGNAL(valueChanged(int)), mVSlider, SLOT(slotSetValue(int))); +} + +void GreyWidget::slotRefreshColor() +{ + double v = mColor.R() + mColor.G() + mColor.B(); + v /= 3.0; + v = 255.0 - v; + mVIn->setValue(static_cast<int>(v)); + mVSlider->slotSetValue(static_cast<int>(v)); + mColorPatch -> setColor(mColor.color()); +} + +void GreyWidget::slotVSliderChanged(int v) +{ + v = 255 - v; + + mColor.setRGB(v, v, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void GreyWidget::slotVInChanged(int v) +{ + v = 255 - v; + + mColor.setRGB(v, v, v); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void GreyWidget::slotPatchChanged(const QColor& clr) +{ + int gray = qGray(clr.red(), clr.green(), clr.blue()); + + mColor.setRGB(gray, gray, gray); + slotRefreshColor(); + emit colorChanged(mColor); +} + +LABWidget::LABWidget(QWidget *parent) : ColorWidget(parent) +{ + QGridLayout *mGrid = new QGridLayout(this, 4, 5); + + mColorPatch = new KColorPatch(this); + + /* setup color sliders */ + mLSlider = new KoColorSlider(this); + mLSlider->setMaximumHeight(20); + mLSlider->slotSetRange(0, 255); + + mASlider = new KoColorSlider(this); + mASlider->setMaximumHeight(20); + mASlider->slotSetRange(0, 255); + + mBSlider = new KoColorSlider(this); + mBSlider->setMaximumHeight(20); + mBSlider->slotSetRange(0, 255); + + /* setup slider labels */ + mLLabel = new QLabel("L", this); + mLLabel->setFixedWidth(16); + mLLabel->setFixedHeight(20); + mALabel = new QLabel("A", this); + mALabel->setFixedWidth(16); + mALabel->setFixedHeight(20); + mBLabel = new QLabel("B", this); + mBLabel->setFixedWidth(16); + mBLabel->setFixedHeight(20); + + /* setup spin box */ + mLIn = new QSpinBox(0, 255, 1, this); + mLIn->setFixedWidth(42); + mLIn->setFixedHeight(20); + mAIn = new QSpinBox(0, 255, 1, this); + mAIn->setFixedWidth(42); + mAIn->setFixedHeight(20); + mBIn = new QSpinBox(0, 255, 1, this); + mBIn->setFixedWidth(42); + mBIn->setFixedHeight(20); + + mGrid->addMultiCellWidget(mColorPatch, 0, 4, 0, 0); + mGrid->addWidget(mLLabel, 1, 1); + mGrid->addWidget(mALabel, 2, 1); + mGrid->addWidget(mBLabel, 3, 1); + mGrid->addMultiCellWidget(mLSlider, 1, 1, 2, 3); + mGrid->addMultiCellWidget(mASlider, 2, 2, 2, 3); + mGrid->addMultiCellWidget(mBSlider, 3, 3, 2, 3); + mGrid->addWidget(mLIn, 1, 4); + mGrid->addWidget(mAIn, 2, 4); + mGrid->addWidget(mBIn, 3, 4); + + connect(mColorPatch, SIGNAL(colorChanged(const QColor &)), this, SLOT(slotPatchChanged(const QColor &))); + + /* connect color sliders */ + connect(mLSlider, SIGNAL(valueChanged(int)), this, SLOT(slotLSliderChanged(int))); + connect(mASlider, SIGNAL(valueChanged(int)), this, SLOT(slotASliderChanged(int))); + connect(mBSlider, SIGNAL(valueChanged(int)), this, SLOT(slotBSliderChanged(int))); + + /* connect spin box */ + connect(mLIn, SIGNAL(valueChanged(int)), this, SLOT(slotLInChanged(int))); + connect(mAIn, SIGNAL(valueChanged(int)), this, SLOT(slotAInChanged(int))); + connect(mBIn, SIGNAL(valueChanged(int)), this, SLOT(slotBInChanged(int))); +} + +void LABWidget::slotRefreshColor() +{ + int l = mColor.L(); + int a = mColor.a(); + int b = mColor.b(); + + mLSlider->slotSetColor1(KoColor(0, a, b, KoColor::csLab).color()); + mLSlider->slotSetColor2(KoColor(255, a, b, KoColor::csLab).color()); + mLSlider->slotSetValue(l); + mLIn->setValue(l); + + mASlider->slotSetColor1(KoColor(l, 0, b, KoColor::csLab).color()); + mASlider->slotSetColor2(KoColor(l, 255, b, KoColor::csLab).color()); + mASlider->slotSetValue(a); + mAIn->setValue(a); + + mBSlider->slotSetColor1(KoColor(l, a, 0, KoColor::csLab).color()); + mBSlider->slotSetColor2(KoColor(l, a, 255, KoColor::csLab).color()); + mBSlider->slotSetValue(b); + mBIn->setValue(b); + mColorPatch -> setColor(mColor.color()); +} + +void LABWidget::slotLSliderChanged(int l) +{ + int a = mColor.a(); + int b = mColor.b(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); + +} + +void LABWidget::slotASliderChanged(int a) +{ + int l = mColor.L(); + int b = mColor.b(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void LABWidget::slotBSliderChanged(int b) +{ + int l = mColor.L(); + int a = mColor.a(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void LABWidget::slotLInChanged(int l) +{ + int a = mColor.a(); + int b = mColor.b(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void LABWidget::slotAInChanged(int a) +{ + int l = mColor.L(); + int b = mColor.b(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void LABWidget::slotBInChanged(int b) +{ + int l = mColor.L(); + int a = mColor.a(); + + mColor.setLab(l, a, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +void LABWidget::slotPatchChanged(const QColor& clr) +{ + int r = clr.red(); + int g = clr.green(); + int b = clr.blue(); + + mColor.setRGB(r, g, b); + slotRefreshColor(); + emit colorChanged(mColor); +} + +#include "koColorChooser.moc" + diff --git a/lib/kopainter/koColorChooser.h b/lib/kopainter/koColorChooser.h new file mode 100644 index 00000000..3dddcb8b --- /dev/null +++ b/lib/kopainter/koColorChooser.h @@ -0,0 +1,236 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_ColorChooser_h__ +#define __ko_ColorChooser_h__ + +#include <qwidget.h> +#include "koColor.h" + +class KoFrameButton; +class QGridLayout; +class QTabWidget; +class RGBWidget; +class HSVWidget; +class CMYKWidget; +class LABWidget; +class GreyWidget; +class KoColor; +class KoColorSlider; +class QLabel; +class QSpinBox; +class KHSSelector; +class KColorPatch; +class ColorWidget; + +class KoColorChooser : public QWidget +{ + Q_OBJECT +public: + KoColorChooser(QWidget *parent = 0L, const char *name = 0L); + + const KoColor &color() const {return mColor; } + +public slots: + void slotChangeColor(const KoColor &c); + void slotChangeColor(const QColor &c); + +signals: + void colorChanged(const KoColor &c); + +protected slots: + void slotChangeXY(int h, int s); + +private slots: + void childColorChanged(const KoColor& c); + void slotCurrentChanged(QWidget *current); + +private: + ColorWidget *m_current; + KoColor mColor; + QTabWidget *m_tab; + QGridLayout *mGrid; + KoFrameButton *btnRGB; + KoFrameButton *btnHSV; + KoFrameButton *btnCMYK; + KoFrameButton *btnLAB; + KoFrameButton *btnGrey; + RGBWidget *mRGBWidget; + HSVWidget *mHSVWidget; + QWidget *mCMYKWidget; + LABWidget *mLABWidget; + GreyWidget *mGreyWidget; + KHSSelector *mColorSelector; +}; + +class ColorWidget : public QWidget { + Q_OBJECT + +public: + ColorWidget(QWidget *parent = 0); + virtual ~ColorWidget(); + +public slots: + virtual void slotChangeColor(const KoColor& c); + virtual void slotChangeColor(const QColor& c); + virtual void slotRefreshColor() = 0; + +protected: + KoColor mColor; +}; + +class RGBWidget : public ColorWidget +{ + Q_OBJECT +public: + RGBWidget(QWidget *parent = 0L); + virtual ~RGBWidget() {} + +public slots: + virtual void slotRefreshColor(); + +protected slots: + void slotRSliderChanged(int r); + void slotGSliderChanged(int g); + void slotBSliderChanged(int b); + + void slotRInChanged(int r); + void slotGInChanged(int g); + void slotBInChanged(int b); + + void slotPatchChanged(const QColor& clr); + +signals: + void colorChanged(const KoColor &c); + +private: + KoColorSlider *mRSlider; + KoColorSlider *mGSlider; + KoColorSlider *mBSlider; + QLabel *mRLabel; + QLabel *mGLabel; + QLabel *mBLabel; + QSpinBox *mRIn; + QSpinBox *mGIn; + QSpinBox *mBIn; + KColorPatch *mColorPatch; +}; + +class HSVWidget : public ColorWidget +{ + Q_OBJECT +public: + HSVWidget(QWidget *parent = 0L); + virtual ~HSVWidget() {} + +public slots: + virtual void slotRefreshColor(); + +protected slots: + void slotHSliderChanged(int h); + void slotSSliderChanged(int s); + void slotVSliderChanged(int v); + + void slotHInChanged(int h); + void slotSInChanged(int s); + void slotVInChanged(int v); + + void slotPatchChanged(const QColor& clr); + +signals: + void colorChanged(const KoColor &c); + +private: + KoColorSlider *mHSlider; + KoColorSlider *mSSlider; + KoColorSlider *mVSlider; + QLabel *mHLabel; + QLabel *mSLabel; + QLabel *mVLabel; + QSpinBox *mHIn; + QSpinBox *mSIn; + QSpinBox *mVIn; + KColorPatch *mColorPatch; +}; + +class GreyWidget : public ColorWidget +{ + Q_OBJECT +public: + GreyWidget(QWidget *parent = 0L); + virtual ~GreyWidget() {} + +public slots: + virtual void slotRefreshColor(); + +protected slots: + void slotVSliderChanged(int v); + void slotVInChanged(int v); + void slotPatchChanged(const QColor& clr); + +signals: + void colorChanged(const KoColor &c); + +protected: + KoColorSlider *mVSlider; + QLabel *mVLabel; + QSpinBox *mVIn; + KColorPatch *mColorPatch; +}; + +class LABWidget : public ColorWidget +{ + Q_OBJECT +public: + LABWidget(QWidget *parent = 0L); + virtual ~LABWidget() {} + +public slots: + virtual void slotRefreshColor(); + +protected slots: + void slotLSliderChanged(int l); + void slotASliderChanged(int a); + void slotBSliderChanged(int b); + + void slotLInChanged(int l); + void slotAInChanged(int a); + void slotBInChanged(int b); + + void slotPatchChanged(const QColor& clr); + +signals: + void colorChanged(const KoColor &c); + +private: + KoColorSlider *mLSlider; + KoColorSlider *mASlider; + KoColorSlider *mBSlider; + QLabel *mLLabel; + QLabel *mALabel; + QLabel *mBLabel; + QSpinBox *mLIn; + QSpinBox *mAIn; + QSpinBox *mBIn; + KColorPatch *mColorPatch; +}; + +#endif + diff --git a/lib/kopainter/koColorSlider.cc b/lib/kopainter/koColorSlider.cc new file mode 100644 index 00000000..08c8020a --- /dev/null +++ b/lib/kopainter/koColorSlider.cc @@ -0,0 +1,365 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "koColorSlider.h" + +#include <qpainter.h> +#include <qcursor.h> +#include <qpen.h> + +#include <kdebug.h> +#include <kpixmapeffect.h> + +KoColorFrame::KoColorFrame(QWidget *parent): +QFrame(parent) +{ + setFrameStyle(Panel | Sunken); + setBackgroundMode(NoBackground); + + /* default values */ + mC1 = QColor(0, 0, 0); + mC2 = QColor(255, 255, 255); + + mColorChanged = false; + mPixChanged = false; + mDragging = false; +} + +const QColor KoColorFrame::colorAt(const QPoint &p) +{ + if(mPixChanged) + { + mImage = mPixmap.convertToImage(); + mPixChanged = false; + } + + if(p.x() >= mPixmap.width() || p.y() >= mPixmap.height()) + return QColor(255,255,255); + + return QColor(mImage.pixel(p.x(), p.y())); +} + +void KoColorFrame::slotSetColor1(const QColor &c) +{ + mC1 = c; + mColorChanged = true; + mPixChanged = true; + repaint(); +} + +void KoColorFrame::slotSetColor2(const QColor &c) +{ + mC2 = c; + mColorChanged = true; + repaint(); +} + +void KoColorFrame::drawContents(QPainter *p) +{ + QRect r = contentsRect(); + + if((mPixmap.size() != r.size()) || mColorChanged) + { + mPixmap.resize(r.width() + 1, r.height() + 1); + KPixmapEffect::gradient(mPixmap, mC1, mC2, KPixmapEffect::HorizontalGradient); + mColorChanged = false; + mPixChanged = true; + } + + p->drawPixmap(r.left(), r.top(), mPixmap); +} + +void KoColorFrame::mousePressEvent(QMouseEvent *e) +{ + if(e->button() & LeftButton) + { + emit clicked(e->pos()); + + mDragging = true; + QPoint pos = QPoint(e->pos().x() - contentsRect().left(), e->pos().y() - contentsRect().top()); + + if(pos.x() < 0) + pos.setX(0); + else if(pos.x() >= contentsRect().width()) + pos.setX(contentsRect().width()-1); + + if(pos.y() < 0) + pos.setY(0); + else if(pos.y() >= contentsRect().height()) + pos.setY(contentsRect().height()-1); + + QColor c = colorAt(pos); + emit colorSelected(c); + } + else + QFrame::mousePressEvent(e); +} + +void KoColorFrame::mouseReleaseEvent(QMouseEvent *e) +{ + if(e->button() & LeftButton) + mDragging = false; + else + QFrame::mouseReleaseEvent(e); +} + +void KoColorFrame::mouseMoveEvent(QMouseEvent *e) +{ + if(mDragging) + { + bool set = false; + int x = e->pos().x(); + int y = e->pos().y(); + + int left = contentsRect().left(); + int right = contentsRect().left() + contentsRect().width(); + int top = contentsRect().top(); + int bottom = contentsRect().top() + contentsRect().height(); + + if(x < left) + { + x = left; + set = true; + } + else if(x > right) + { + x = right; + set = true; + } + if(y < top) + { + y = top; + set = true; + } + else if(y > bottom) + { + y = bottom; + set = true; + } + +// if(set) +// QCursor::setPos(mapToGlobal(QPoint(x,y))); + + QPoint pos = QPoint(x - contentsRect().left(), y - contentsRect().top()); + + QColor c = colorAt(pos); + emit colorSelected(c); + } + else + QFrame::mouseMoveEvent(e); +} + +/***********************************************************************************/ + +KoSliderWidget::KoSliderWidget(QWidget *parent): +QWidget(parent) +{ + mDragging = false; + setFixedHeight(6); + setFixedWidth(11); +} + +void KoSliderWidget::paintEvent(QPaintEvent *) +{ + QPainter p; + QPen pen(black, 1); + p.begin(this); + + p.setPen(pen); + p.drawLine(0, 5, 5, 0); + p.drawLine(10, 5, 5, 0); + p.drawLine(0, 5, 10, 5); + p.end(); +} + +void KoSliderWidget::mousePressEvent(QMouseEvent *e) +{ + if(e->button() & LeftButton) + { + mPos = e->pos(); + mDragging = true; + } + else + QWidget::mousePressEvent(e); +} + +void KoSliderWidget::mouseReleaseEvent(QMouseEvent *e) +{ + if(e->button() & LeftButton) + mDragging = false; + else + QWidget::mouseReleaseEvent(e); +} + +void KoSliderWidget::mouseMoveEvent(QMouseEvent *e) +{ + if(mDragging) + { + QWidget *p = parentWidget(); + + if(!p) + return; + + QPoint newPos = p->mapFromGlobal(QCursor::pos()) - mPos; + + /* don't drag vertically */ + newPos.setY(pos().y()); + + if(newPos.x() < 0) + newPos.setX(0); + if(newPos.x() > p->width() - width()) + newPos.setX(p->width() - width()); + + move(newPos); + emit positionChanged(newPos.x()); + } + else + QWidget::mouseMoveEvent(e); +} + +/***********************************************************************************/ + +KoColorSlider::KoColorSlider(QWidget *parent): +QWidget(parent) +{ + mColorFrame = new KoColorFrame(this); + mSlider = new KoSliderWidget(this); + + mMin = 0; + mMax = 255; + mValue = 0; + + connect(mSlider, SIGNAL(positionChanged(int)), this, SLOT(slotSliderMoved(int))); + connect(mColorFrame, SIGNAL(clicked(const QPoint &)), this, SLOT(slotFrameClicked(const QPoint &))); +} + +KoColorSlider::~KoColorSlider() +{ + delete mColorFrame; + delete mSlider; +} + +int KoColorSlider::minValue() +{ + return mMin; +} + +int KoColorSlider::maxValue() +{ + return mMax; +} + +void KoColorSlider::slotSetRange(int min, int max) +{ + if(min >= max) + return; + + mMin = min; + mMax = max; +} + +void KoColorSlider::resizeEvent(QResizeEvent *e) +{ + QWidget::resizeEvent(e); + // m_pSlider->width()/2 * 2 seems stupid but is not because for example + // m_pSlider->width() == 11 I get 10. + mColorFrame->setGeometry(mSlider->width() / 2, 0, width() - mSlider->width() / 2 * 2, height() - mSlider->height()); + slotSetValue(mValue); +} + +void KoColorSlider::slotSetColor1(const QColor &c) +{ + mColorFrame->slotSetColor1(c); +} + +void KoColorSlider::slotSetColor2(const QColor &c) +{ + mColorFrame->slotSetColor2(c); +} + +void KoColorSlider::slotSetValue(int value) +{ + if(value < mMin) + value = mMin; + if(value > mMax) + value = mMax; + + mValue = value; + + int range = mMax - mMin; + float v = value; + if(mMin < 0) + v += -mMin; + + float factor = v / range; + int x = static_cast<int>(factor * mColorFrame->contentsRect().width()); + + mSlider->move(QPoint(x, height() - mSlider->height())); +} + +void KoColorSlider::slotSliderMoved(int x) +{ + if(x < 0) + x = 0; + if(x > mColorFrame->contentsRect().width()) + x = mColorFrame->contentsRect().width(); + + float factor = x; + factor /= mColorFrame->contentsRect().width(); + int range = mMax - mMin; + + mValue = static_cast<int>(factor * range); + + emit valueChanged(mValue); + emit colorSelected(mColorFrame->colorAt(QPoint(x, mColorFrame->contentsRect().height()/2))); +} + +void KoColorSlider::slotFrameClicked(const QPoint &p) +{ + QPoint local = mColorFrame->mapToParent(p); + QPoint pos = QPoint(local.x() - mSlider->width() / 2, height() - mSlider->height()); + + if(pos.x() < 0) + pos.setX(0); + else if(pos.x() > width() - mSlider->width()) + pos.setX(width() - mSlider->width()); + + mSlider->move(pos); + slotSliderMoved(pos.x()); +} + +void KoColorSlider::mousePressEvent(QMouseEvent *e) +{ + if(e->button() & LeftButton) + { + QPoint pos = QPoint(e->pos().x() - mSlider->width() / 2, height() - mSlider->height()); + + if(pos.x() < 0) + pos.setX(0); + else if(pos.x() > width() - mSlider->width()) + pos.setX(width() - mSlider->width()); + + mSlider->move(pos); + slotSliderMoved(pos.x()); + } + else + QWidget::mousePressEvent(e); +} + +#include "koColorSlider.moc" diff --git a/lib/kopainter/koColorSlider.h b/lib/kopainter/koColorSlider.h new file mode 100644 index 00000000..5c520ba8 --- /dev/null +++ b/lib/kopainter/koColorSlider.h @@ -0,0 +1,119 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_ColorSlider_h__ +#define __ko_ColorSlider_h__ + +#include <qframe.h> +#include <qpoint.h> +#include <qimage.h> +#include <qwidget.h> +#include <kpixmap.h> +#include <koffice_export.h> +class SliderWidget; + +class KOPAINTER_EXPORT KoColorFrame : public QFrame +{ + Q_OBJECT +public: + KoColorFrame(QWidget *parent = 0L); + + const QColor colorAt(const QPoint &p); + +protected: + void drawContents(QPainter *p); + void mousePressEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + +public slots: + void slotSetColor1(const QColor &c); + void slotSetColor2(const QColor &c); + +signals: + void clicked(const QPoint &p); + void colorSelected(const QColor &c); + +protected: + QColor mC1; + QColor mC2; + KPixmap mPixmap; + QImage mImage; + bool mColorChanged; + bool mPixChanged; + bool mDragging; +}; + +class KOPAINTER_EXPORT KoSliderWidget : public QWidget +{ + Q_OBJECT +public: + KoSliderWidget(QWidget *parent = 0L); + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void mouseMoveEvent(QMouseEvent *e); + void paintEvent(QPaintEvent *); + +signals: + void positionChanged(int); + +protected: + bool mDragging; + QPoint mPos; +}; + +class KOPAINTER_EXPORT KoColorSlider : public QWidget +{ + Q_OBJECT +public: + KoColorSlider(QWidget *parent = 0L); + virtual ~KoColorSlider(); + + int minValue(); + int maxValue(); + +protected: + void resizeEvent(QResizeEvent *); + void mousePressEvent(QMouseEvent *); + +public slots: + void slotSetColor1(const QColor &c); + void slotSetColor2(const QColor &c); + + void slotSetValue(int value); + void slotSetRange(int min, int max); + +protected slots: + void slotSliderMoved(int x); + void slotFrameClicked(const QPoint &p); + +signals: + void colorSelected(const QColor &c); + void valueChanged(int value); + +protected: + KoSliderWidget *mSlider; + KoColorFrame *mColorFrame; + int mMin, mMax; + int mValue; +}; + +#endif diff --git a/lib/kopainter/koFrameButton.cc b/lib/kopainter/koFrameButton.cc new file mode 100644 index 00000000..cb752363 --- /dev/null +++ b/lib/kopainter/koFrameButton.cc @@ -0,0 +1,102 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "koFrameButton.h" + +KoFrameButton::KoFrameButton(QWidget *parent, const char *name): +QLabel(parent, name) +{ + setAutoResize(true); + setFrameStyle(Panel | Raised); + setLineWidth(1); + setMaximumHeight(8); + mActive = false; + mToggle = false; +} + +KoFrameButton::KoFrameButton(const QString &text, QWidget *parent, const char *name): +QLabel(parent, name) +{ + setFrameStyle(Panel | Raised); + setLineWidth(1); + setText(text); + setAlignment(AlignHCenter | AlignVCenter); + mActive = false; + mToggle = false; +} + +KoFrameButton::KoFrameButton(const QPixmap &pixmap, QWidget *parent, const char *name): +QLabel(parent, name) +{ + setFrameStyle(Panel | Raised); + setLineWidth(1); + setPixmap(pixmap); + mActive = false; + mToggle = false; +} + +void KoFrameButton::mousePressEvent(QMouseEvent *) +{ + setFrameStyle(Panel | Sunken); +} + +void KoFrameButton::mouseReleaseEvent(QMouseEvent *) +{ + if(mToggle) + { + mActive = !mActive; + if(mActive) + setFrameStyle(Panel | Sunken); + else + setFrameStyle(Panel | Raised); + } + else + setFrameStyle(Panel | Raised); + + emit clicked(); + emit clicked(mText); +} + +void KoFrameButton::setOn(bool v) +{ + if(!mToggle) + return; + + mActive = v; + + if(mActive) + setFrameStyle(Panel | Sunken); + else + setFrameStyle(Panel | Raised); +} + + +void KoFrameButton::setToggleButton(bool v) +{ + mToggle = v; +} + +void KoFrameButton::setText(const QString &t) +{ + mText = t; + QLabel::setText(t); +} + +#include "koFrameButton.moc" diff --git a/lib/kopainter/koFrameButton.h b/lib/kopainter/koFrameButton.h new file mode 100644 index 00000000..c540fd9f --- /dev/null +++ b/lib/kopainter/koFrameButton.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Matthias Elter (me@kde.org) + Copyright (c) 2001 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_framebutton_h__ +#define __ko_framebutton_h__ + +#include <qlabel.h> + +class QPixmap; +class QString; + +class KoFrameButton : public QLabel +{ + Q_OBJECT +public: + KoFrameButton(QWidget *parent = 0, const char *name = 0); + KoFrameButton(const QString &text, QWidget *parent = 0, const char *name = 0); + KoFrameButton(const QPixmap &pixmap, QWidget *parent = 0, const char *name = 0); + + bool isOn() {return mActive; } + void setOn(bool v); + + bool isToggleButton() {return mToggle; } + void setToggleButton(bool v); + + QString text() {return mText; } + virtual void setText(const QString &t); + +signals: + void clicked(); + void clicked(const QString &); + +protected: + void mousePressEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + +private: + bool mActive; + bool mToggle; + QString mText; +}; + +#endif diff --git a/lib/kopainter/koIconChooser.cc b/lib/kopainter/koIconChooser.cc new file mode 100644 index 00000000..57fda8d8 --- /dev/null +++ b/lib/kopainter/koIconChooser.cc @@ -0,0 +1,482 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Carsten Pfeiffer (pfeiffer@kde.org) + Copyright (c) 2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> +#include <koIconChooser.h> +#include <kglobal.h> + +#include <qpainter.h> +#include <qcursor.h> +#include <qapplication.h> +#include <qhbox.h> +#include <qlayout.h> +#include <kdebug.h> + +KoPixmapWidget::KoPixmapWidget(const QPixmap &aPixmap, QWidget *parent, const char *name): +QFrame(parent, name, WType_Popup) +{ + kdDebug() << "Popup created: " << name << "\n"; + setFrameStyle(QFrame::WinPanel | QFrame::Raised); + mPixmap = aPixmap; + int w = mPixmap.width() + 2 * lineWidth(); + int h = mPixmap.height() + 2 * lineWidth(); + resize(w, h); + +} + +KoPixmapWidget::~KoPixmapWidget() +{ +} + +// paint the centered pixmap; don't overpaint the frame +void KoPixmapWidget::paintEvent(QPaintEvent *e) +{ + QFrame::paintEvent(e); + QPainter p(this); + p.setClipRect(e->rect()); + p.drawPixmap(lineWidth(), lineWidth(), mPixmap); +} + + +void KoPixmapWidget::mouseReleaseEvent(QMouseEvent *) +{ + hide(); +} + + +KoIconChooser::KoIconChooser(QSize aIconSize, QWidget *parent, const char *name, bool sort): +QGridView(parent, name) +{ + QGridView::setBackgroundColor(Qt::white); + + mMargin = 2; + setCellWidth(aIconSize.width() + 2 * mMargin); + setCellHeight(aIconSize.height() + 2 * mMargin); + + mIconList.clear(); + mPixmapWidget = 0L; + mNCols = 0; + mCurRow = 0; + mCurCol = 0; + mItemCount = 0; + mItemWidth = aIconSize.width(); + mItemHeight = aIconSize.height(); + mMouseButtonDown = false; + mDragEnabled = false; + mSort = sort; +} + +KoIconChooser::~KoIconChooser() +{ + mIconList.clear(); + if(mPixmapWidget) + delete mPixmapWidget; +} + +void KoIconChooser::addItem(KoIconItem *item) +{ + Q_INT32 n = mItemCount; + KoIconItem *current = currentItem(); + + Q_ASSERT(item); + + int i; + + if (mSort) + { + i = sortInsertionIndex(item); + } + else + { + i = mItemCount; + } + + mIconList.insert(i, item); + mItemCount++; + calculateCells(); + + if (mSort) + { + setCurrentItem(current); + updateContents(); + } + else + { + updateCell(n / numCols(), n - (n / numCols()) * numCols()); + } +} + +bool KoIconChooser::removeItem(KoIconItem *item) +{ + int index = mIconList.find(item); + bool ok = mIconList.remove(item); + if( ok ) + { + mItemCount--; + // select same cell as deleted cell, or new last cell if we deleted + // last cell. + setCurrentItem(itemAt(kMin(index, mItemCount - 1))); + calculateCells(); + } + return ok; +} + +void KoIconChooser::clear() +{ + mItemCount = 0; + mIconList.clear(); + calculateCells(); +} + +// return 0L if there is no current item +KoIconItem *KoIconChooser::currentItem() +{ + return itemAt(mCurRow, mCurCol); +} + +// sets the current item to item +// does NOT emit selected() (should it?) +void KoIconChooser::setCurrentItem(KoIconItem *item) +{ + int index = mIconList.find(item); + + // item is available + if(index != -1 && mNCols > 0) + { + int oldRow = mCurRow; + int oldCol = mCurCol; + + mCurRow = index / mNCols; + mCurCol = index % mNCols; + + // repaint the old and the new item + repaintCell(oldRow, oldCol); + repaintCell(mCurRow, mCurCol); + + ensureCellVisible(mCurRow, mCurCol); + } +} + +// eventually select the item, clicked on +void KoIconChooser::mousePressEvent(QMouseEvent *e) +{ + QGridView::mousePressEvent(e); +} + +void KoIconChooser::mouseMoveEvent(QMouseEvent *e) +{ + if(mMouseButtonDown && mDragEnabled ) + { +#if 0 + if(mPixmapWidget) + { + delete mPixmapWidget; + mPixmapWidget = 0L; + } +#endif + if( ( mDragStartPos - e->pos() ).manhattanLength() > QApplication::startDragDistance() ) + startDrag(); + } +} + +void +KoIconChooser::startDrag() +{ + mMouseButtonDown = false; +} + +void KoIconChooser::mouseReleaseEvent(QMouseEvent * e) +{ + mMouseButtonDown = true; + if(e->button() == LeftButton) + { + QPoint p = e->pos(); + mDragStartPos = p; + int x = contentsX() + p.x(); + int y = contentsY() + p.y(); + QSize gridExtent = gridSize(); + + if (x < gridExtent.width() && y < gridExtent.height()) + { + int row = rowAt(y); + int col = columnAt(x); + + KoIconItem *item = itemAt(row, col); + if(item) + { + const QPixmap &pix = item->pixmap(); + if(pix.width() > mItemWidth || pix.height() > mItemHeight) + showFullPixmap(pix, p); + + setCurrentItem(item); + emit selected( item ); + } + } + } +} + +// FIXME: implement keyboard navigation +void KoIconChooser::keyPressEvent(QKeyEvent *e) +{ + QGridView::keyPressEvent(e); +} + +// recalculate the number of items that fit into one row +// set the current item again after calculating the new grid +void KoIconChooser::resizeEvent(QResizeEvent *e) +{ + QGridView::resizeEvent(e); + + KoIconItem *item = currentItem(); + int oldNCols = mNCols; + + if (cellWidth() != 0) + { + mNCols = e -> size().width() / cellWidth(); + } + + if(mNCols != oldNCols) + { + setNumCols(mNCols); + calculateCells(); + setCurrentItem(item); + updateContents(); + } +} + +// paint one cell +// mark the current item and center items smaller than the cellSize +// TODO: scale down big pixmaps and paint the size as text into the pixmap +void KoIconChooser::paintCell(QPainter *p, int row, int col) +{ + KoIconItem *item = itemAt(row, col); + + if(item) + { + const QPixmap &pix = item->pixmap(); + + int x = mMargin; + int y = mMargin; + int pw = pix.width(); + int ph = pix.height(); + int cw = cellWidth(); + int ch = cellHeight(); + + // center small pixmaps + if(pw < mItemWidth) + x = (cw - pw) / 2; + if(ph < mItemHeight) + y = (cw - ph) / 2; + + if((!item->hasValidThumb()) || (pw <= mItemWidth && ph <= mItemHeight)) + p->drawPixmap(x, y, pix, 0, 0, mItemWidth, mItemHeight); + else + { + const QPixmap &thumbpix = item->thumbPixmap(); + x = mMargin; + y = mMargin; + pw = thumbpix.width(); + ph = thumbpix.height(); + cw = cellWidth(); + ch = cellHeight(); + + // center small pixmaps + if(pw < mItemWidth) + x = (cw - pw) / 2; + if(ph < mItemHeight) + y = (cw - ph) / 2; + p->drawPixmap(x, y, thumbpix, 0, 0, mItemWidth, mItemHeight); + } + + // highlight current item + if(row == mCurRow && col == mCurCol) + { + p->setPen(blue); + p->drawRect(0, 0, cw, ch); + } + else + { + p->setPen(gray); + //p->drawRect(0, 0, cw, ch); + p->drawLine(cw-1, 0, cw-1, ch-1); + p->drawLine(0, ch-1, cw-1, ch-1); + } + } + else + { + // empty cell + p->fillRect(0, 0, cellWidth(), cellHeight(), QBrush(Qt::white)); + } +} + +// return the pointer of the item at (row,col) - beware, resizing disturbs +// rows and cols! +// return 0L if item is not found +KoIconItem *KoIconChooser::itemAt(int row, int col) +{ + return itemAt(cellIndex(row, col)); +} + +// return the pointer of the item at position index +// return 0L if item is not found +KoIconItem *KoIconChooser::itemAt(int index) +{ + if(index < 0) + return 0L; + return mIconList.count() > uint(index) ? mIconList.at(index) : 0; +} + +// return the index of a cell, given row and column position +// maps directly to the position in the itemlist +// return -1 on failure +int KoIconChooser::cellIndex(int row, int col) +{ + if(row < 0 || col < 0) + return -1; + else + return((row * mNCols) + col); +} + +// calculate the grid and set the number of rows and columns +// reorder all items approrpriately +void KoIconChooser::calculateCells() +{ + if(mNCols == 0) + return; + bool update = isUpdatesEnabled(); + int rows = mItemCount / mNCols; + setUpdatesEnabled(false); + if((rows * mNCols) < mItemCount) + rows++; + setNumRows(rows); + setUpdatesEnabled(update); + updateContents(); +} + +// show the full pixmap of a large item in an extra widget +void KoIconChooser::showFullPixmap(const QPixmap &pix, const QPoint &/*p*/) +{ + //delete mPixmapWidget; + mPixmapWidget = new KoPixmapWidget(pix, this); + + // center widget under mouse cursor + QPoint p = QCursor::pos(); + int w = mPixmapWidget->width(); + int h = mPixmapWidget->height(); + mPixmapWidget->move(p.x() - w / 2, p.y() - h / 2); + mPixmapWidget->show(); +} + +int KoIconChooser::sortInsertionIndex(const KoIconItem *item) +{ + int index = 0; + + if (!mIconList.isEmpty()) + { + // Binary insertion + int first = 0; + int last = mIconList.count() - 1; + + while (first != last) + { + int middle = (first + last) / 2; + + if (item -> compare(mIconList.at(middle)) < 0) + { + last = middle - 1; + + if (last < first) + { + last = first; + } + } + else + { + first = middle + 1; + + if (first > last) + { + first = last; + } + } + } + + if (item -> compare(mIconList.at(first)) < 0) + { + index = first; + } + else + { + index = first + 1; + } + } + + return index; +} + +KoPatternChooser::KoPatternChooser( const QPtrList<KoIconItem> &list, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + // only serves as beautifier for the iconchooser + //frame = new QHBox( this ); + //frame->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + chooser = new KoIconChooser( QSize(30,30), this, "pattern chooser" ); + + QObject::connect( chooser, SIGNAL(selected( KoIconItem * ) ), + this, SIGNAL( selected( KoIconItem * ))); + + QPtrListIterator<KoIconItem> itr( list ); + for( itr.toFirst(); itr.current(); ++itr ) + chooser->addItem( itr.current() ); + + QVBoxLayout *mainLayout = new QVBoxLayout( this, 1, -1, "main layout" ); + mainLayout->addWidget( chooser, 10 ); +} + + +KoPatternChooser::~KoPatternChooser() +{ + delete chooser; + //delete frame; +} + +// set the active pattern in the chooser - does NOT emit selected() (should it?) +void KoPatternChooser::setCurrentPattern( KoIconItem *pattern ) +{ + chooser->setCurrentItem( pattern ); +} + +void KoPatternChooser::addPattern( KoIconItem *pattern ) +{ + chooser->addItem( pattern ); +} + +// return the active pattern +KoIconItem *KoPatternChooser::currentPattern() +{ + return chooser->currentItem(); +} + +void KoPatternChooser::removePattern( KoIconItem *pattern ) +{ + chooser->removeItem( pattern ); +} + +#include "koIconChooser.moc" diff --git a/lib/kopainter/koIconChooser.h b/lib/kopainter/koIconChooser.h new file mode 100644 index 00000000..5beb25a0 --- /dev/null +++ b/lib/kopainter/koIconChooser.h @@ -0,0 +1,145 @@ +/* This file is part of the KDE project + Copyright (c) 1999 Carsten Pfeiffer (pfeiffer@kde.org) + Copyright (c) 2002 Igor Jansen (rm@kde.org) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __ko_iconchooser_h__ +#define __ko_iconchooser_h__ + +#include <qgridview.h> +#include <qptrlist.h> +#include <qpixmap.h> +#include <koffice_export.h> + +class KoIconItem +{ +public: + KoIconItem() {} + virtual ~KoIconItem() {} + + bool hasValidPixmap() {return validPixmap; } + bool validPixmap; + bool hasValidThumb() {return validThumb; } + bool validThumb; + + virtual int spacing() const {return 0; } + virtual void setSpacing(int) {} + virtual QPixmap &pixmap() const = 0; + virtual QPixmap &thumbPixmap() const = 0; + // Return -1 if this is less than other, 0 if equal, 1 if greater than. + virtual int compare(const KoIconItem */*other*/) const { return 0; } +}; + +class KoPixmapWidget : public QFrame +{ +public: + KoPixmapWidget(const QPixmap &aPixmap, QWidget *parent = 0L, const char *name = 0L); + ~KoPixmapWidget(); + +protected: + void paintEvent(QPaintEvent *e); + void mouseReleaseEvent( QMouseEvent *e); + +private: + QPixmap mPixmap; +}; + +class KOPAINTER_EXPORT KoIconChooser: public QGridView +{ + Q_OBJECT +public: + // To make the items sorted, set 'sort' to true and override KoIconItem::compare(). + KoIconChooser(QSize iconSize, QWidget *parent = 0L, const char *name = 0L, bool sort = false); + virtual ~KoIconChooser(); + + bool autoDelete() const {return mIconList.autoDelete(); } + void setAutoDelete(bool b) {mIconList.setAutoDelete(b); } + + void addItem(KoIconItem *item); + bool removeItem(KoIconItem *item); + void clear(); + + KoIconItem *currentItem(); + void setCurrentItem(KoIconItem *item); + + void setDragEnabled(bool allow) { mDragEnabled = allow; } + bool dragEnabled() const { return mDragEnabled; } + + KoIconItem *itemAt(int row, int col); + KoIconItem *itemAt(int index); + +signals: + void selected(KoIconItem *item); + +protected: + void keyPressEvent(QKeyEvent *e); + void mousePressEvent( QMouseEvent *e); + void mouseReleaseEvent( QMouseEvent *e); + void mouseMoveEvent( QMouseEvent *e); + void resizeEvent(QResizeEvent *e); + void paintCell(QPainter *p, int row, int col); + virtual void startDrag(); + +private: + int cellIndex(int row, int col); + void calculateCells(); + void showFullPixmap(const QPixmap &pix, const QPoint &p); + int sortInsertionIndex(const KoIconItem *item); + +private: + QPtrList<KoIconItem> mIconList; + KoPixmapWidget *mPixmapWidget; + int mItemWidth; + int mItemHeight; + int mItemCount; + int mNCols; + int mCurRow; + int mCurCol; + int mMargin; + QPoint mDragStartPos; + bool mMouseButtonDown; + bool mDragEnabled; + bool mSort; +}; + +// This is a first attempt at a pattern chooser widget abstraction which is at least +// useful for two applications(karbon and krita). It is really a light version of +// kis_patternchooser. (Rob) +class KOPAINTER_EXPORT KoPatternChooser : public QWidget +{ + Q_OBJECT +public: + KoPatternChooser( const QPtrList<KoIconItem> &list, QWidget *parent, const char *name = 0 ); + ~KoPatternChooser(); + + KoIconItem *currentPattern(); + void setCurrentPattern( KoIconItem * ); + +public slots: + void addPattern( KoIconItem * ); + void removePattern( KoIconItem * ); + +private: + KoIconChooser *chooser; + +signals: + void selected( KoIconItem * ); +}; + + +#endif diff --git a/lib/kopainter/ko_cmyk_widget.cc b/lib/kopainter/ko_cmyk_widget.cc new file mode 100644 index 00000000..86b20ad9 --- /dev/null +++ b/lib/kopainter/ko_cmyk_widget.cc @@ -0,0 +1,403 @@ +/* + * This file is part of KOffice + * + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * Copyright (c) 2005 Tim Beaulen (tbscope@gmail.com) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "ko_cmyk_widget.h" + +#include <qlayout.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qtooltip.h> +#include <qcolor.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +#include <koFrameButton.h> +#include <koColorSlider.h> +#include <kcolordialog.h> +#include <kdualcolorbutton.h> + +KoCMYKWidget::KoCMYKWidget(QWidget *parent, const char *name) : super(parent, name) +{ + m_ColorButton = new KDualColorButton(this); + m_ColorButton -> setFixedSize(m_ColorButton->sizeHint()); + QGridLayout *mGrid = new QGridLayout(this, 4, 5, 5, 2); + + /* setup color sliders */ + mCSlider = new KoColorSlider(this); + mCSlider->setMaximumHeight(20); + mCSlider->slotSetRange(0, 255); + mCSlider->setFocusPolicy( QWidget::ClickFocus ); + + mMSlider = new KoColorSlider(this); + mMSlider->setMaximumHeight(20); + mMSlider->slotSetRange(0, 255); + mMSlider->setFocusPolicy( QWidget::ClickFocus ); + + mYSlider = new KoColorSlider(this); + mYSlider->setMaximumHeight(20); + mYSlider->slotSetRange(0, 255); + mYSlider->setFocusPolicy( QWidget::ClickFocus ); + + mKSlider = new KoColorSlider(this); + mKSlider->setMaximumHeight(20); + mKSlider->slotSetRange(0, 255); + mKSlider->setFocusPolicy( QWidget::ClickFocus ); + + /* setup slider labels */ + mCLabel = new QLabel("C", this); + mCLabel->setFixedWidth(12); + mCLabel->setFixedHeight(20); + mMLabel = new QLabel("M", this); + mMLabel->setFixedWidth(12); + mMLabel->setFixedHeight(20); + mYLabel = new QLabel("Y", this); + mYLabel->setFixedWidth(12); + mYLabel->setFixedHeight(20); + mKLabel = new QLabel("K", this); + mKLabel->setFixedWidth(12); + mKLabel->setFixedHeight(20); + + /* setup spin box */ + mCIn = new QSpinBox(0, 255, 1, this); + mCIn->setFixedWidth(50); + mCIn->setFixedHeight(20); + mCIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mCIn, i18n( "Cyan" ) ); + + mMIn = new QSpinBox(0, 255, 1, this); + mMIn->setFixedWidth(50); + mMIn->setFixedHeight(20); + mMIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mMIn, i18n( "Magenta" ) ); + + mYIn = new QSpinBox(0, 255, 1, this); + mYIn->setFixedWidth(50); + mYIn->setFixedHeight(20); + mYIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mYIn, i18n( "Yellow" ) ); + + mKIn = new QSpinBox(0, 255, 1, this); + mKIn->setFixedWidth(50); + mKIn->setFixedHeight(20); + mKIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mKIn, i18n( "Black" ) ); + + mGrid->addMultiCellWidget(m_ColorButton, 0, 4, 0, 0, Qt::AlignTop); + mGrid->addWidget(mCLabel, 0, 1); + mGrid->addWidget(mMLabel, 1, 1); + mGrid->addWidget(mYLabel, 2, 1); + mGrid->addWidget(mKLabel, 3, 1); + mGrid->addMultiCellWidget(mCSlider, 0, 0, 2, 3); + mGrid->addMultiCellWidget(mMSlider, 1, 1, 2, 3); + mGrid->addMultiCellWidget(mYSlider, 2, 2, 2, 3); + mGrid->addMultiCellWidget(mKSlider, 3, 3, 2, 3); + mGrid->addWidget(mCIn, 0, 4); + mGrid->addWidget(mMIn, 1, 4); + mGrid->addWidget(mYIn, 2, 4); + mGrid->addWidget(mKIn, 3, 4); + + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + /* connect color sliders */ + connect(mCSlider, SIGNAL(valueChanged(int)), this, SLOT(slotCChanged(int))); + connect(mMSlider, SIGNAL(valueChanged(int)), this, SLOT(slotMChanged(int))); + connect(mYSlider, SIGNAL(valueChanged(int)), this, SLOT(slotYChanged(int))); + connect(mKSlider, SIGNAL(valueChanged(int)), this, SLOT(slotKChanged(int))); + + /* connect spin box */ + connect(mCIn, SIGNAL(valueChanged(int)), this, SLOT(slotCChanged(int))); + connect(mMIn, SIGNAL(valueChanged(int)), this, SLOT(slotMChanged(int))); + connect(mYIn, SIGNAL(valueChanged(int)), this, SLOT(slotYChanged(int))); + connect(mKIn, SIGNAL(valueChanged(int)), this, SLOT(slotKChanged(int))); +} + +void KoCMYKWidget::slotCChanged(int c) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground){ + CMYKColor col = RgbToCmyk(m_fgColor); + col.C = c / 255.0; + m_fgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Foreground); + emit sigFgColorChanged(m_fgColor); + } + else{ + CMYKColor col = RgbToCmyk(m_bgColor); + col.C = c / 255.0; + m_bgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Background); + emit sigBgColorChanged(m_bgColor); + } +} + +void KoCMYKWidget::slotMChanged(int m) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground){ + CMYKColor col = RgbToCmyk(m_fgColor); + col.M = m / 255.0; + m_fgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Foreground); + emit sigFgColorChanged(m_fgColor); + } + else{ + CMYKColor col = RgbToCmyk(m_bgColor); + col.M = m / 255.0; + m_bgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Background); + emit sigBgColorChanged(m_bgColor); + } +} + +void KoCMYKWidget::slotYChanged(int y) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground){ + CMYKColor col = RgbToCmyk(m_fgColor); + col.Y = y / 255.0; + m_fgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Foreground); + emit sigFgColorChanged(m_fgColor); + } + else{ + CMYKColor col = RgbToCmyk(m_bgColor); + col.Y = y / 255.0; + m_bgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Background); + emit sigBgColorChanged(m_bgColor); + } +} + +void KoCMYKWidget::slotKChanged(int k) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground){ + CMYKColor col = RgbToCmyk(m_fgColor); + col.K = k / 255.0; + m_fgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Foreground); + emit sigFgColorChanged(m_fgColor); + } + else{ + CMYKColor col = RgbToCmyk(m_bgColor); + col.K = k / 255.0; + m_bgColor = CmykToRgb(col); + m_ColorButton->setCurrent(KDualColorButton::Background); + emit sigBgColorChanged(m_bgColor); + } +} + +void KoCMYKWidget::setFgColor(const QColor & c) +{ + update(c, m_bgColor); +} + +void KoCMYKWidget::setBgColor(const QColor & c) +{ + update(m_fgColor, c); +} + +void KoCMYKWidget::update(const QColor fgColor, const QColor bgColor) +{ + m_fgColor = fgColor; + m_bgColor = bgColor; + + QColor color = (m_ColorButton->current() == KDualColorButton::Foreground)? m_fgColor : m_bgColor; + + CMYKColor col = RgbToCmyk(color); + + disconnect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + disconnect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + m_ColorButton->setForeground( m_fgColor ); + m_ColorButton->setBackground( m_bgColor ); + + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + mCSlider->blockSignals(true); + mCIn->blockSignals(true); + mMSlider->blockSignals(true); + mMIn->blockSignals(true); + mYSlider->blockSignals(true); + mYIn->blockSignals(true); + mKSlider->blockSignals(true); + mKIn->blockSignals(true); + + CMYKColor minC = col; + minC.C = 0.0; + CMYKColor maxC = col; + maxC.C = 1.0; + + mCSlider->slotSetColor1(CmykToRgb(minC)); + mCSlider->slotSetColor2(CmykToRgb(maxC)); + mCSlider->slotSetValue(int(col.C * 255)); + mCIn->setValue(int(col.C * 255)); + + CMYKColor minM = col; + minM.M = 0.0; + CMYKColor maxM = col; + maxM.M = 1.0; + + mMSlider->slotSetColor1(CmykToRgb(minM)); + mMSlider->slotSetColor2(CmykToRgb(maxM)); + mMSlider->slotSetValue(int(col.M * 255)); + mMIn->setValue(int(col.M * 255)); + + CMYKColor minY = col; + minY.Y = 0.0; + CMYKColor maxY = col; + maxY.Y = 1.0; + + mYSlider->slotSetColor1(CmykToRgb(minY)); + mYSlider->slotSetColor2(CmykToRgb(maxY)); + mYSlider->slotSetValue(int(col.Y * 255)); + mYIn->setValue(int(col.Y * 255)); + + CMYKColor minK = col; + minK.K = 0.0; + CMYKColor maxK = col; + maxK.K = 1.0; + + mKSlider->slotSetColor1(CmykToRgb(minK)); + mKSlider->slotSetColor2(CmykToRgb(maxK)); + mKSlider->slotSetValue(int(col.K * 255)); + mKIn->setValue(int(col.K * 255)); + + mCSlider->blockSignals(false); + mCIn->blockSignals(false); + mMSlider->blockSignals(false); + mMIn->blockSignals(false); + mYSlider->blockSignals(false); + mYIn->blockSignals(false); + mKSlider->blockSignals(false); + mKIn->blockSignals(false); +} + +void KoCMYKWidget::slotFGColorSelected(const QColor& c) +{ + m_fgColor = QColor(c); + emit sigFgColorChanged(m_fgColor); +} + +void KoCMYKWidget::slotBGColorSelected(const QColor& c) +{ + m_bgColor = QColor(c); + emit sigBgColorChanged(m_bgColor); +} + +CMYKColor KoCMYKWidget::RgbToCmyk(const QColor& col) +{ + kdDebug() << "--[ KoCMYKWidget::RgbToCmyk ]--------------------------------------" << endl; + kdDebug() << endl; + + // RGB to CMY + float r = col.red() / 255.0; + float g = col.green() / 255.0; + float b = col.blue() / 255.0; + + kdDebug() << "float r = col.red() / 255.0;" << endl; + kdDebug() << " r = " << col.red() << " / 255.0 = " << r << endl; + kdDebug() << "float g = col.green() / 255.0;" << endl; + kdDebug() << " g = " << col.green() << " / 255.0 = " << g << endl; + kdDebug() << "float b = col.blue() / 255.0;" << endl; + kdDebug() << " b = " << col.blue() << " / 255.0 = " << b << endl; + kdDebug() << endl; + + float ac = 1.0 - r; + float am = 1.0 - g; + float ay = 1.0 - b; + + kdDebug() << "float ac = 1.0 - r;" << endl; + kdDebug() << " ac = 1.0 - " << r << " = " << ac << endl; + kdDebug() << "float am = 1.0 - g;" << endl; + kdDebug() << " am = 1.0 - " << g << " = " << am << endl; + kdDebug() << "float ay = 1.0 - b;" << endl; + kdDebug() << " ay = 1.0 - " << b << " = " << ay << endl; + kdDebug() << endl; + + // CMY to CMYK + float c = 0.0; + float m = 0.0; + float y = 0.0; + float k = 0.0; + + if ((r == 0.0) && (g == 0.0) && (b == 0.0)) + { + kdDebug() << "r = g = b = 0.0: Therefor k = 1.0" << endl; + k = 1.0; + } + else + { + kdDebug() << "r = g = b != 0.0: Therefor k = min(ac,am,ay)" << endl; + + if (kMin(ac,am) == ac) + k = kMin(ac,ay); + else + k = kMin(am,ay); + + c = (ac - k) / (1.0 - k); + m = (am - k) / (1.0 - k); + y = (ay - k) / (1.0 - k); + } + + kdDebug() << "float k = " << k << endl; + kdDebug() << endl; + + kdDebug() << "float c = (ac - k) / (1.0 - k);" << endl; + kdDebug() << " c = (" << ac << " - " << k << ") / (1.0 - " << k << ") = " << c << endl; + kdDebug() << "float m = (am - k) / (1.0 - k);" << endl; + kdDebug() << " m = (" << am << " - " << k << ") / (1.0 - " << k << ") = " << m << endl; + kdDebug() << "float y = (ay - k) / (1.0 - k);" << endl; + kdDebug() << " y = (" << ay << " - " << k << ") / (1.0 - " << k << ") = " << y << endl; + kdDebug() << endl; + + CMYKColor color; + color.C = c; + color.M = m; + color.Y = y; + color.K = k; + + kdDebug() << "===================================================================" << endl; + + return color; +} + +QColor KoCMYKWidget::CmykToRgb(const CMYKColor& c) +{ + // CMYK to CMY + float ac = kMin(1.0, c.C * (1.0 - c.K) + c.K); + float am = kMin(1.0, c.M * (1.0 - c.K) + c.K); + float ay = kMin(1.0, c.Y * (1.0 - c.K) + c.K); + + // CMY to RGB + int r = int((1.0 - ac) * 255.0); + int g = int((1.0 - am) * 255.0); + int b = int((1.0 - ay) * 255.0); + + QColor color; + color.setRgb(r,g,b); + + return color; +} + +#include "ko_cmyk_widget.moc" diff --git a/lib/kopainter/ko_cmyk_widget.h b/lib/kopainter/ko_cmyk_widget.h new file mode 100644 index 00000000..5cb00b7a --- /dev/null +++ b/lib/kopainter/ko_cmyk_widget.h @@ -0,0 +1,116 @@ +/* This file is part of the KDE project + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * Copyright (c) 2005 Tim Beaulen (tbscope@gmail.com) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KO_CMYK_WIDGET_H +#define KO_CMYK_WIDGET_H + +#include "qwidget.h" + +#include <koffice_export.h> + +class KoFrameButton; +class QGridLayout; +class QColor; +class KoColorSlider; +class QLabel; +class QSpinBox; +class KDualColorButton; + +struct CMYKColor +{ + float C; + float M; + float Y; + float K; +}; + +class KoCMYKWidget + : public QWidget +{ + Q_OBJECT + typedef QWidget super; + +public: + KoCMYKWidget(QWidget *parent = 0L, const char *name = 0); + virtual ~KoCMYKWidget() {} + +public slots: + /** + * Set the current color to c. Do not emit the color changed signals + */ + virtual void setFgColor(const QColor & c); + virtual void setBgColor(const QColor & c); + +signals: + + /** + * Emitted when the current color is changed. + */ + virtual void sigFgColorChanged(const QColor & c); + virtual void sigBgColorChanged(const QColor & c); + + +protected slots: + + virtual void slotCChanged(int c); + virtual void slotMChanged(int m); + virtual void slotYChanged(int y); + virtual void slotKChanged(int k); + + void slotFGColorSelected(const QColor& c); + void slotBGColorSelected(const QColor& c); + +private: + + void update(const QColor fgColor, const QColor); + + CMYKColor RgbToCmyk(const QColor& col); + QColor CmykToRgb(const CMYKColor& c); + +private: + + KoColorSlider *mCSlider; + KoColorSlider *mMSlider; + KoColorSlider *mYSlider; + KoColorSlider *mKSlider; + QLabel *mCLabel; + QLabel *mMLabel; + QLabel *mYLabel; + QLabel *mKLabel; + QSpinBox *mCIn; + QSpinBox *mMIn; + QSpinBox *mYIn; + QSpinBox *mKIn; + KDualColorButton *m_ColorButton; + + float m_fgC; + float m_fgM; + float m_fgY; + float m_fgK; + + float m_bgC; + float m_bgM; + float m_bgY; + float m_bgK; + + QColor m_fgColor; + QColor m_bgColor; +}; + +#endif diff --git a/lib/kopainter/ko_color_wheel.cc b/lib/kopainter/ko_color_wheel.cc new file mode 100644 index 00000000..a7a77a44 --- /dev/null +++ b/lib/kopainter/ko_color_wheel.cc @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include <math.h> + +#include <qpoint.h> +#include <qpainter.h> +#include <qimage.h> + +#include <kdebug.h> +#include "ko_color_wheel.h" + +#define pi 3.14159265 + +KoColorWheel::KoColorWheel( QWidget *parent, const char *name ): KXYSelector( parent, name ) +{ + +} + +void KoColorWheel::resizeEvent( QResizeEvent * ) +{ + drawWheel(&m_pixmap); + setRange( 0, 0, contentsRect().width(), contentsRect().height() ); +} + +void KoColorWheel::drawContents( QPainter *painter ) +{ + painter->drawPixmap( contentsRect().x(), contentsRect().y(), m_pixmap ); +} + +void KoColorWheel::drawWheel( QPixmap *pixmap ) +{ + int size = QMIN(contentsRect().width(), contentsRect().height()); + QPoint center(size/2, size/2); + + QImage image( size, size, 32 ); + image.fill(colorGroup ().background().pixel()); + + QColor col; + int a, b, h, s; + uint *p; + + for ( a = size-1; a >= 0; a-- ) + { + p = (uint*) image.scanLine( size - a - 1 ); + for( b = 0; b < size; b++ ) + { + s = (int)(sqrt(pow(a-center.y(), 2) + pow(b-center.x(), 2))/(size/2)*255); + if(s<=255) + { + h = (int)(atan2( b-center.x(), a-center.y())* 180.0 / pi); + if(h<0) h += 360; + if(h>360) h -= 360; + + col.setHsv( h, s, 210 ); + *p = col.rgb(); + } + p++; + } + } + pixmap->convertFromImage( image ); +} + +void KoColorWheel::mousePressEvent( QMouseEvent *e ) +{ + int size = QMIN(contentsRect().width(), contentsRect().height()); + QPoint center(size/2, size/2); + + int xVal, yVal; + valuesFromPosition( e->pos().x() - 2, e->pos().y() - 2, xVal, yVal ); + setValues( xVal, yVal ); + + int h, s; + + s = (int)(sqrt(pow(yVal-center.y(), 2) + pow(xVal-center.x(), 2))/(size/2)*255); + if(s>255) s = 255; + + h = (int)(atan2( xVal-center.x(), yVal-center.y())* 180.0 / pi); + if(h<0) h += 360; + if(h>360) h -= 360; + + m_color.setHSV( h, s, 255); + emit valueChanged(m_color); +} + +void KoColorWheel::mouseMoveEvent( QMouseEvent *e ) +{ + mousePressEvent( e ); +} + +void KoColorWheel::slotSetValue(const KoColor& c) +{ + int size = QMIN(contentsRect().width(), contentsRect().height()); + QPoint center(size/2, size/2); + + int xVal, yVal; + xVal = (int)(sin(c.H() * pi /180) * c.S() / 255 * (size/2) + center.x()); + yVal = (int)(cos(c.H() * pi /180) * c.S() / 255 * (size/2) + center.y()); + setValues( xVal, yVal ); +} + +#include "ko_color_wheel.moc" diff --git a/lib/kopainter/ko_color_wheel.h b/lib/kopainter/ko_color_wheel.h new file mode 100644 index 00000000..c084a564 --- /dev/null +++ b/lib/kopainter/ko_color_wheel.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KO_COLORWHEEL_H +#define KO_COLORWHEEL_H + +#include <qpixmap.h> + +#include <kselect.h> +#include <koColor.h> + +class QPainter; + +class KoColorWheel : public KXYSelector +{ + Q_OBJECT + +public: + KoColorWheel( QWidget *parent=0, const char *name=0 ); + +signals: + void valueChanged(const KoColor& c); + +public slots: + virtual void slotSetValue(const KoColor& c); + +protected: + virtual void drawWheel( QPixmap *pixmap ); + virtual void resizeEvent( QResizeEvent * ); + virtual void mousePressEvent( QMouseEvent *e ); + virtual void mouseMoveEvent( QMouseEvent *e ); + virtual void drawContents( QPainter *painter ); + +private: + QPixmap m_pixmap; + KoColor m_color; +}; + +#endif diff --git a/lib/kopainter/ko_gray_widget.cc b/lib/kopainter/ko_gray_widget.cc new file mode 100644 index 00000000..957ee917 --- /dev/null +++ b/lib/kopainter/ko_gray_widget.cc @@ -0,0 +1,157 @@ +/* + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "ko_gray_widget.h" + +#include <qlayout.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qcolor.h> + +#include <kdebug.h> + +#include <koFrameButton.h> +#include <koColorSlider.h> +#include <kcolordialog.h> + +KoGrayWidget::KoGrayWidget(QWidget *parent, const char *name) : super(parent, name) +{ + m_ColorButton = new KDualColorButton(this); + Q_CHECK_PTR(m_ColorButton); + + m_ColorButton -> setFixedSize(m_ColorButton->sizeHint()); + QGridLayout *mGrid = new QGridLayout(this, 3, 5, 5, 2); + + /* setup color sliders */ + mSlider = new KoColorSlider(this); + mSlider->setFocusPolicy( QWidget::ClickFocus ); + mSlider->setMaximumHeight(20); + mSlider->slotSetRange(0, 255); + mSlider->slotSetColor1(QColor(255, 255, 255)); + mSlider->slotSetColor2(QColor(0, 0, 0)); + + /* setup slider labels */ + mLabel = new QLabel("K:", this); + mLabel->setFixedWidth(12); + mLabel->setFixedHeight(20); + + /* setup spin box */ + mIn = new QSpinBox(0, 255, 1, this); + mIn->setFixedWidth(50); + mIn->setFixedHeight(20); + mIn->setFocusPolicy( QWidget::ClickFocus ); + + mGrid->addMultiCellWidget(m_ColorButton, 0, 3, 0, 0, Qt::AlignTop); + mGrid->addWidget(mLabel, 0, 1); + mGrid->addMultiCellWidget(mSlider, 0, 0, 2, 3); + mGrid->addWidget(mIn, 0, 4); + + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + /* connect color slider */ + connect(mSlider, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); + + /* connect spin box */ + connect(mIn, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); +} + +void KoGrayWidget::slotChanged(int v) +{ + v = 255 - v; + + if (m_ColorButton->current() == KDualColorButton::Foreground){ + slotFGColorSelected( QColor( v, v, v)); + } + else{ + slotBGColorSelected( QColor( v, v, v)); + } +} + +void KoGrayWidget::setFgColor(const QColor & c) +{ + blockSignals(true); + slotFGColorSelected(c); + blockSignals(false); +} + +void KoGrayWidget::setBgColor(const QColor & c) +{ + blockSignals(true); + slotBGColorSelected(c); + blockSignals(false); +} + +void KoGrayWidget::update(const QColor & fgColor, const QColor & bgColor) +{ + + m_fgColor = fgColor; + m_bgColor = bgColor; + + QColor color = (m_ColorButton->current() == KDualColorButton::Foreground)? m_fgColor : m_bgColor; + + disconnect(mSlider, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); + disconnect(mIn, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); + + mIn->blockSignals(true); + mSlider->blockSignals(true); + double v = color.red() + color.green() + color.blue(); + v /= 3.0; + v = 255.0 - v; + mIn->setValue(static_cast<int>(v)); + mSlider->slotSetValue(static_cast<int>(v)); + mIn->blockSignals(false); + mSlider->blockSignals(false); + + connect(mSlider, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); + connect(mIn, SIGNAL(valueChanged(int)), this, SLOT(slotChanged(int))); +} + +void KoGrayWidget::slotFGColorSelected(const QColor& c) +{ + m_fgColor = c; + + disconnect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + m_ColorButton->setForeground( m_fgColor ); + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + + emit sigFgColorChanged(m_fgColor); +} + +void KoGrayWidget::slotBGColorSelected(const QColor& c) +{ + m_bgColor = c; + + disconnect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + m_ColorButton->setBackground( m_bgColor ); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + emit sigBgColorChanged(m_bgColor); +} + +void KoGrayWidget::currentChanged(KDualColorButton::DualColor s) +{ + if(s == KDualColorButton::Foreground) + slotFGColorSelected(m_ColorButton->currentColor()); + else + slotBGColorSelected(m_ColorButton->currentColor()); +} + +#include "ko_gray_widget.moc" diff --git a/lib/kopainter/ko_gray_widget.h b/lib/kopainter/ko_gray_widget.h new file mode 100644 index 00000000..818932c5 --- /dev/null +++ b/lib/kopainter/ko_gray_widget.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KO_GRAY_WIDGET_H +#define KO_GRAY_WIDGET_H + +#include "qwidget.h" + +#include <koffice_export.h> +#include <kdualcolorbutton.h> + +class KoFrameButton; +class QGridLayout; +class QColor; +class KoColorSlider; +class QLabel; +class QSpinBox; +class KDualColorButton; + +class KoGrayWidget + : public QWidget +{ + Q_OBJECT + typedef QWidget super; + +public: + KoGrayWidget(QWidget *parent = 0L, const char *name = 0); + virtual ~KoGrayWidget() {} + +public slots: + /** + * Set the current color to c. Do not emit the color changed signals + */ + virtual void setFgColor(const QColor & c); + virtual void setBgColor(const QColor & c); + +signals: + + /** + * Emitted when the current color is changed. + */ + virtual void sigFgColorChanged(const QColor & c); + virtual void sigBgColorChanged(const QColor & c); + +protected slots: + virtual void slotChanged(int v); + + void slotFGColorSelected(const QColor& c); + void slotBGColorSelected(const QColor& c); + void currentChanged(KDualColorButton::DualColor); + +private: + + void update(const QColor & fgColor, const QColor & bgColor); + + KoColorSlider *mSlider; + QLabel *mLabel; + QSpinBox *mIn; + KDualColorButton *m_ColorButton; + + QColor m_fgColor; + QColor m_bgColor; +}; + +#endif diff --git a/lib/kopainter/ko_hsv_widget.cc b/lib/kopainter/ko_hsv_widget.cc new file mode 100644 index 00000000..3670b5d9 --- /dev/null +++ b/lib/kopainter/ko_hsv_widget.cc @@ -0,0 +1,274 @@ +/* + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "ko_hsv_widget.h" +#include "ko_color_wheel.h" + +#include <kselect.h> +#include <qlayout.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qtooltip.h> +#include <koFrameButton.h> +#include <koColorSlider.h> +#include <kcolordialog.h> +#include <kdualcolorbutton.h> +#include <koColor.h> +#include <kdebug.h> +#include <klocale.h> + +KoHSVWidget::KoHSVWidget(QWidget *parent, const char *name) : super(parent, name) +{ + m_ColorButton = new KDualColorButton(this); + m_ColorButton -> setFixedSize(m_ColorButton->sizeHint()); + + QGridLayout *mGrid = new QGridLayout(this, 5, 7, 5, 2); + m_colorwheel = new KoColorWheel(this); + m_colorwheel->setFixedSize( 120, 120); + m_VSelector = new KValueSelector(Qt::Vertical, this); + m_VSelector-> setFixedSize( 30, 120); + + /* setup slider labels */ + mHLabel = new QLabel("H:", this); + mHLabel->setFixedSize(12, 20); + mSLabel = new QLabel("S:", this); + mSLabel->setFixedSize(12, 20); + mVLabel = new QLabel("V:", this); + mVLabel->setFixedSize(12, 20); + + /* setup spin box */ + mHIn = new QSpinBox(0, 359, 1, this); + mHIn->setFixedSize(50, 20); + mHIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mHIn, i18n( "Hue" ) ); + + mSIn = new QSpinBox(0, 255, 1, this); + mSIn->setFixedSize(50, 20); + mSIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mSIn, i18n( "Saturation" ) ); + + mVIn = new QSpinBox(0, 255, 1, this); + mVIn->setFixedSize(50, 20); + mVIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mVIn, i18n( "Value (brightness)" ) ); + + mGrid->addMultiCellWidget(m_ColorButton, 0, 0, 0, 1, Qt::AlignTop); + + mGrid->addWidget(mHLabel, 1, 0); + mGrid->addWidget(mSLabel, 2, 0); + mGrid->addWidget(mVLabel, 3, 0); + + mGrid->addMultiCellWidget(m_colorwheel, 0, 3, 2, 4); + + mGrid->addWidget(mHIn, 1, 1); + mGrid->addWidget(mSIn, 2, 1); + mGrid->addWidget(mVIn, 3, 1); + + mGrid->addMultiCellWidget(m_VSelector, 0, 3, 5, 5); + + + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(currentChanged(KDualColorButton::DualColor)), this, SLOT(currentChanged(KDualColorButton::DualColor))); + + connect(m_VSelector, SIGNAL(valueChanged(int)), this, SLOT(slotVChanged(int))); + connect(m_colorwheel, SIGNAL(valueChanged(const KoColor&)), this, SLOT(slotWheelChanged(const KoColor&))); + + /* connect spin box */ + connect(mHIn, SIGNAL(valueChanged(int)), this, SLOT(slotHChanged(int))); + connect(mSIn, SIGNAL(valueChanged(int)), this, SLOT(slotSChanged(int))); + connect(mVIn, SIGNAL(valueChanged(int)), this, SLOT(slotVChanged(int))); + + //setFixedSize(mGrid -> minimumSize()); + m_autovalue = true; // So on the initial selection of h or v, s gets set to 255. + + update(Qt::black, Qt::white); +} + +void KoHSVWidget::slotHChanged(int h) +{ + //kdDebug() << "H changed: " << h << endl; + if (m_ColorButton->current() == KDualColorButton::Foreground){ + m_fgColor.setHSV(h, m_fgColor.S(), m_fgColor.V()); + changedFgColor(); + } + else{ + m_bgColor.setHSV(h, m_bgColor.S(), m_bgColor.V()); + changedBgColor(); + } +} + +void KoHSVWidget::slotSChanged(int s) +{ + //kdDebug() << "S changed: " << s << endl; + if (m_ColorButton->current() == KDualColorButton::Foreground){ + m_fgColor.setHSV(m_fgColor.H(), s, m_fgColor.V()); + changedFgColor(); + } + else{ + m_bgColor.setHSV(m_bgColor.H(), s, m_bgColor.V()); + changedBgColor(); + } +} + +void KoHSVWidget::slotVChanged(int v) +{ + //kdDebug() << "V changed: " << v << ", setting autovalue to false " << endl; + m_autovalue = false; + if (m_ColorButton->current() == KDualColorButton::Foreground){ + m_fgColor.setHSV(m_fgColor.H(), m_fgColor.S(), v); + changedFgColor(); + } + else{ + m_bgColor.setHSV(m_bgColor.H(), m_bgColor.S(), v); + changedBgColor(); + } +} + +void KoHSVWidget::slotWheelChanged(const KoColor& c) +{ + //kdDebug() << "Wheel changed: " << c.color() << endl; + if (m_ColorButton->current() == KDualColorButton::Foreground){ + if(m_autovalue) + m_fgColor.setHSV(c.H(), c.S(), 255); + else + m_fgColor.setHSV(c.H(), c.S(), m_fgColor.V()); + changedFgColor(); + } + else{ + if(m_autovalue) + m_bgColor.setHSV(c.H(), c.S(), 255); + else + m_bgColor.setHSV(c.H(), c.S(), m_bgColor.V()); + changedBgColor(); + } +} + + +void KoHSVWidget::setFgColor(const QColor & c) +{ + //kdDebug() << "setFGColor " << c << endl; + blockSignals(true); + slotFGColorSelected(c); + blockSignals(false); +} + +void KoHSVWidget::setBgColor(const QColor & c) +{ + //kdDebug() << "setBgColor " << c << endl; + blockSignals(true); + slotBGColorSelected(c); + blockSignals(false); +} + +void KoHSVWidget::changedFgColor() +{ + //kdDebug() << "ChangedFgColor\n"; + disconnect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + m_ColorButton->setForeground( m_fgColor.color() ); + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + + update( m_fgColor, m_bgColor); + + emit sigFgColorChanged(m_fgColor.color()); +} + +void KoHSVWidget::changedBgColor() +{ + //kdDebug() << "changedBgColor()\n"; + disconnect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + m_ColorButton->setBackground( m_bgColor.color() ); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + update(m_fgColor, m_bgColor ); + + emit sigBgColorChanged(m_bgColor.color()); +} + +void KoHSVWidget::update(const KoColor & fgColor, const KoColor & bgColor) +{ + + mHIn->blockSignals(true); + mSIn->blockSignals(true); + mVIn->blockSignals(true); + m_VSelector->blockSignals(true); + m_colorwheel->blockSignals(true); + + //kdDebug() << "update. FG: " << fgColor.color() << ", bg: " << bgColor.color() << endl; + m_fgColor = fgColor; + m_bgColor = bgColor; + + KoColor color = (m_ColorButton->current() == KDualColorButton::Foreground)? m_fgColor : m_bgColor; + + int h = color.H(); + int s = color.S(); + int v = color.V(); + + mHIn->setValue(h); + mSIn->setValue(s); + mVIn->setValue(v); + + m_VSelector->setHue(h); + m_VSelector->setSaturation(s); + m_VSelector->setValue(v); + m_VSelector->updateContents(); + + m_colorwheel->slotSetValue(color); + + mHIn->blockSignals(false); + mSIn->blockSignals(false); + mVIn->blockSignals(false); + m_VSelector->blockSignals(false); + m_VSelector->repaint(false); + m_colorwheel->blockSignals(false); +} + +void KoHSVWidget::slotFGColorSelected(const QColor& c) +{ + //kdDebug() << "slotFGColorSelected " << c << endl; + m_fgColor = KoColor(c); + + changedFgColor(); +} + +void KoHSVWidget::slotBGColorSelected(const QColor& c) +{ + //kdDebug() << "slotBGColorSelected()" << c << endl; + m_bgColor = KoColor(c); + + changedBgColor(); +} + +void KoHSVWidget::currentChanged(KDualColorButton::DualColor s) +{ + //kdDebug() << "currentChanged\n"; + if(s == KDualColorButton::Foreground) + slotFGColorSelected(m_ColorButton->currentColor()); + else + slotBGColorSelected(m_ColorButton->currentColor()); + emit sigModeChanged( s ); +} + +void KoHSVWidget::setMode(KDualColorButton::DualColor s) +{ + m_ColorButton->setCurrent( s ); +} + +#include "ko_hsv_widget.moc" diff --git a/lib/kopainter/ko_hsv_widget.h b/lib/kopainter/ko_hsv_widget.h new file mode 100644 index 00000000..f8fcdcfb --- /dev/null +++ b/lib/kopainter/ko_hsv_widget.h @@ -0,0 +1,99 @@ +/** + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KO_HSV_WIDGET_H +#define KO_HSV_WIDGET_H + +#include "qwidget.h" +#include "kdualcolorbutton.h" + +#include "koColor.h" + +#include <koffice_export.h> + +class KDualColorButton; +class KValueSelector; +class KoColorWheel; +class KoColorSlider; +class KoFrameButton; +class QGridLayout; +class QLabel; +class QSpinBox; + +class KoHSVWidget + : public QWidget +{ + Q_OBJECT + typedef QWidget super; + +public: + KoHSVWidget(QWidget *parent = 0L, const char *name = 0); + virtual ~KoHSVWidget() {} + +public slots: + /** + * Set the current color to c. Do not emit the color changed signals + */ + virtual void setFgColor(const QColor & c); + virtual void setBgColor(const QColor & c); + /// Sets the current mode (foreground/background) without emitting the signal + virtual void setMode(KDualColorButton::DualColor); +signals: + + /** + * Emitted when the current color is changed. + */ + virtual void sigFgColorChanged(const QColor & c); + virtual void sigBgColorChanged(const QColor & c); + /// Emitted when the mode (foreground/background) was changed + virtual void sigModeChanged(KDualColorButton::DualColor); + +protected slots: + + virtual void slotHChanged(int h); + virtual void slotSChanged(int s); + virtual void slotVChanged(int v); + virtual void slotWheelChanged(const KoColor& c); + + void slotFGColorSelected(const QColor& c); + void slotBGColorSelected(const QColor& c); + void currentChanged(KDualColorButton::DualColor); + +private: + void changedFgColor(); + void changedBgColor(); + + void update(const KoColor & fgColor, const KoColor & bgColor); + + KoColorWheel *m_colorwheel; + KValueSelector *m_VSelector; + QLabel *mHLabel; + QLabel *mSLabel; + QLabel *mVLabel; + QSpinBox *mHIn; + QSpinBox *mSIn; + QSpinBox *mVIn; + KDualColorButton *m_ColorButton; + + KoColor m_fgColor; + KoColor m_bgColor; + + bool m_autovalue; +}; + +#endif diff --git a/lib/kopainter/ko_rgb_widget.cc b/lib/kopainter/ko_rgb_widget.cc new file mode 100644 index 00000000..f533bef5 --- /dev/null +++ b/lib/kopainter/ko_rgb_widget.cc @@ -0,0 +1,235 @@ +/* + * This file is part of Krita + * + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "ko_rgb_widget.h" + +#include <qlayout.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qtooltip.h> +#include <qcolor.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <koFrameButton.h> +#include <koColorSlider.h> +#include <kcolordialog.h> + +KoRGBWidget::KoRGBWidget(QWidget *parent, const char *name) : super(parent, name) +{ + m_ColorButton = new KDualColorButton(this); + m_ColorButton -> setFixedSize(m_ColorButton->sizeHint()); + QGridLayout *mGrid = new QGridLayout(this, 3, 5, 5, 2); + + /* setup color sliders */ + mRSlider = new KoColorSlider(this); + mRSlider->setMaximumHeight(20); + mRSlider->slotSetRange(0, 255); + mRSlider->setFocusPolicy( QWidget::ClickFocus ); + + mGSlider = new KoColorSlider(this); + mGSlider->setMaximumHeight(20); + mGSlider->slotSetRange(0, 255); + mGSlider->setFocusPolicy( QWidget::ClickFocus ); + + mBSlider = new KoColorSlider(this); + mBSlider->setMaximumHeight(20); + mBSlider->slotSetRange(0, 255); + mBSlider->setFocusPolicy( QWidget::ClickFocus ); + + /* setup slider labels */ + mRLabel = new QLabel("R:", this); + mRLabel->setFixedWidth(12); + mRLabel->setFixedHeight(20); + mGLabel = new QLabel("G:", this); + mGLabel->setFixedWidth(12); + mGLabel->setFixedHeight(20); + mBLabel = new QLabel("B:", this); + mBLabel->setFixedWidth(12); + mBLabel->setFixedHeight(20); + + /* setup spin box */ + mRIn = new QSpinBox(0, 255, 1, this); + mRIn->setFixedWidth(50); + mRIn->setFixedHeight(20); + mRIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mRIn, i18n( "Red" ) ); + + mGIn = new QSpinBox(0, 255, 1, this); + mGIn->setFixedWidth(50); + mGIn->setFixedHeight(20); + mGIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mGIn, i18n( "Green" ) ); + + mBIn = new QSpinBox(0, 255, 1, this); + mBIn->setFixedWidth(50); + mBIn->setFixedHeight(20); + mBIn->setFocusPolicy( QWidget::ClickFocus ); + QToolTip::add( mBIn, i18n( "Blue" ) ); + + mGrid->addMultiCellWidget(m_ColorButton, 0, 3, 0, 0, Qt::AlignTop); + mGrid->addWidget(mRLabel, 0, 1); + mGrid->addWidget(mGLabel, 1, 1); + mGrid->addWidget(mBLabel, 2, 1); + mGrid->addMultiCellWidget(mRSlider, 0, 0, 2, 3); + mGrid->addMultiCellWidget(mGSlider, 1, 1, 2, 3); + mGrid->addMultiCellWidget(mBSlider, 2, 2, 2, 3); + mGrid->addWidget(mRIn, 0, 4); + mGrid->addWidget(mGIn, 1, 4); + mGrid->addWidget(mBIn, 2, 4); + + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + connect(m_ColorButton, SIGNAL(currentChanged(KDualColorButton::DualColor)), this, SLOT(currentChanged(KDualColorButton::DualColor))); + + /* connect color sliders */ + connect(mRSlider, SIGNAL(valueChanged(int)), this, SLOT(slotRChanged(int))); + connect(mGSlider, SIGNAL(valueChanged(int)), this, SLOT(slotGChanged(int))); + connect(mBSlider, SIGNAL(valueChanged(int)), this, SLOT(slotBChanged(int))); + + /* connect spin box */ + connect(mRIn, SIGNAL(valueChanged(int)), this, SLOT(slotRChanged(int))); + connect(mGIn, SIGNAL(valueChanged(int)), this, SLOT(slotGChanged(int))); + connect(mBIn, SIGNAL(valueChanged(int)), this, SLOT(slotBChanged(int))); + + update(Qt::black, Qt::white); +} + +void KoRGBWidget::slotRChanged(int r) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground) + slotFGColorSelected( QColor(r, m_fgColor.green(), m_fgColor.blue())); + else + slotBGColorSelected( QColor(r, m_bgColor.green(), m_bgColor.blue())); +} + +void KoRGBWidget::slotGChanged(int g) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground) + slotFGColorSelected( QColor( m_fgColor.red(), g, m_fgColor.blue())); + else + slotBGColorSelected( QColor( m_bgColor.red(), g, m_bgColor.blue()));; +} + +void KoRGBWidget::slotBChanged(int b) +{ + if (m_ColorButton->current() == KDualColorButton::Foreground) + slotFGColorSelected( QColor( m_fgColor.red(), m_fgColor.green(), b)); + else + slotBGColorSelected( QColor( m_bgColor.red(), m_bgColor.green(), b)); +} + +void KoRGBWidget::setFgColor(const QColor & c) +{ + blockSignals(true); + slotFGColorSelected(c); + blockSignals(false); +} + +void KoRGBWidget::setBgColor(const QColor & c) +{ + blockSignals(true); + slotBGColorSelected(c); + blockSignals(false); +} + +void KoRGBWidget::update(const QColor fgColor, const QColor bgColor) +{ + + m_fgColor = fgColor; + m_bgColor = bgColor; + + QColor color = (m_ColorButton->current() == KDualColorButton::Foreground)? m_fgColor : m_bgColor; + + int r = color.red(); + int g = color.green(); + int b = color.blue(); + + mRSlider->blockSignals(true); + mRIn->blockSignals(true); + mGSlider->blockSignals(true); + mGIn->blockSignals(true); + mBSlider->blockSignals(true); + mBIn->blockSignals(true); + + mRSlider->slotSetColor1(QColor(0, g, b)); + mRSlider->slotSetColor2(QColor(255, g, b)); + mRSlider->slotSetValue(r); + mRIn->setValue(r); + + mGSlider->slotSetColor1(QColor(r, 0, b)); + mGSlider->slotSetColor2(QColor(r, 255, b)); + mGSlider->slotSetValue(g); + mGIn->setValue(g); + + mBSlider->slotSetColor1(QColor(r, g, 0)); + mBSlider->slotSetColor2(QColor(r, g, 255)); + mBSlider->slotSetValue(b); + mBIn->setValue(b); + + mRSlider->blockSignals(false); + mRIn->blockSignals(false); + mGSlider->blockSignals(false); + mGIn->blockSignals(false); + mBSlider->blockSignals(false); + mBIn->blockSignals(false); +} + +void KoRGBWidget::slotFGColorSelected(const QColor& c) +{ + m_fgColor = c; + disconnect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + m_ColorButton->setForeground( m_fgColor ); + connect(m_ColorButton, SIGNAL(fgChanged(const QColor &)), this, SLOT(slotFGColorSelected(const QColor &))); + + update( m_fgColor, m_bgColor); + emit sigFgColorChanged(m_fgColor); +} + +void KoRGBWidget::slotBGColorSelected(const QColor& c) +{ + m_bgColor = c; + + disconnect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + m_ColorButton->setBackground( m_bgColor ); + connect(m_ColorButton, SIGNAL(bgChanged(const QColor &)), this, SLOT(slotBGColorSelected(const QColor &))); + + update(m_fgColor, m_bgColor); + emit sigBgColorChanged(m_bgColor); +} + +void KoRGBWidget::currentChanged(KDualColorButton::DualColor s) +{ + if(s == KDualColorButton::Foreground) + slotFGColorSelected(m_ColorButton->currentColor()); + else + slotBGColorSelected(m_ColorButton->currentColor()); + emit sigModeChanged( s ); +} + +void KoRGBWidget::setMode(KDualColorButton::DualColor s) +{ + m_ColorButton->setCurrent( s ); +} + +#include "ko_rgb_widget.moc" diff --git a/lib/kopainter/ko_rgb_widget.h b/lib/kopainter/ko_rgb_widget.h new file mode 100644 index 00000000..ab18c8a5 --- /dev/null +++ b/lib/kopainter/ko_rgb_widget.h @@ -0,0 +1,98 @@ +/* This file is part of the KDE project + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KO_RGB_WIDGET_H +#define KO_RGB_WIDGET_H + +#include "qwidget.h" + +#include <koffice_export.h> +#include <kdualcolorbutton.h> + +class KoFrameButton; +class QGridLayout; +class QColor; +class KoColorSlider; +class QLabel; +class QSpinBox; +class KDualColorButton; +class KoColorSlider; +class QColor; + +class KoRGBWidget + : public QWidget +{ + Q_OBJECT + typedef QWidget super; + +public: + KoRGBWidget(QWidget *parent = 0L, const char *name = 0); + virtual ~KoRGBWidget() {} + +public slots: + /** + * Set the current color to c. Do not emit the color changed signals + */ + virtual void setFgColor(const QColor & c); + virtual void setBgColor(const QColor & c); + /// Sets the current mode (foreground/background) without emitting the signal + virtual void setMode(KDualColorButton::DualColor); + +signals: + + /** + * Emitted when the current color is changed. + */ + virtual void sigFgColorChanged(const QColor & c); + virtual void sigBgColorChanged(const QColor & c); + /// Emitted when the mode (foreground/background) was changed + virtual void sigModeChanged(KDualColorButton::DualColor); + + +protected slots: + + virtual void slotRChanged(int r); + virtual void slotGChanged(int g); + virtual void slotBChanged(int b); + + void slotFGColorSelected(const QColor& c); + void slotBGColorSelected(const QColor& c); + void currentChanged(KDualColorButton::DualColor); + +private: + + void update(const QColor fgColor, const QColor); + +private: + + KoColorSlider *mRSlider; + KoColorSlider *mGSlider; + KoColorSlider *mBSlider; + QLabel *mRLabel; + QLabel *mGLabel; + QLabel *mBLabel; + QSpinBox *mRIn; + QSpinBox *mGIn; + QSpinBox *mBIn; + KDualColorButton *m_ColorButton; + + QColor m_fgColor; + QColor m_bgColor; +}; + +#endif diff --git a/lib/kopainter/kogradientmanager.cc b/lib/kopainter/kogradientmanager.cc new file mode 100644 index 00000000..41f31d81 --- /dev/null +++ b/lib/kopainter/kogradientmanager.cc @@ -0,0 +1,559 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Tim Beaulen <tbscope@gmail.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "kogradientmanager.h" + +#include "svgnamedcolors.h" + +#include <qtextstream.h> +#include <qcstring.h> + +#include <kdebug.h> + +KoGradientManager::KoGradientManager() +{ +} + +KoGradientManager::~KoGradientManager() +{ + // XXX: Should we delete the gradients here? +} + +KoGradient* KoGradientManager::loadGradient(const QString& filename) +{ + QString strExt; + const int result=filename.findRev('.'); + if (result>=0) + { + strExt=filename.mid(result).lower(); + } + + QFile f(filename); + + if(f.open(IO_ReadOnly)) + { + if(strExt == ".ggr") + { + return loadKritaGradient(&f); + } + else if(strExt==".kgr") + { + return loadKarbonGradient(&f); + } + else if(strExt==".svg") + { + return loadSvgGradient(&f); + } + } + + return 0; +} + +KoGradient* KoGradientManager::loadKarbonGradient(QFile* file) +{ + QDomDocument doc; + + if(!(doc.setContent(file))) + file->close(); + else + { + QDomElement e; + QDomNode n = doc.documentElement().firstChild(); + + if(!n.isNull()) + { + e = n.toElement(); + + if(!e.isNull()) + if( e.tagName() == "GRADIENT" ) + return parseKarbonGradient(e); + } + } + + return 0; +} + +KoGradient* KoGradientManager::loadKritaGradient(QFile* file) +{ + KoGradient* grad = new KoGradient(); + + QByteArray m_data = file->readAll(); + file->close(); + + QTextIStream fileContent(m_data); + fileContent.setEncoding(QTextStream::UnicodeUTF8); + + QString header = fileContent.readLine(); + + if (header != "GIMP Gradient") + { + delete grad; + return 0; + } + + QString nameDefinition = fileContent.readLine(); + QString numSegmentsText; + + if (nameDefinition.startsWith("Name: ")) + { + QString nameText = nameDefinition.right(nameDefinition.length() - 6); + numSegmentsText = fileContent.readLine(); + } + else + { + // Older format without name. + + numSegmentsText = nameDefinition; + } + + int numSegments; + bool ok; + + numSegments = numSegmentsText.toInt(&ok); + + if (!ok || numSegments < 1) + { + return 0; + } + + for (int i = 0; i < numSegments; i++) + { + KoColorStop *stop = new KoColorStop(); + + QString segmentText = fileContent.readLine(); + QTextIStream segmentFields(&segmentText); + + double leftOffset; + double middleOffset; + double rightOffset; + + segmentFields >> leftOffset >> middleOffset >> rightOffset; + + double leftRed; + double leftGreen; + double leftBlue; + double leftAlpha; + + segmentFields >> leftRed >> leftGreen >> leftBlue >> leftAlpha; + + double rightRed; + double rightGreen; + double rightBlue; + double rightAlpha; + + segmentFields >> rightRed >> rightGreen >> rightBlue >> rightAlpha; + + int interpolationType; + int colorInterpolationType; + + segmentFields >> interpolationType >> colorInterpolationType; + + middleOffset = (middleOffset - leftOffset) / (rightOffset - leftOffset); + + stop->opacity = leftAlpha; + stop->midpoint = middleOffset; + stop->offset = leftOffset; + + stop->color1 = leftRed; + stop->color2 = leftGreen; + stop->color3 = leftBlue; + stop->color4 = 0.0; + stop->colorType = colorInterpolationType; + stop->interpolation = interpolationType; + + grad->colorStops.append(stop); + + if(rightOffset == 1.0) + { + KoColorStop *lastStop = new KoColorStop(); + lastStop->opacity = rightAlpha; + lastStop->midpoint = middleOffset; + lastStop->offset = rightOffset; + lastStop->color1 = rightRed; + lastStop->color2 = rightGreen; + lastStop->color3 = rightBlue; + lastStop->color4 = 0.0; + lastStop->colorType = colorInterpolationType; + lastStop->interpolation = interpolationType; + grad->colorStops.append(lastStop); + } + } + + if (!grad->colorStops.isEmpty()) + { + grad->originX = 0.0; + grad->originY = 1.0; + grad->vectorX = 0.0; + grad->vectorY = 0.0; + grad->focalpointX = 0.0; + grad->focalpointY = 0.0; + grad->gradientType = gradient_type_linear; + grad->gradientRepeatMethod = repeat_method_none; + + return grad; + } + else + { + delete grad; + return 0; + } +} + +KoGradient* KoGradientManager::loadSvgGradient(QFile* file) +{ + QDomDocument doc; + + if(!(doc.setContent(file))) + file->close(); + else + { + for( QDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement e = n.toElement(); + if( e.isNull() ) continue; + + if( e.tagName() == "linearGradient" || e.tagName() == "radialGradient" ) + return parseSvgGradient(e); + } + } + + return 0; +} + +KoGradient* KoGradientManager::parseKarbonGradient(const QDomElement& element) +{ + KoGradient* grad = new KoGradient(); + + grad->originX = element.attribute("originX", "0.0").toDouble(); + grad->originY = element.attribute("originY", "0.0").toDouble(); + grad->focalpointX = element.attribute("focalX", "0.0").toDouble(); + grad->focalpointY = element.attribute("focalY", "0.0").toDouble(); + grad->vectorX = element.attribute("vectorX", "0.0").toDouble(); + grad->vectorY = element.attribute("vectorY", "0.0").toDouble(); + grad->gradientType = (KoGradientType)element.attribute("type", 0).toInt(); + grad->gradientRepeatMethod = (KoGradientRepeatMethod)element.attribute("repeatMethod", 0).toInt(); + + grad->colorStops.clear(); + + // load stops + QDomNodeList list = element.childNodes(); + for( uint i = 0; i < list.count(); ++i ) + { + if( list.item( i ).isElement() ) + { + QDomElement colorstop = list.item( i ).toElement(); + + if( colorstop.tagName() == "COLORSTOP" ) + { + KoColorStop *stop = new KoColorStop(); + + QDomElement e = colorstop.firstChild().toElement(); + + switch(e.attribute("colorSpace").toUShort()) + { + case 1: // cmyk + stop->color1 = e.attribute( "v1", "0.0" ).toFloat(); + stop->color2 = e.attribute( "v2", "0.0" ).toFloat(); + stop->color3 = e.attribute( "v3", "0.0" ).toFloat(); + stop->color4 = e.attribute( "v4", "0.0" ).toFloat(); + stop->colorType = color_type_cmyk; + stop->interpolation = interpolation_linear; + break; + case 2: // hsv + stop->color1 = e.attribute( "v1", "0.0" ).toFloat(); + stop->color2 = e.attribute( "v2", "0.0" ).toFloat(); + stop->color3 = e.attribute( "v3", "0.0" ).toFloat(); + stop->color4 = 0.0; + stop->colorType = color_type_hsv_cw; + stop->interpolation = interpolation_linear; + break; + case 3: // gray + stop->color1 = e.attribute( "v1", "0.0" ).toFloat(); + stop->color2 = 0.0; + stop->color3 = 0.0; + stop->color4 = 0.0; + stop->colorType = color_type_gray; + stop->interpolation = interpolation_linear; + break; + default: // rgb + stop->color1 = e.attribute( "v1", "0.0" ).toFloat(); + stop->color2 = e.attribute( "v2", "0.0" ).toFloat(); + stop->color3 = e.attribute( "v3", "0.0" ).toFloat(); + stop->color4 = 0.0; + stop->colorType = color_type_rgb; + stop->interpolation = interpolation_linear; + } + + stop->opacity = e.attribute("opacity", "1.0").toFloat(); + + stop->offset = colorstop.attribute("ramppoint", "0.0").toFloat(); + stop->midpoint = colorstop.attribute("midpoint", "0.5").toFloat(); + + grad->colorStops.append(stop); + } + } + } + + return grad; +} + +KoGradient* KoGradientManager::parseSvgGradient(const QDomElement& element) +{ + KoGradient* grad = new KoGradient; + + grad->colorStops.clear(); + grad->gradientRepeatMethod = repeat_method_none; + + /*QString href = e.attribute( "xlink:href" ).mid( 1 ); + if( !href.isEmpty() ) + { + }*/ + + bool bbox = element.attribute( "gradientUnits" ) != "userSpaceOnUse"; + + if( element.tagName() == "linearGradient" ) + { + if( bbox ) + { + QString s; + + s = element.attribute( "x1", "0%" ); + double xOrigin; + if( s.endsWith( "%" ) ) + xOrigin = s.remove( '%' ).toDouble(); + else + xOrigin = s.toDouble() * 100.0; + + s = element.attribute( "y1", "0%" ); + double yOrigin; + if( s.endsWith( "%" ) ) + yOrigin = s.remove( '%' ).toDouble(); + else + yOrigin = s.toDouble() * 100.0; + + s = element.attribute( "x2", "100%" ); + double xVector; + if( s.endsWith( "%" ) ) + xVector = s.remove( '%' ).toDouble(); + else + xVector = s.toDouble() * 100.0; + + s = element.attribute( "y2", "0%" ); + double yVector; + if( s.endsWith( "%" ) ) + yVector = s.remove( '%' ).toDouble(); + else + yVector = s.toDouble() * 100.0; + + grad->originX = xOrigin; + grad->originY = yOrigin; + grad->vectorX = xVector; + grad->vectorY = yVector; + } + else + { + grad->originX = element.attribute( "x1" ).toDouble(); + grad->originY = element.attribute( "y1" ).toDouble(); + grad->vectorX = element.attribute( "x2" ).toDouble(); + grad->vectorY = element.attribute( "y2" ).toDouble(); + } + grad->gradientType = gradient_type_linear; + } + else + { + if( bbox ) + { + QString s; + + s = element.attribute( "cx", "50%" ); + double xOrigin; + if( s.endsWith( "%" ) ) + xOrigin = s.remove( '%' ).toDouble(); + else + xOrigin = s.toDouble() * 100.0; + + s = element.attribute( "cy", "50%" ); + double yOrigin; + if( s.endsWith( "%" ) ) + yOrigin = s.remove( '%' ).toDouble(); + else + yOrigin = s.toDouble() * 100.0; + + s = element.attribute( "cx", "50%" ); + double xVector; + if( s.endsWith( "%" ) ) + xVector = s.remove( '%' ).toDouble(); + else + xVector = s.toDouble() * 100.0; + + s = element.attribute( "r", "50%" ); + if( s.endsWith( "%" ) ) + xVector += s.remove( '%' ).toDouble(); + else + xVector += s.toDouble() * 100.0; + + s = element.attribute( "cy", "50%" ); + double yVector; + if( s.endsWith( "%" ) ) + yVector = s.remove( '%' ).toDouble(); + else + yVector = s.toDouble() * 100.0; + + s = element.attribute( "fx", "50%" ); + double xFocal; + if( s.endsWith( "%" ) ) + xFocal = s.remove( '%' ).toDouble(); + else + xFocal = s.toDouble() * 100.0; + + s = element.attribute( "fy", "50%" ); + double yFocal; + if( s.endsWith( "%" ) ) + yFocal = s.remove( '%' ).toDouble(); + else + yFocal = s.toDouble() * 100.0; + + grad->originX = xOrigin; + grad->originY = yOrigin; + grad->vectorX = xVector; + grad->vectorY = yVector; + grad->focalpointX = xFocal; + grad->focalpointY = yFocal; + } + else + { + grad->originX = element.attribute( "cx" ).toDouble(); + grad->originY = element.attribute( "cy" ).toDouble(); + grad->vectorX = element.attribute( "cx" ).toDouble() + element.attribute( "r" ).toDouble(); + grad->vectorY = element.attribute( "cy" ).toDouble(); + grad->focalpointX = element.attribute( "fx" ).toDouble(); + grad->focalpointY = element.attribute( "fy" ).toDouble(); + } + grad->gradientType = gradient_type_radial; + } + // handle spread method + QString spreadMethod = element.attribute( "spreadMethod" ); + if( !spreadMethod.isEmpty() ) + { + if( spreadMethod == "reflect" ) + grad->gradientRepeatMethod = repeat_method_reflect; + else if( spreadMethod == "repeat" ) + grad->gradientRepeatMethod = repeat_method_repeat; + } + + for( QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling() ) + { + QDomElement colorstop = n.toElement(); + if( colorstop.tagName() == "stop" ) + { + KoColorStop *stop = new KoColorStop(); + QColor c; + float off; + QString temp = colorstop.attribute( "offset" ); + if( temp.contains( '%' ) ) + { + temp = temp.left( temp.length() - 1 ); + off = temp.toFloat() / 100.0; + } + else + off = temp.toFloat(); + + if( !colorstop.attribute( "stop-color" ).isEmpty() ) + parseSvgColor( c, colorstop.attribute( "stop-color" ) ); + else + { + // try style attr + QString style = colorstop.attribute( "style" ).simplifyWhiteSpace(); + QStringList substyles = QStringList::split( ';', style ); + for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it ) + { + QStringList substyle = QStringList::split( ':', (*it) ); + QString command = substyle[0].stripWhiteSpace(); + QString params = substyle[1].stripWhiteSpace(); + if( command == "stop-color" ) + parseSvgColor( c, params ); + if( command == "stop-opacity" ) + stop->opacity = params.toDouble(); + } + + } + if( !colorstop.attribute( "stop-opacity" ).isEmpty() ) + stop->opacity = colorstop.attribute( "stop-opacity" ).toDouble(); + + stop->offset = off; + stop->midpoint = 0.5; + stop->color1 = c.red() / 255.0; + stop->color2 = c.green() / 255.0; + stop->color3 = c.blue() / 255.0; + stop->color4 = 0.0; + stop->colorType = color_type_rgb; + stop->interpolation = interpolation_linear; + grad->colorStops.append(stop); + } + } + + return grad; +} + +void KoGradientManager::parseSvgColor(QColor &color, const QString &s) +{ + if( s.startsWith( "rgb(" ) ) + { + QString parse = s.stripWhiteSpace(); + QStringList colors = QStringList::split( ',', parse ); + QString r = colors[0].right( ( colors[0].length() - 4 ) ); + QString g = colors[1]; + QString b = colors[2].left( ( colors[2].length() - 1 ) ); + + if( r.contains( "%" ) ) + { + r = r.left( r.length() - 1 ); + r = QString::number( int( ( double( 255 * r.toDouble() ) / 100.0 ) ) ); + } + + if( g.contains( "%" ) ) + { + g = g.left( g.length() - 1 ); + g = QString::number( int( ( double( 255 * g.toDouble() ) / 100.0 ) ) ); + } + + if( b.contains( "%" ) ) + { + b = b.left( b.length() - 1 ); + b = QString::number( int( ( double( 255 * b.toDouble() ) / 100.0 ) ) ); + } + + color = QColor( r.toInt(), g.toInt(), b.toInt() ); + } + else + { + QString rgbColor = s.stripWhiteSpace(); + QColor c; + if( rgbColor.startsWith( "#" ) ) + c.setNamedColor( rgbColor ); + else + { + int r, g, b; + svgNamedColorToRGB( rgbColor, r, g, b ); + c = QColor( r, g, b ); + } + color = c; + } +} + diff --git a/lib/kopainter/kogradientmanager.h b/lib/kopainter/kogradientmanager.h new file mode 100644 index 00000000..08412108 --- /dev/null +++ b/lib/kopainter/kogradientmanager.h @@ -0,0 +1,115 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Tim Beaulen <tbscope@gmail.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __GRADIENT_LOADER__ +#define __GRADIENT_LOADER__ + +#include <qptrlist.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qfile.h> +#include <qdom.h> +#include <qcolor.h> +#include <koffice_export.h> +struct KoColorStop +{ + double offset; + double midpoint; + double opacity; + double color1; + double color2; + double color3; + double color4; + int colorType; + int interpolation; +}; + +struct KoGradient +{ + double originX; + double originY; + double vectorX; + double vectorY; + double focalpointX; + double focalpointY; + int gradientType; + int gradientRepeatMethod; + + QPtrList<KoColorStop> colorStops; +}; + +class KOPAINTER_EXPORT KoGradientManager +{ +public: + + enum KoGradientType + { + gradient_type_linear = 0, + gradient_type_radial = 1, + gradient_type_conic = 2 + }; + + enum KoGradientInterpolation + { + interpolation_linear = 0, + interpolation_curved = 1, + interpolation_sine = 2, + interpolation_sphere_increasing = 3, + interpolation_sphere_decreasing = 4 + }; + + enum KoGradientColorType + { + color_type_rgb = 0, + color_type_hsv_ccw = 1, + color_type_hsv_cw = 2, + color_type_gray = 3, + color_type_cmyk = 4 + }; + + enum KoGradientRepeatMethod + { + repeat_method_none = 0, + repeat_method_reflect = 1, + repeat_method_repeat = 2 + }; + + KoGradientManager(); + ~KoGradientManager(); + + KoGradient* loadGradient(const QString& filename); + static QStringList filters() + { + QStringList filterList; + filterList << "*.kgr" << "*.svg" << "*.ggr"; + return filterList; + } + +private: + KoGradient* loadKarbonGradient(QFile* file); + KoGradient* loadKritaGradient(QFile* file); + KoGradient* loadSvgGradient(QFile* file); + KoGradient* parseKarbonGradient(const QDomElement& element); + KoGradient* parseSvgGradient(const QDomElement& element); + void parseSvgColor(QColor &color, const QString &s); +}; + +#endif + + diff --git a/lib/kopainter/svgnamedcolors.h b/lib/kopainter/svgnamedcolors.h new file mode 100644 index 00000000..bf926331 --- /dev/null +++ b/lib/kopainter/svgnamedcolors.h @@ -0,0 +1,306 @@ + +#define TORGB( red, green, blue ) \ +{ \ + r = red; \ + b = blue; \ + g = green; \ +} + +void svgNamedColorToRGB( QString rgbColor, int &r, int &g, int &b ) +{ + if( rgbColor == "aliceblue" ) + TORGB( 240, 248, 255) + else if( rgbColor == "antiquewhite" ) + TORGB( 250, 235, 215) + else if( rgbColor == "aqua" ) + TORGB( 0, 255, 255) + else if( rgbColor == "aquamarine" ) + TORGB( 127, 255, 212 ) + else if( rgbColor == "azure" ) + TORGB( 240, 255, 255 ) + else if( rgbColor == "beige" ) + TORGB( 245, 245, 220 ) + else if( rgbColor == "bisque" ) + TORGB( 255, 228, 196 ) + else if( rgbColor == "black" ) + TORGB( 0, 0, 0 ) + else if( rgbColor == "blanchedalmond" ) + TORGB( 255, 235, 205 ) + else if( rgbColor == "blue" ) + TORGB( 0, 0, 255 ) + else if( rgbColor == "blueviolet" ) + TORGB( 138, 43, 226 ) + else if( rgbColor == "brown" ) + TORGB( 165, 42, 42 ) + else if( rgbColor == "burlywood" ) + TORGB( 222, 184, 135 ) + else if( rgbColor == "cadetblue" ) + TORGB( 95, 158, 160 ) + else if( rgbColor == "chartreuse" ) + TORGB( 127, 255, 0 ) + else if( rgbColor == "chocolate" ) + TORGB( 210, 105, 30 ) + else if( rgbColor == "coral" ) + TORGB( 255, 127, 80 ) + else if( rgbColor == "cornflowerblue" ) + TORGB( 100, 149, 237 ) + else if( rgbColor == "cornsilk" ) + TORGB( 255, 248, 220 ) + else if( rgbColor == "crimson" ) + TORGB( 220, 20, 60 ) + else if( rgbColor == "cyan" ) + TORGB( 0, 255, 255 ) + else if( rgbColor == "darkblue" ) + TORGB( 0, 0, 139 ) + else if( rgbColor == "darkcyan" ) + TORGB( 0, 139, 139 ) + else if( rgbColor == "darkgoldenrod" ) + TORGB( 184, 134, 11 ) + else if( rgbColor == "darkgray" ) + TORGB( 169, 169, 169 ) + else if( rgbColor == "darkgrey" ) + TORGB( 169, 169, 169 ) + else if( rgbColor == "darkgreen" ) + TORGB( 0, 100, 0 ) + else if( rgbColor == "darkkhaki" ) + TORGB( 189, 183, 107 ) + else if( rgbColor == "darkmagenta" ) + TORGB( 139, 0, 139 ) + else if( rgbColor == "darkolivegreen" ) + TORGB( 85, 107, 47 ) + else if( rgbColor == "darkorange" ) + TORGB( 255, 140, 0 ) + else if( rgbColor == "darkorchid" ) + TORGB( 153, 50, 204 ) + else if( rgbColor == "darkred" ) + TORGB( 139, 0, 0 ) + else if( rgbColor == "darksalmon" ) + TORGB( 233, 150, 122 ) + else if( rgbColor == "darkseagreen" ) + TORGB( 143, 188, 143 ) + else if( rgbColor == "darkslateblue" ) + TORGB( 72, 61, 139 ) + else if( rgbColor == "darkslategray" ) + TORGB( 47, 79, 79 ) + else if( rgbColor == "darkslategrey" ) + TORGB( 47, 79, 79 ) + else if( rgbColor == "darkturquoise" ) + TORGB( 0, 206, 209 ) + else if( rgbColor == "darkviolet" ) + TORGB( 148, 0, 211 ) + else if( rgbColor == "deeppink" ) + TORGB( 255, 20, 147 ) + else if( rgbColor == "deepskyblue" ) + TORGB( 0, 191, 255 ) + else if( rgbColor == "dimgray" ) + TORGB( 105, 105, 105 ) + else if( rgbColor == "dimgrey" ) + TORGB( 105, 105, 105 ) + else if( rgbColor == "dodgerblue" ) + TORGB( 30, 144, 255 ) + else if( rgbColor == "firebrick" ) + TORGB( 178, 34, 34 ) + else if( rgbColor == "floralwhite" ) + TORGB( 255, 250, 240 ) + else if( rgbColor == "forestgreen" ) + TORGB( 34, 139, 34 ) + else if( rgbColor == "fuchsia" ) + TORGB( 255, 0, 255 ) + else if( rgbColor == "gainsboro" ) + TORGB( 220, 220, 220 ) + else if( rgbColor == "ghostwhite" ) + TORGB( 248, 248, 255 ) + else if( rgbColor == "gold" ) + TORGB( 255, 215, 0 ) + else if( rgbColor == "goldenrod" ) + TORGB( 218, 165, 32 ) + else if( rgbColor == "gray" ) + TORGB( 128, 128, 128 ) + else if( rgbColor == "grey" ) + TORGB( 128, 128, 128 ) + else if( rgbColor == "green" ) + TORGB( 0, 128, 0 ) + else if( rgbColor == "greenyellow" ) + TORGB( 173, 255, 47 ) + else if( rgbColor == "honeydew" ) + TORGB( 240, 255, 240 ) + else if( rgbColor == "hotpink" ) + TORGB( 255, 105, 180 ) + else if( rgbColor == "indianred" ) + TORGB( 205, 92, 92 ) + else if( rgbColor == "indigo" ) + TORGB( 75, 0, 130 ) + else if( rgbColor == "ivory" ) + TORGB( 255, 255, 240 ) + else if( rgbColor == "khaki" ) + TORGB( 240, 230, 140 ) + else if( rgbColor == "lavender" ) + TORGB( 230, 230, 250 ) + else if( rgbColor == "lavenderblush" ) + TORGB( 255, 240, 245 ) + else if( rgbColor == "lawngreen" ) + TORGB( 124, 252, 0 ) + else if( rgbColor == "lemonchiffon" ) + TORGB( 255, 250, 205 ) + else if( rgbColor == "lightblue" ) + TORGB( 173, 216, 230 ) + else if( rgbColor == "lightcoral" ) + TORGB( 240, 128, 128 ) + else if( rgbColor == "lightcyan" ) + TORGB( 224, 255, 255 ) + else if( rgbColor == "lightgoldenrodyellow" ) + TORGB( 250, 250, 210 ) + else if( rgbColor == "lightgray" ) + TORGB( 211, 211, 211 ) + else if( rgbColor == "lightgrey" ) + TORGB( 211, 211, 211 ) + else if( rgbColor == "lightgreen" ) + TORGB( 144, 238, 144 ) + else if( rgbColor == "lightpink" ) + TORGB( 255, 182, 193 ) + else if( rgbColor == "lightsalmon" ) + TORGB( 255, 160, 122 ) + else if( rgbColor == "lightseagreen" ) + TORGB( 32, 178, 170 ) + else if( rgbColor == "lightskyblue" ) + TORGB( 135, 206, 250 ) + else if( rgbColor == "lightslategray" ) + TORGB( 119, 136, 153 ) + else if( rgbColor == "lightslategrey" ) + TORGB( 119, 136, 153 ) + else if( rgbColor == "lightsteelblue" ) + TORGB( 176, 196, 222 ) + else if( rgbColor == "lightyellow" ) + TORGB( 255, 255, 224 ) + else if( rgbColor == "lime" ) + TORGB( 0, 255, 0 ) + else if( rgbColor == "limegreen" ) + TORGB( 50, 205, 50 ) + else if( rgbColor == "linen" ) + TORGB( 250, 240, 230 ) + else if( rgbColor == "magenta" ) + TORGB( 255, 0, 255 ) + else if( rgbColor == "maroon" ) + TORGB( 128, 0, 0 ) + else if( rgbColor == "mediumaquamarine" ) + TORGB( 102, 205, 170 ) + else if( rgbColor == "mediumblue" ) + TORGB( 0, 0, 205 ) + else if( rgbColor == "mediumorchid" ) + TORGB( 186, 85, 211 ) + else if( rgbColor == "mediumpurple" ) + TORGB( 147, 112, 219 ) + else if( rgbColor == "mediumseagreen" ) + TORGB( 60, 179, 113 ) + else if( rgbColor == "mediumslateblue" ) + TORGB( 123, 104, 238 ) + else if( rgbColor == "mediumspringgreen" ) + TORGB( 0, 250, 154 ) + else if( rgbColor == "mediumturquoise" ) + TORGB( 72, 209, 204 ) + else if( rgbColor == "mediumvioletred" ) + TORGB( 199, 21, 133 ) + else if( rgbColor == "midnightblue" ) + TORGB( 25, 25, 112 ) + else if( rgbColor == "mintcream" ) + TORGB( 245, 255, 250 ) + else if( rgbColor == "mistyrose" ) + TORGB( 255, 228, 225 ) + else if( rgbColor == "moccasin" ) + TORGB( 255, 228, 181 ) + else if( rgbColor == "navajowhite" ) + TORGB( 255, 222, 173 ) + else if( rgbColor == "navy" ) + TORGB( 0, 0, 128 ) + else if( rgbColor == "oldlace" ) + TORGB( 253, 245, 230 ) + else if( rgbColor == "olive" ) + TORGB( 128, 128, 0 ) + else if( rgbColor == "olivedrab" ) + TORGB( 107, 142, 35 ) + else if( rgbColor == "orange" ) + TORGB( 255, 165, 0 ) + else if( rgbColor == "orangered" ) + TORGB( 255, 69, 0 ) + else if( rgbColor == "orchid" ) + TORGB( 218, 112, 214 ) + else if( rgbColor == "palegoldenrod" ) + TORGB( 238, 232, 170 ) + else if( rgbColor == "palegreen" ) + TORGB( 152, 251, 152 ) + else if( rgbColor == "paleturquoise" ) + TORGB( 175, 238, 238 ) + else if( rgbColor == "palevioletred" ) + TORGB( 219, 112, 147 ) + else if( rgbColor == "papayawhip" ) + TORGB( 255, 239, 213 ) + else if( rgbColor == "peachpuff" ) + TORGB( 255, 218, 185 ) + else if( rgbColor == "peru" ) + TORGB( 205, 133, 63 ) + else if( rgbColor == "pink" ) + TORGB( 255, 192, 203 ) + else if( rgbColor == "plum" ) + TORGB( 221, 160, 221 ) + else if( rgbColor == "powderblue" ) + TORGB( 176, 224, 230 ) + else if( rgbColor == "purple" ) + TORGB( 128, 0, 128 ) + else if( rgbColor == "red" ) + TORGB( 255, 0, 0 ) + else if( rgbColor == "rosybrown" ) + TORGB( 188, 143, 143 ) + else if( rgbColor == "royalblue" ) + TORGB( 65, 105, 225 ) + else if( rgbColor == "saddlebrown" ) + TORGB( 139, 69, 19 ) + else if( rgbColor == "salmon" ) + TORGB( 250, 128, 114 ) + else if( rgbColor == "sandybrown" ) + TORGB( 244, 164, 96 ) + else if( rgbColor == "seagreen" ) + TORGB( 46, 139, 87 ) + else if( rgbColor == "seashell" ) + TORGB( 255, 245, 238 ) + else if( rgbColor == "sienna" ) + TORGB( 160, 82, 45 ) + else if( rgbColor == "silver" ) + TORGB( 192, 192, 192 ) + else if( rgbColor == "skyblue" ) + TORGB( 135, 206, 235 ) + else if( rgbColor == "slateblue" ) + TORGB( 106, 90, 205 ) + else if( rgbColor == "slategray" ) + TORGB( 112, 128, 144 ) + else if( rgbColor == "slategrey" ) + TORGB( 112, 128, 144 ) + else if( rgbColor == "snow" ) + TORGB( 255, 250, 250 ) + else if( rgbColor == "springgreen" ) + TORGB( 0, 255, 127 ) + else if( rgbColor == "steelblue" ) + TORGB( 70, 130, 180 ) + else if( rgbColor == "tan" ) + TORGB( 210, 180, 140 ) + else if( rgbColor == "teal" ) + TORGB( 0, 128, 128 ) + else if( rgbColor == "thistle" ) + TORGB( 216, 191, 216 ) + else if( rgbColor == "tomato" ) + TORGB( 255, 99, 71 ) + else if( rgbColor == "turquoise" ) + TORGB( 64, 224, 208 ) + else if( rgbColor == "violet" ) + TORGB( 238, 130, 238 ) + else if( rgbColor == "wheat" ) + TORGB( 245, 222, 179 ) + else if( rgbColor == "white" ) + TORGB( 255, 255, 255 ) + else if( rgbColor == "whitesmoke" ) + TORGB( 245, 245, 245 ) + else if( rgbColor == "yellow" ) + TORGB( 255, 255, 0 ) + else if( rgbColor == "yellowgreen" ) + TORGB( 154, 205, 50 ) +} + diff --git a/lib/kopainter/svgpathparser.cc b/lib/kopainter/svgpathparser.cc new file mode 100644 index 00000000..454c921b --- /dev/null +++ b/lib/kopainter/svgpathparser.cc @@ -0,0 +1,577 @@ +/* This file is part of the KDE project + Copyright (C) 2002, The Karbon Developers + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include "svgpathparser.h" +#include <qstring.h> +#include <math.h> +#include <kdebug.h> + +// parses the coord into number and forwards to the next token +const char * +SVGPathParser::getCoord( const char *ptr, double &number ) +{ + int integer, exponent; + double decimal, frac; + int sign, expsign; + + exponent = 0; + integer = 0; + frac = 1.0; + decimal = 0; + sign = 1; + expsign = 1; + + // read the sign + if(*ptr == '+') + ptr++; + else if(*ptr == '-') + { + ptr++; + sign = -1; + } + + // read the integer part + while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') + integer = (integer * 10) + *(ptr++) - '0'; + if(*ptr == '.') // read the decimals + { + ptr++; + while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') + decimal += (*(ptr++) - '0') * (frac *= 0.1); + } + + if(*ptr == 'e' || *ptr == 'E') // read the exponent part + { + ptr++; + + // read the sign of the exponent + if(*ptr == '+') + ptr++; + else if(*ptr == '-') + { + ptr++; + expsign = -1; + } + + exponent = 0; + while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9') + { + exponent *= 10; + exponent += *ptr - '0'; + ptr++; + } + } + number = integer + decimal; + number *= sign * pow( (double)10, double( expsign * exponent ) ); + + // skip the following space + if(*ptr == ' ') + ptr++; + + return ptr; +} + +void +SVGPathParser::parseSVG( const QString &s, bool process ) +{ + if( !s.isEmpty() ) + { + QString d = s; + d = d.replace( ',', ' ' ); + d = d.simplifyWhiteSpace(); + + const char *ptr = d.latin1(); + const char *end = d.latin1() + d.length() + 1; + + double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc; + double px1, py1, px2, py2, px3, py3; + bool relative; + char command = *(ptr++), lastCommand = ' '; + + subpathx = subpathy = curx = cury = contrlx = contrly = 0.0; + while( ptr < end ) + { + if( *ptr == ' ' ) + ptr++; + + relative = false; + + //std::cout << "Command : " << command << std::endl; + switch( command ) + { + case 'm': + relative = true; + case 'M': + { + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + + if( process ) + { + subpathx = curx = relative ? curx + tox : tox; + subpathy = cury = relative ? cury + toy : toy; + + svgMoveTo( curx, cury ); + } + else + svgMoveTo( tox, toy, !relative ); + break; + } + case 'l': + relative = true; + case 'L': + { + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + + if( process ) + { + curx = relative ? curx + tox : tox; + cury = relative ? cury + toy : toy; + + svgLineTo( curx, cury ); + } + else + svgLineTo( tox, toy, !relative ); + break; + } + case 'h': + { + ptr = getCoord( ptr, tox ); + if( process ) + { + curx = curx + tox; + svgLineTo( curx, cury ); + } + else + svgLineToHorizontal( tox, false ); + break; + } + case 'H': + { + ptr = getCoord( ptr, tox ); + if( process ) + { + curx = tox; + svgLineTo( curx, cury ); + } + else + svgLineToHorizontal( tox ); + break; + } + case 'v': + { + ptr = getCoord( ptr, toy ); + if( process ) + { + cury = cury + toy; + svgLineTo( curx, cury ); + } + else + svgLineToVertical( toy, false ); + break; + } + case 'V': + { + ptr = getCoord( ptr, toy ); + if( process ) + { + cury = toy; + svgLineTo( curx, cury ); + } + else + svgLineToVertical( toy ); + break; + } + case 'z': + case 'Z': + { + // reset curx, cury for next path + if( process ) + { + curx = subpathx; + cury = subpathy; + } + svgClosePath(); + break; + } + case 'c': + relative = true; + case 'C': + { + ptr = getCoord( ptr, x1 ); + ptr = getCoord( ptr, y1 ); + ptr = getCoord( ptr, x2 ); + ptr = getCoord( ptr, y2 ); + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + + if( process ) + { + px1 = relative ? curx + x1 : x1; + py1 = relative ? cury + y1 : y1; + px2 = relative ? curx + x2 : x2; + py2 = relative ? cury + y2 : y2; + px3 = relative ? curx + tox : tox; + py3 = relative ? cury + toy : toy; + + svgCurveToCubic( px1, py1, px2, py2, px3, py3 ); + + contrlx = relative ? curx + x2 : x2; + contrly = relative ? cury + y2 : y2; + curx = relative ? curx + tox : tox; + cury = relative ? cury + toy : toy; + } + else + svgCurveToCubic( x1, y1, x2, y2, tox, toy, !relative ); + + break; + } + case 's': + relative = true; + case 'S': + { + ptr = getCoord( ptr, x2 ); + ptr = getCoord( ptr, y2 ); + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + if( !( lastCommand == 'c' || lastCommand == 'C' || + lastCommand == 's' || lastCommand == 'S' ) ) + { + contrlx = curx; + contrly = cury; + } + + + if( process ) + { + px1 = 2 * curx - contrlx; + py1 = 2 * cury - contrly; + px2 = relative ? curx + x2 : x2; + py2 = relative ? cury + y2 : y2; + px3 = relative ? curx + tox : tox; + py3 = relative ? cury + toy : toy; + + svgCurveToCubic( px1, py1, px2, py2, px3, py3 ); + + contrlx = relative ? curx + x2 : x2; + contrly = relative ? cury + y2 : y2; + curx = relative ? curx + tox : tox; + cury = relative ? cury + toy : toy; + } + else + svgCurveToCubicSmooth( x2, y2, tox, toy, !relative ); + break; + } + case 'q': + relative = true; + case 'Q': + { + ptr = getCoord( ptr, x1 ); + ptr = getCoord( ptr, y1 ); + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + + if( process ) + { + px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0); + py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0); + px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0); + py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0); + px3 = relative ? curx + tox : tox; + py3 = relative ? cury + toy : toy; + + svgCurveToCubic( px1, py1, px2, py2, px3, py3 ); + + contrlx = relative ? curx + x1 : x1; + contrly = relative ? cury + y1 : y1; + curx = relative ? curx + tox : tox; + cury = relative ? cury + toy : toy; + } + else + svgCurveToQuadratic( x1, y1, tox, toy, !relative ); + break; + } + case 't': + relative = true; + case 'T': + { + ptr = getCoord(ptr, tox); + ptr = getCoord(ptr, toy); + if( !( lastCommand == 'q' || lastCommand == 'Q' || + lastCommand == 't' || lastCommand == 'T' ) ) + { + contrlx = curx; + contrly = cury; + } + + if( process ) + { + xc = 2 * curx - contrlx; + yc = 2 * cury - contrly; + + px1 = (curx + 2 * xc) * (1.0 / 3.0); + py1 = (cury + 2 * yc) * (1.0 / 3.0); + px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0); + py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0); + px3 = relative ? curx + tox : tox; + py3 = relative ? cury + toy : toy; + + svgCurveToCubic( px1, py1, px2, py2, px3, py3 ); + + contrlx = xc; + contrly = yc; + curx = relative ? curx + tox : tox; + cury = relative ? cury + toy : toy; + } + else + svgCurveToQuadraticSmooth( tox, toy, !relative ); + break; + } + case 'a': + relative = true; + case 'A': + { + bool largeArc, sweep; + double angle, rx, ry; + ptr = getCoord( ptr, rx ); + ptr = getCoord( ptr, ry ); + ptr = getCoord( ptr, angle ); + ptr = getCoord( ptr, tox ); + largeArc = tox == 1; + ptr = getCoord( ptr, tox ); + sweep = tox == 1; + ptr = getCoord( ptr, tox ); + ptr = getCoord( ptr, toy ); + + // Spec: radii are nonnegative numbers + rx = fabs(rx); + ry = fabs(ry); + + if( process ) + calculateArc( relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep ); + else + svgArcTo( tox, toy, rx, ry, angle, largeArc, sweep, !relative ); + } + default: + { + // when svg parser is used for a parsing an odf path an unknown command + // can be encountered, so we stop parsing here + kdDebug() << "SVGPathParser::parseSVG(): unknown command \"" << command << "\"" << endl; + return; + } + } + + lastCommand = command; + + if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9')) + { + // there are still coords in this command + if(command == 'M') + command = 'L'; + else if(command == 'm') + command = 'l'; + } + else + command = *(ptr++); + + if( lastCommand != 'C' && lastCommand != 'c' && + lastCommand != 'S' && lastCommand != 's' && + lastCommand != 'Q' && lastCommand != 'q' && + lastCommand != 'T' && lastCommand != 't') + { + contrlx = curx; + contrly = cury; + } + } + } +} + +// This works by converting the SVG arc to "simple" beziers. +// For each bezier found a svgToCurve call is done. +// Adapted from Niko's code in kdelibs/kdecore/svgicons. +// Maybe this can serve in some shared lib? (Rob) +void +SVGPathParser::calculateArc(bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag) +{ + double sin_th, cos_th; + double a00, a01, a10, a11; + double x0, y0, x1, y1, xc, yc; + double d, sfactor, sfactor_sq; + double th0, th1, th_arc; + int i, n_segs; + + sin_th = sin(angle * (M_PI / 180.0)); + cos_th = cos(angle * (M_PI / 180.0)); + + double dx; + + if(!relative) + dx = (curx - x) / 2.0; + else + dx = -x / 2.0; + + double dy; + + if(!relative) + dy = (cury - y) / 2.0; + else + dy = -y / 2.0; + + double _x1 = cos_th * dx + sin_th * dy; + double _y1 = -sin_th * dx + cos_th * dy; + double Pr1 = r1 * r1; + double Pr2 = r2 * r2; + double Px = _x1 * _x1; + double Py = _y1 * _y1; + + // Spec : check if radii are large enough + double check = Px / Pr1 + Py / Pr2; + if(check > 1) + { + r1 = r1 * sqrt(check); + r2 = r2 * sqrt(check); + } + + a00 = cos_th / r1; + a01 = sin_th / r1; + a10 = -sin_th / r2; + a11 = cos_th / r2; + + x0 = a00 * curx + a01 * cury; + y0 = a10 * curx + a11 * cury; + + if(!relative) + x1 = a00 * x + a01 * y; + else + x1 = a00 * (curx + x) + a01 * (cury + y); + + if(!relative) + y1 = a10 * x + a11 * y; + else + y1 = a10 * (curx + x) + a11 * (cury + y); + + /* (x0, y0) is current point in transformed coordinate space. + (x1, y1) is new point in transformed coordinate space. + + The arc fits a unit-radius circle in this space. + */ + + d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); + + sfactor_sq = 1.0 / d - 0.25; + + if(sfactor_sq < 0) + sfactor_sq = 0; + + sfactor = sqrt(sfactor_sq); + + if(sweepFlag == largeArcFlag) + sfactor = -sfactor; + + xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); + yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); + + /* (xc, yc) is center of the circle. */ + th0 = atan2(y0 - yc, x0 - xc); + th1 = atan2(y1 - yc, x1 - xc); + + th_arc = th1 - th0; + if(th_arc < 0 && sweepFlag) + th_arc += 2 * M_PI; + else if(th_arc > 0 && !sweepFlag) + th_arc -= 2 * M_PI; + + n_segs = (int) (int) ceil(fabs(th_arc / (M_PI * 0.5 + 0.001))); + + for(i = 0; i < n_segs; i++) + { + { + double sin_th, cos_th; + double a00, a01, a10, a11; + double x1, y1, x2, y2, x3, y3; + double t; + double th_half; + + double _th0 = th0 + i * th_arc / n_segs; + double _th1 = th0 + (i + 1) * th_arc / n_segs; + + sin_th = sin(angle * (M_PI / 180.0)); + cos_th = cos(angle * (M_PI / 180.0)); + + /* inverse transform compared with rsvg_path_arc */ + a00 = cos_th * r1; + a01 = -sin_th * r2; + a10 = sin_th * r1; + a11 = cos_th * r2; + + th_half = 0.5 * (_th1 - _th0); + t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); + x1 = xc + cos(_th0) - t * sin(_th0); + y1 = yc + sin(_th0) + t * cos(_th0); + x3 = xc + cos(_th1); + y3 = yc + sin(_th1); + x2 = x3 + t * sin(_th1); + y2 = y3 - t * cos(_th1); + + svgCurveToCubic( a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 ); + } + } + + if(!relative) + curx = x; + else + curx += x; + + if(!relative) + cury = y; + else + cury += y; +} + +void +SVGPathParser::svgLineToHorizontal( double, bool ) +{ +} + +void +SVGPathParser::svgLineToVertical( double, bool ) +{ +} + +void +SVGPathParser::svgCurveToCubicSmooth( double, double, double, double, bool ) +{ +} + +void +SVGPathParser::svgCurveToQuadratic( double, double, double, double, bool ) +{ +} + +void +SVGPathParser::svgCurveToQuadraticSmooth( double, double, bool ) +{ +} + +void +SVGPathParser::svgArcTo( double, double, double, double, double, bool, bool, bool ) +{ +} + diff --git a/lib/kopainter/svgpathparser.h b/lib/kopainter/svgpathparser.h new file mode 100644 index 00000000..00a23c81 --- /dev/null +++ b/lib/kopainter/svgpathparser.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2002, 2003 The Karbon Developers + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#ifndef __SVGPATHPARSER_H__ +#define __SVGPATHPARSER_H__ + +class QString; + +#include <koffice_export.h> +/** + * Parser for svg path data, contained in the d attribute. + * + * The parser delivers encountered commands and parameters by calling + * methods that correspond to those commands. Clients have to derive + * from this class and implement the abstract command methods. + * + * There are two operating modes. By default the parser just delivers unaltered + * svg path data commands and parameters. In the second mode, it will convert all + * relative coordinates to absolute ones, and convert all curves to cubic beziers. + */ +class KOPAINTER_EXPORT SVGPathParser +{ +public: + virtual ~SVGPathParser(){} + void parseSVG( const QString &d, bool process = false ); + +protected: + virtual void svgMoveTo( double x1, double y1, bool abs = true ) = 0; + virtual void svgLineTo( double x1, double y1, bool abs = true ) = 0; + virtual void svgLineToHorizontal( double x, bool abs = true ); + virtual void svgLineToVertical( double y, bool abs = true ); + virtual void svgCurveToCubic( double x1, double y1, double x2, double y2, double x, double y, bool abs = true ) = 0; + virtual void svgCurveToCubicSmooth( double x, double y, double x2, double y2, bool abs = true ); + virtual void svgCurveToQuadratic( double x, double y, double x1, double y1, bool abs = true ); + virtual void svgCurveToQuadraticSmooth( double x, double y, bool abs = true ); + virtual void svgArcTo( double x, double y, double r1, double r2, double angle, bool largeArcFlag, bool sweepFlag, bool abs = true ); + virtual void svgClosePath() = 0; + +private: + const char *getCoord( const char *, double & ); + void calculateArc( bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag ); +}; + +#endif |