diff --git a/libs/widgets/kis_color_input.cpp b/libs/widgets/kis_color_input.cpp index 916eb0557a..01b7b0dd74 100644 --- a/libs/widgets/kis_color_input.cpp +++ b/libs/widgets/kis_color_input.cpp @@ -1,418 +1,436 @@ /* * Copyright (c) 2008 Cyrille Berger * Copyright (c) 2011 Sven Langkamp * Copyright (c) 2015 Moritz Molch * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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_input.h" #include #ifdef HAVE_OPENEXR #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_double_parse_spin_box.h" #include "kis_int_parse_spin_box.h" KisColorInput::KisColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, bool usePercentage) : QWidget(parent), m_channelInfo(channelInfo), m_color(color), m_displayRenderer(displayRenderer), m_usePercentage(usePercentage) { } void KisColorInput::init() { QHBoxLayout* m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->setSpacing(1); QLabel* m_label = new QLabel(i18n("%1:", m_channelInfo->name()), this); m_layout->addWidget(m_label); m_colorSlider = new KoColorSlider(Qt::Horizontal, this, m_displayRenderer); m_colorSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); m_layout->addWidget(m_colorSlider); QWidget* m_input = createInput(); m_colorSlider->setFixedHeight(m_input->sizeHint().height()); m_layout->addWidget(m_input); } KisIntegerColorInput::KisIntegerColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, bool usePercentage) : KisColorInput(parent, channelInfo, color, displayRenderer, usePercentage) { init(); } void KisIntegerColorInput::setValue(int v) { quint8* data = m_color->data() + m_channelInfo->pos(); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: *(reinterpret_cast(data)) = v; break; case KoChannelInfo::UINT16: *(reinterpret_cast(data)) = v; break; case KoChannelInfo::UINT32: *(reinterpret_cast(data)) = v; break; default: Q_ASSERT(false); } emit(updated()); } void KisIntegerColorInput::update() { KoColor min = *m_color; KoColor max = *m_color; quint8* data = m_color->data() + m_channelInfo->pos(); quint8* dataMin = min.data() + m_channelInfo->pos(); quint8* dataMax = max.data() + m_channelInfo->pos(); m_intNumInput->blockSignals(true); m_colorSlider->blockSignals(true); switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 255.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFF); m_intNumInput->setValue(*(reinterpret_cast(data))); } m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFF; break; case KoChannelInfo::UINT16: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 65535.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFFFF); m_intNumInput->setValue(*(reinterpret_cast(data))); } m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFFFF; break; case KoChannelInfo::UINT32: if (m_usePercentage) { m_intNumInput->setMaximum(100); m_intNumInput->setValue(round(*(reinterpret_cast(data))*1.0 / 4294967295.0 * 100.0)); } else { m_intNumInput->setMaximum(0xFFFF); m_intNumInput->setValue(*(reinterpret_cast(data))); } m_colorSlider->setValue(*(reinterpret_cast(data))); *(reinterpret_cast(dataMin)) = 0x0; *(reinterpret_cast(dataMax)) = 0xFFFFFFFF; break; default: Q_ASSERT(false); } m_colorSlider->setColors(min, max); m_intNumInput->blockSignals(false); m_colorSlider->blockSignals(false); } QWidget* KisIntegerColorInput::createInput() { m_intNumInput = new KisIntParseSpinBox(this); m_intNumInput->setMinimum(0); m_colorSlider->setMinimum(0); if (m_usePercentage) { m_intNumInput->setSuffix(i18n("%")); } else { m_intNumInput->setSuffix(""); } switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFF); } m_colorSlider->setMaximum(0xFF); break; case KoChannelInfo::UINT16: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFFFF); } m_colorSlider->setMaximum(0xFFFF); break; case KoChannelInfo::UINT32: if (m_usePercentage) { m_intNumInput->setMaximum(100); } else { m_intNumInput->setMaximum(0xFFFFFFFF); } m_colorSlider->setMaximum(0xFFFFFFFF); break; default: Q_ASSERT(false); } connect(m_colorSlider, SIGNAL(valueChanged(int)), this, SLOT(onColorSliderChanged(int))); connect(m_intNumInput, SIGNAL(valueChanged(int)), this, SLOT(onNumInputChanged(int))); return m_intNumInput; } void KisIntegerColorInput::setPercentageWise(bool val) { m_usePercentage = val; if (m_usePercentage) { m_intNumInput->setSuffix(i18n("%")); } else { m_intNumInput->setSuffix(""); } } void KisIntegerColorInput::onColorSliderChanged(int val) { m_intNumInput->blockSignals(true); if (m_usePercentage) { switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_intNumInput->setValue(round((val*1.0) / 255.0 * 100.0)); break; case KoChannelInfo::UINT16: m_intNumInput->setValue(round((val*1.0) / 65535.0 * 100.0)); break; case KoChannelInfo::UINT32: m_intNumInput->setValue(round((val*1.0) / 4294967295.0 * 100.0)); break; default: Q_ASSERT(false); } } else { m_intNumInput->setValue(val); } m_intNumInput->blockSignals(false); setValue(val); } void KisIntegerColorInput::onNumInputChanged(int val) { m_colorSlider->blockSignals(true); if (m_usePercentage) { switch (m_channelInfo->channelValueType()) { case KoChannelInfo::UINT8: m_colorSlider->setValue((val*1.0)/100.0 * 255.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 255.0); break; case KoChannelInfo::UINT16: m_colorSlider->setValue((val*1.0)/100.0 * 65535.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 65535.0); break; case KoChannelInfo::UINT32: m_colorSlider->setValue((val*1.0)/100.0 * 4294967295.0); m_colorSlider->blockSignals(false); setValue((val*1.0)/100.0 * 4294967295.0); break; default: Q_ASSERT(false); } } else { m_colorSlider->setValue(val); m_colorSlider->blockSignals(false); setValue(val); } } KisFloatColorInput::KisFloatColorInput(QWidget* parent, const KoChannelInfo* channelInfo, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, bool usePercentage) : KisColorInput(parent, channelInfo, color, displayRenderer, usePercentage) { init(); } void KisFloatColorInput::setValue(double v) { quint8* data = m_color->data() + m_channelInfo->pos(); switch (m_channelInfo->channelValueType()) { #ifdef HAVE_OPENEXR case KoChannelInfo::FLOAT16: *(reinterpret_cast(data)) = v; break; #endif case KoChannelInfo::FLOAT32: *(reinterpret_cast(data)) = v; break; default: Q_ASSERT(false); } emit(updated()); } QWidget* KisFloatColorInput::createInput() { m_dblNumInput = new KisDoubleParseSpinBox(this); m_dblNumInput->setMinimum(0); m_dblNumInput->setMaximum(1.0); connect(m_colorSlider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); connect(m_dblNumInput, SIGNAL(valueChanged(double)), this, SLOT(setValue(double))); m_dblNumInput->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); m_dblNumInput->setMinimumWidth(60); m_dblNumInput->setMaximumWidth(60); + + quint8* data = m_color->data() + m_channelInfo->pos(); + qreal value = 1.0; + + switch (m_channelInfo->channelValueType()) { +#ifdef HAVE_OPENEXR + case KoChannelInfo::FLOAT16: + value = *(reinterpret_cast(data)); + break; +#endif + case KoChannelInfo::FLOAT32: + value = *(reinterpret_cast(data)); + break; + default: + Q_ASSERT(false); + } + m_dblNumInput->setValue(value); + return m_dblNumInput; } void KisFloatColorInput::sliderChanged(int i) { const qreal floatRange = m_maxValue - m_minValue; m_dblNumInput->setValue(m_minValue + (i / 255.0) * floatRange); } void KisFloatColorInput::update() { KoColor min = *m_color; KoColor max = *m_color; quint8* data = m_color->data() + m_channelInfo->pos(); quint8* dataMin = min.data() + m_channelInfo->pos(); quint8* dataMax = max.data() + m_channelInfo->pos(); qreal value = 1.0; m_minValue = m_displayRenderer->minVisibleFloatValue(m_channelInfo); m_maxValue = m_displayRenderer->maxVisibleFloatValue(m_channelInfo); m_colorSlider->blockSignals(true); switch (m_channelInfo->channelValueType()) { #ifdef HAVE_OPENEXR case KoChannelInfo::FLOAT16: value = *(reinterpret_cast(data)); m_minValue = qMin(value, m_minValue); m_maxValue = qMax(value, m_maxValue); *(reinterpret_cast(dataMin)) = m_minValue; *(reinterpret_cast(dataMax)) = m_maxValue; break; #endif case KoChannelInfo::FLOAT32: value = *(reinterpret_cast(data)); m_minValue = qMin(value, m_minValue); m_maxValue = qMax(value, m_maxValue); *(reinterpret_cast(dataMin)) = m_minValue; *(reinterpret_cast(dataMax)) = m_maxValue; break; default: Q_ASSERT(false); } m_dblNumInput->setMinimum(m_minValue); m_dblNumInput->setMaximum(m_maxValue); // ensure at least 3 significant digits are always shown int newPrecision = 2 + qMax(qreal(0.0), std::ceil(-std::log10(m_maxValue))); if (newPrecision != m_dblNumInput->decimals()) { m_dblNumInput->setDecimals(newPrecision); m_dblNumInput->updateGeometry(); } m_colorSlider->setColors(min, max); const qreal floatRange = m_maxValue - m_minValue; m_colorSlider->setValue((value - m_minValue) / floatRange * 255); m_colorSlider->blockSignals(false); } KisHexColorInput::KisHexColorInput(QWidget* parent, KoColor* color, KoColorDisplayRendererInterface *displayRenderer, bool usePercentage) : KisColorInput(parent, 0, color, displayRenderer, usePercentage) { QHBoxLayout* m_layout = new QHBoxLayout(this); m_layout->setContentsMargins(0,0,0,0); m_layout->setSpacing(1); QLabel* m_label = new QLabel(i18n("Color name:"), this); m_label->setMinimumWidth(50); m_layout->addWidget(m_label); QWidget* m_input = createInput(); m_input->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); m_layout->addWidget(m_input); } void KisHexColorInput::setValue() { QString valueString = m_hexInput->text(); valueString.remove(QChar('#')); QList channels = m_color->colorSpace()->channels(); channels = KoChannelInfo::displayOrderSorted(channels); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { Q_ASSERT(channel->channelValueType() == KoChannelInfo::UINT8); quint8* data = m_color->data() + channel->pos(); int value = valueString.left(2).toInt(0, 16); *(reinterpret_cast(data)) = value; valueString.remove(0, 2); } } emit(updated()); } void KisHexColorInput::update() { QString hexString("#"); QList channels = m_color->colorSpace()->channels(); channels = KoChannelInfo::displayOrderSorted(channels); Q_FOREACH (KoChannelInfo* channel, channels) { if (channel->channelType() == KoChannelInfo::COLOR) { Q_ASSERT(channel->channelValueType() == KoChannelInfo::UINT8); quint8* data = m_color->data() + channel->pos(); hexString.append(QString("%1").arg(*(reinterpret_cast(data)), 2, 16, QChar('0'))); } } m_hexInput->setText(hexString); } QWidget* KisHexColorInput::createInput() { m_hexInput = new QLineEdit(this); m_hexInput->setAlignment(Qt::AlignRight); int digits = 2*m_color->colorSpace()->colorChannelCount(); QString pattern = QString("#?[a-fA-F0-9]{%1,%2}").arg(digits).arg(digits); m_hexInput->setValidator(new QRegExpValidator(QRegExp(pattern), this)); connect(m_hexInput, SIGNAL(editingFinished()), this, SLOT(setValue())); return m_hexInput; }