Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit cf3c9a4f authored by Dmitry Kazakov's avatar Dmitry Kazakov

Delegate color correction in KisMinimanShadeSelector to a separate class

KisDisplayColorConverter is now in charge of all the color-related stuff
inside of the color selector.

Now it is only left to port other selectors to use it :)

CCBUG:288716
parent efa1fd79
......@@ -24,6 +24,7 @@ kis_color_selector_triangle.cpp
kis_color_selector_simple.cpp
kis_color_selector_wheel.cpp
kis_color_selector_combo_box.cpp
kis_color_selector_base_proxy.cpp
)
kde4_add_ui_files(KRITA_COLORSELECTORNG_PART_SRCS
......
/*
* Copyright (c) 2014 Dmitry Kazakov <dimula73@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 __KIS_ACS_TYPES_H
#define __KIS_ACS_TYPES_H
#include <QPoint>
#include <KoColor.h>
namespace Acs {
enum ColorRole {Foreground, Background};
inline ColorRole buttonToRole(Qt::MouseButton button) {
return button == Qt::LeftButton ? Acs::Foreground : Acs::Background;
}
template <class ResourceProvider>
void setCurrentColor(ResourceProvider *provider, ColorRole role, const KoColor &color) {
if (role == Acs::Foreground) {
provider->setFGColor(color);
} else {
provider->setBGColor(color);
}
}
template <class ResourceProvider>
KoColor currentColor(ResourceProvider *provider, ColorRole role) {
return role == Acs::Foreground ? provider->fgColor() : provider->bgColor();
}
template <class PaintDeviceSP>
KoColor pickColor(PaintDeviceSP device, const QPoint &pt) {
KoColor color;
(void) device->pixel(pt.x(), pt.y(), &color);
return color;
}
template <class PaintDeviceSP>
void setColor(PaintDeviceSP device, const QPoint &pt, const KoColor &color) {
(void) device->setPixel(pt.x(), pt.y(), &color);
}
}
#endif /* __KIS_ACS_TYPES_H */
......@@ -168,7 +168,7 @@ void KisColorPatches::mousePressEvent(QMouseEvent *event)
if(event->isAccepted())
return;
updateColorPreview(koColor.toQColor());
updateColorPreview(koColor);
if (event->button() == Qt::LeftButton)
m_dragStartPos = event->pos();
......
......@@ -33,8 +33,7 @@ public:
explicit KisColorPatches(QString configPrefix, QWidget *parent = 0);
enum Direction { Horizontal, Vertical };
void setColors(QList<KoColor> colors);
QList<KoColor> colors() const {return m_colors;}
virtual void setCanvas(KisCanvas2 *canvas) { m_canvas = canvas; }
virtual void unsetCanvas() { KisColorSelectorBase::unsetCanvas(); m_canvas = 0;}
......@@ -42,6 +41,9 @@ public slots:
void updateSettings();
protected:
void setColors(QList<KoColor> colors);
QList<KoColor> colors() const {return m_colors;}
void paintEvent(QPaintEvent *);
void wheelEvent(QWheelEvent *);
void resizeEvent(QResizeEvent *);
......
......@@ -221,13 +221,10 @@ void KisColorSelector::resizeEvent(QResizeEvent* e) {
}
}
}
if(m_canvas && m_canvas->resourceManager()) {
if (m_lastColorRole==Foreground) {
setColor(m_canvas->resourceManager()->foregroundColor().toQColor());
} else if (m_lastColorRole==Background) {
setColor(m_canvas->resourceManager()->backgroundColor().toQColor());
}
}
// reset the currect color after resizing the widget
setColor(m_lastColor);
KisColorSelectorBase::resizeEvent(e);
}
......@@ -263,14 +260,9 @@ void KisColorSelector::mouseReleaseEvent(QMouseEvent* e)
if(!e->isAccepted() &&
m_lastColor != m_currentColor &&
m_currentColor.isValid()) {
m_lastColor=m_currentColor;
if(e->button() == Qt::LeftButton)
{
m_lastColorRole=Foreground;}
else if (e->button() == Qt::RightButton)
{
m_lastColorRole=Background;}
m_lastColorRole = Acs::buttonToRole(e->button());
commitColor(KoColor(m_currentColor, colorSpace()), m_lastColorRole);
e->accept();
......@@ -303,15 +295,10 @@ void KisColorSelector::mouseEvent(QMouseEvent *e)
m_currentColor=m_mainComponent->currentColor();
KoColor kocolor(m_currentColor, colorSpace());
updateColorPreview(kocolor.toQColor());
if (e->buttons() & Qt::LeftButton) {
commitColor(kocolor, Foreground);
}
else if (e->buttons() & Qt::RightButton) {
commitColor(kocolor, Background);
}
updateColorPreview(kocolor);
Acs::ColorRole role = Acs::buttonToRole(e->button());
commitColor(kocolor, role);
}
}
......@@ -319,7 +306,7 @@ void KisColorSelector::init()
{
setAcceptDrops(true);
m_lastColorRole = Foreground;
m_lastColorRole = Acs::Foreground;
m_ring = new KisColorSelectorRing(this);
m_triangle = new KisColorSelectorTriangle(this);
m_slider = new KisColorSelectorSimple(this);
......
......@@ -132,7 +132,7 @@ private:
QColor m_lastColor;
QColor m_currentColor;
bool m_blipDisplay;
ColorRole m_lastColorRole;
Acs::ColorRole m_lastColorRole;
public:
......
......@@ -37,13 +37,15 @@
#include "kis_node.h"
#include "kis_view2.h"
#include "kis_image.h"
#include "kis_display_color_converter.h"
class KisColorPreviewPopup : public QWidget {
public:
KisColorPreviewPopup(KisColorSelectorBase* parent) : QWidget(), m_parent(parent)
{
setWindowFlags(Qt::ToolTip);
setColor(QColor(0,0,0));
setQColor(QColor(0,0,0));
setMouseTracking(true);
}
......@@ -70,7 +72,7 @@ public:
setGeometry(targetPos.x(), targetPos.y(), 100, 100);
}
void setColor(const QColor& color)
void setQColor(const QColor& color)
{
m_color = color;
update();
......@@ -195,9 +197,7 @@ void KisColorSelectorBase::mousePressEvent(QMouseEvent* event)
} else if (m_isPopup && event->button() == Qt::MidButton) {
hide();
} else {
if(m_colorPreviewPopup->isHidden()) {
m_colorPreviewPopup->show();
}
showColorPreview();
event->ignore();
}
}
......@@ -286,59 +286,15 @@ void KisColorSelectorBase::keyPressEvent(QKeyEvent *)
}
}
qreal distance(const QColor& c1, const QColor& c2)
{
qreal dr = c1.redF()-c2.redF();
qreal dg = c1.greenF()-c2.greenF();
qreal db = c1.blueF()-c2.blueF();
return sqrt(dr*dr+dg*dg+db*db);
}
inline bool inRange(qreal m) {
if(m>=0. && m<=1.) return true;
else return false;
}
inline bool modify(QColor* estimate, const QColor& target, const QColor& result)
{
qreal r = estimate->redF() - (result.redF() - target.redF());
qreal g = estimate->greenF() - (result.greenF() - target.greenF());
qreal b = estimate->blueF() - (result.blueF() - target.blueF());
if(inRange(r) && inRange(g) && inRange(b)) {
estimate->setRgbF(r, g, b);
return true;
}
else {
return false;
}
}
QColor KisColorSelectorBase::findGeneratingColor(const KoColor& ref) const
{
KoColor converter(colorSpace());
QColor currentEstimate;
ref.toQColor(&currentEstimate);
QColor currentResult;
converter.fromQColor(currentEstimate);
converter.toQColor(&currentResult);
QColor target;
ref.toQColor(&target);
KoColor color(ref);
QColor result;
bool estimateValid=true;
int iterationCounter=0;
color.convertTo(colorSpace());
color.toQColor(&result);
while(distance(target, currentResult)>0.001 && estimateValid && iterationCounter<100) {
estimateValid = modify(&currentEstimate, target, currentResult);
converter.fromQColor(currentEstimate);
converter.toQColor(&currentResult);
iterationCounter++;
}
return currentEstimate;
return result;
}
void KisColorSelectorBase::dragEnterEvent(QDragEnterEvent *e)
......@@ -362,9 +318,16 @@ void KisColorSelectorBase::dropEvent(QDropEvent *e)
}
KoColor kocolor(color , KoColorSpaceRegistry::instance()->rgb8());
color = findGeneratingColor(kocolor);
setColor(color);
commitColor(kocolor, Foreground);
updateColor(kocolor, Acs::Foreground, true);
}
void KisColorSelectorBase::updateColor(const KoColor &color, Acs::ColorRole role, bool needsExplicitColorReset)
{
commitColor(color, role);
if (needsExplicitColorReset) {
setKoColor(color);
}
}
void KisColorSelectorBase::setColor(const QColor& color)
......@@ -372,6 +335,11 @@ void KisColorSelectorBase::setColor(const QColor& color)
Q_UNUSED(color);
}
void KisColorSelectorBase::setKoColor(const KoColor& color)
{
setColor(color.toQColor());
}
void KisColorSelectorBase::setHidingTime(int time)
{
KIS_ASSERT_RECOVER_NOOP(m_isPopup);
......@@ -421,15 +389,14 @@ void KisColorSelectorBase::hidePopup()
hide();
}
void KisColorSelectorBase::commitColor(const KoColor& color, ColorRole role)
void KisColorSelectorBase::commitColor(const KoColor& color, Acs::ColorRole role)
{
if (!m_canvas)
return;
m_colorUpdateAllowed=false;
if (role == Foreground)
if (role == Acs::Foreground)
m_canvas->resourceManager()->setForegroundColor(color);
else
m_canvas->resourceManager()->setBackgroundColor(color);
......@@ -437,46 +404,68 @@ void KisColorSelectorBase::commitColor(const KoColor& color, ColorRole role)
m_colorUpdateAllowed=true;
}
void KisColorSelectorBase::updateColorPreview(const QColor& color)
void KisColorSelectorBase::showColorPreview()
{
m_colorPreviewPopup->setColor(color);
if(m_colorPreviewPopup->isHidden()) {
m_colorPreviewPopup->show();
}
}
void KisColorSelectorBase::updateColorPreview(const KoColor &color)
{
m_colorPreviewPopup->setQColor(converter()->toQColor(color));
}
void KisColorSelectorBase::canvasResourceChanged(int key, const QVariant &v)
{
if (key == KoCanvasResourceManager::ForegroundColor || key == KoCanvasResourceManager::BackgroundColor) {
QColor c = findGeneratingColor(v.value<KoColor>());
updateColorPreview(c);
KoColor realColor(v.value<KoColor>());
updateColorPreview(realColor);
if (m_colorUpdateAllowed && !m_colorUpdateSelf) {
setColor(c);
setKoColor(realColor);
}
}
}
const KoColorSpace* KisColorSelectorBase::colorSpace() const
const KoColorSpace* KisColorSelectorBase::fetchCorrectColorSpace() const
{
if (m_colorSpace != 0) {
return m_colorSpace;
}
else if (m_canvas && m_canvas->resourceManager()) {
const KoColorSpace* cs = 0;
if (m_canvas && m_canvas->resourceManager()) {
KisNodeSP currentNode = m_canvas->resourceManager()->
resource(KisCanvasResourceProvider::CurrentKritaNode).value<KisNodeSP>();
resource(KisCanvasResourceProvider::CurrentKritaNode).value<KisNodeSP>();
if (currentNode) {
m_colorSpace = currentNode->paintDevice() ?
cs = currentNode->paintDevice() ?
currentNode->paintDevice()->compositionSourceColorSpace() :
currentNode->colorSpace();
} else {
m_colorSpace=m_canvas->view()->image()->colorSpace();
cs = m_canvas->view()->image()->colorSpace();
}
return m_colorSpace;
}
return KoColorSpaceRegistry::instance()->rgb8(0);
if (!cs) {
cs = KoColorSpaceRegistry::instance()->rgb8();
}
return cs;
}
const KoColorSpace* KisColorSelectorBase::colorSpace() const
{
KIS_ASSERT_RECOVER(m_colorSpace) {
return KoColorSpaceRegistry::instance()->rgb8();
}
KIS_ASSERT_RECOVER_NOOP(*fetchCorrectColorSpace() == *m_colorSpace);
return m_colorSpace;
}
void KisColorSelectorBase::updateSettings()
{
if(m_popup!=0)
if(m_popup) {
m_popup->updateSettings();
}
KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector");
......@@ -491,11 +480,25 @@ void KisColorSelectorBase::updateSettings()
cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)"));
}
else {
m_colorSpace=0;
// the colorspace will be retrieved next time by calling colorSpace()
m_colorSpace = fetchCorrectColorSpace();
}
/**
* During initialization phase the canvas may not exist yet,
* just initialize the display profile into the default value
*/
const KoColorProfile *monitorProfile = m_canvas ?
m_canvas->view()->resourceProvider()->currentDisplayProfile() : 0;
m_colorConverter.reset(new KisDisplayColorConverter(m_colorSpace, monitorProfile, KisDisplayFilterSP()));
if(m_isPopup) {
resize(cfg.readEntry("zoomSize", 280), cfg.readEntry("zoomSize", 280));
}
}
KisDisplayColorConverter* KisColorSelectorBase::converter() const
{
KIS_ASSERT_RECOVER_NOOP(m_colorConverter);
return m_colorConverter.data();
}
......@@ -22,6 +22,7 @@
#include <QRgb>
#include <QPointer>
#include <kis_canvas2.h>
#include "kis_acs_types.h"
class QColor;
class KoColor;
......@@ -29,6 +30,8 @@ class QTimer;
class KoColorSpace;
class KisCanvas2;
class KisColorPreviewPopup;
class KisDisplayColorConverter;
/// Base class for all color selectors, that should support color management and zooming.
class KisColorSelectorBase : public QWidget
......@@ -44,20 +47,30 @@ public:
virtual void setCanvas(KisCanvas2* canvas);
virtual void unsetCanvas();
const KoColorSpace* colorSpace() const;
enum ColorRole {Foreground, Background};
KisDisplayColorConverter* converter() const;
public:
void updateColor(const KoColor &color, Acs::ColorRole role, bool needsExplicitColorReset);
void updateColorPreview(const KoColor &color);
void showColorPreview();
// FIXME: make private and use updateColor instead
virtual void setColor(const QColor& color);
virtual void setKoColor(const KoColor& color);
// FIXME: deprecate
QColor findGeneratingColor(const KoColor& ref) const;
public slots:
virtual void updateSettings();
virtual void setColor(const QColor& color);
virtual void showPopup(Move move=MoveToMousePosition);
//FIXME: make private and use updateColor instead
/// commits a color to the resource manager
void commitColor(const KoColor& koColor, ColorRole role);
void updateColorPreview(const QColor& color);
void commitColor(const KoColor& koColor, Acs::ColorRole role);
public:
/// finds a QColor, that will be ref.toQColor(), if converting it to the color space of ref
QColor findGeneratingColor(const KoColor& ref) const;
void enterEvent(QEvent *e);
void leaveEvent(QEvent *e);
......@@ -80,6 +93,7 @@ protected slots:
private:
void lazyCreatePopup();
const KoColorSpace* fetchCorrectColorSpace() const;
protected:
QPointer<KisCanvas2> m_canvas;
......@@ -95,6 +109,8 @@ private:
mutable const KoColorSpace* m_colorSpace;
bool m_isPopup; //this instance is a popup
KisColorPreviewPopup* m_colorPreviewPopup;
QScopedPointer<KisDisplayColorConverter> m_colorConverter;
};
#endif
/*
* Copyright (c) 2014 Dmitry Kazakov <dimula73@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 "kis_color_selector_base_proxy.h"
#include "KoColorSpaceRegistry.h"
#include "kis_color_selector_base.h"
#include "kis_display_color_converter.h"
/************* KisColorSelectorBaseProxy *******************************/
KisColorSelectorBaseProxy::~KisColorSelectorBaseProxy()
{
}
/************* KisColorSelectorBaseProxyNoop ***************************/
KisColorSelectorBaseProxyNoop::KisColorSelectorBaseProxyNoop()
: m_converter(
new KisDisplayColorConverter(
KoColorSpaceRegistry::instance()->rgb8(), 0, KisDisplayFilterSP(0)))
{
}
KisColorSelectorBaseProxyNoop::~KisColorSelectorBaseProxyNoop()
{
}
const KoColorSpace* KisColorSelectorBaseProxyNoop::colorSpace() const
{
return KoColorSpaceRegistry::instance()->rgb8();
}
KisDisplayColorConverter* KisColorSelectorBaseProxyNoop::converter() const
{
return m_converter.data();
}
/************* KisColorSelectorBaseProxyObject *************************/
KisColorSelectorBaseProxyObject::KisColorSelectorBaseProxyObject(KisColorSelectorBase *parent)
: m_parent(parent)
{
}
const KoColorSpace* KisColorSelectorBaseProxyObject::colorSpace() const
{
return m_parent->colorSpace();
}
void KisColorSelectorBaseProxyObject::showColorPreview()
{
m_parent->showColorPreview();
}
void KisColorSelectorBaseProxyObject::updateColorPreview(const KoColor &color)
{
m_parent->updateColorPreview(color);
}
void KisColorSelectorBaseProxyObject::updateColor(const KoColor &color, Acs::ColorRole role, bool needsExplicitColorReset)
{
m_parent->updateColor(color, role, needsExplicitColorReset);
}
KisDisplayColorConverter* KisColorSelectorBaseProxyObject::converter() const
{
return m_parent->converter();
}
/*
* Copyright (c) 2014 Dmitry Kazakov <dimula73@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 __KIS_COLOR_SELECTOR_BASE_PROXY_H
#define __KIS_COLOR_SELECTOR_BASE_PROXY_H
#include "kis_acs_types.h"
class KoColor;
class KoColorSpace;
class KisDisplayColorConverter;
/**
* A proxy interface for accessing high-level KisColorSelectorBase
* structure by lower level classes.
*
* This small abstractions makes the interface clear and hides all the
* non-relevant features from the clients
*/
class KisColorSelectorBaseProxy
{
public:
virtual ~KisColorSelectorBaseProxy();